Swift中如何通过#KeyPath获取类/结构体的变量或方法名?
Hey there! Let's sort out how to grab those property or method names that include "Bar" in Swift. You mentioned trying both Swift 3's #keyPath and Swift 4's simplified approach without luck, so I'll break down working examples for both versions below.
Swift 4 made key paths far more flexible, and you can directly convert them to strings using String(describing:). Plus, if you need to find all members (properties/methods) containing "Bar", we can use Mirror to inspect the type's members.
Example Code
First, let's define a sample struct with "Bar"-related members:
struct Foo { var barProperty: String var anotherBar: Int func barMethod() {} func unrelatedMethod() {} }
Get a Single Member's Name
For a specific property or method, use a key path and convert it to a string:
// Get property name let barPropertyKey = \Foo.barProperty let barPropertyName = String(describing: barPropertyKey) // Result: "barProperty" // Get method name let barMethodKey = \Foo.barMethod let barMethodName = String(describing: barMethodKey) // Result: "barMethod()"
Filter All Members Containing "Bar"
If you need to find every member with "Bar" (case-insensitive check included here), use Mirror to iterate over the type's children:
let fooInstance = Foo(barProperty: "test", anotherBar: 42) let mirror = Mirror(reflecting: fooInstance) // Filter for names containing "Bar" (case-insensitive) let barRelatedNames = mirror.children.compactMap { child -> String? in guard let label = child.label else { return nil } return label.lowercased().contains("bar") ? label : nil } print(barRelatedNames) // Output: ["barProperty", "anotherBar"]
In Swift 3, you use the #keyPath directive to get member names as strings. Note that this requires explicitly referencing each member (you can't automatically enumerate them with just #keyPath, so we still use Mirror for bulk filtering).
Example Code
struct Foo { var barProperty: String var anotherBar: Int func barMethod() {} } // Get single property name let barPropertyName = #keyPath(Foo.barProperty) // Result: "barProperty" // Get single method name let barMethodName = #keyPath(Foo.barMethod) // Result: "barMethod" // Filter all "Bar"-related members let fooInstance = Foo(barProperty: "test", anotherBar: 42) let mirror = Mirror(reflecting: fooInstance) let barRelatedNames = mirror.children.flatMap { $0.label }.filter { $0.lowercased().contains("bar") } print(barRelatedNames) // Output: ["barProperty", "anotherBar"]
Common Pitfalls to Check
- Case Sensitivity: Swift is case-sensitive! If your members use lowercase
barbut you're looking for uppercaseBar, make sure to use a case-insensitive check (likelowercased().contains("bar")). - Method Key Paths: For methods, ensure you're referencing the method correctly (no parentheses in the key path, e.g.,
\Foo.barMethodnot\Foo.barMethod()). - Mirror Limitations:
Mirroronly inspects public members by default. If your members are private, they won't show up in the mirror results.
内容的提问来源于stack exchange,提问作者Steve

