使用 Mirror
以下是一种纯 Swift 解决方案,但有一些限制:
protocol PropertyNames {
func propertyNames() -> [String]
}
extension PropertyNames
{
func propertyNames() -> [String] {
return Mirror(reflecting: self).children.flatMap { $0.label }
}
}
class Person : PropertyNames {
var name = "Sansa Stark"
var awesome = true
}
Person().propertyNames()
限制:
- Returns an empty array for Objective-C objects
Will not return computed properties, i.e.:
var favoriteFood: String { return "Lemon Cake" }
If self
is an instance of a class (vs., say, a struct), this doesn't report its superclass's properties, i.e.:
class Person : PropertyNames {
var name = "Bruce Wayne"
}
class Superhero : Person {
var hasSuperpowers = true
}
Superhero().propertyNames()
You could work around this using superclassMirror()
depending on your desired behavior.
使用 class_copyPropertyList
如果你正在使用 Objective-C 对象,你可以使用以下方法:
var count = UInt32()
let classToInspect = NSURL.self
let properties : UnsafeMutablePointer <objc_property_t> = class_copyPropertyList(classToInspect, &count)
var propertyNames = [String]()
let intCount = Int(count)
for var i = 0; i < intCount; i++ {
let property : objc_property_t = properties[i]
guard let propertyName = NSString(UTF8String: property_getName(property)) as? String else {
debugPrint("Couldn't unwrap property name for \(property)")
break
}
propertyNames.append(propertyName)
}
free(properties)
print(propertyNames)
如果
classToInspect
是
NSURL
,则控制台的输出为:
["pathComponents", "lastPathComponent", "pathExtension", "URLByDeletingLastPathComponent", "URLByDeletingPathExtension", "URLByStandardizingPath", "URLByResolvingSymlinksInPath", "dataRepresentation", "absoluteString", "relativeString", "baseURL", "absoluteURL", "scheme", "resourceSpecifier", "host", "port", "user", "password", "path", "fragment", "parameterString", "query", "relativePath", "hasDirectoryPath", "fileSystemRepresentation", "fileURL", "standardizedURL", "filePathURL"]
这在playground中不起作用。只需将
NSURL
替换为
EachDayCell
(或重用相同的逻辑作为扩展)即可正常工作。
self
是一个类,你将无法获得超类的属性。然而在你的例子中,self
从未是一个类,因为1)propertyKeys
不是一个类方法,所以 self 总是指向一个实例;2)你在Superhero().propertyKeys()
上调用它,而不是Superhero.propertyKeys()
。 - barndogself
是类的实例时(相对于结构体等其他情况)。 - Aaron Brager