类的属性列表在swift中
注意:在这里有针对客观的c发布的类似问题,但是我想快速实现它。
我有一个像这样快速声明的类:
import UIKit class EachDayCell : UITableViewCell { @IBOutlet var dateDisplayLabel : UITextField @IBOutlet var nameDisplayLabel : UITextField @IBAction func goToPendingItems(sender : AnyObject) { } @IBAction func showDateSelectionPicker(sender : AnyObject) { } init(style: UITableViewCellStyle, reuseIdentifier: String!) { super.init(style: style, reuseIdentifier: reuseIdentifier) } }
现在我想要在swift中获得一个数组:dateDisplayLabel,nameDisplayLabel。
我怎样才能做到这一点?
使用Mirror
这是一个纯粹的Swift解决scheme,但有一些限制:
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() // ["name", "awesome"]
限制:
- 返回Objective-C对象的空数组
-
不会返回计算的属性,即:
var favoriteFood: String { return "Lemon Cake" }
-
如果
self
是一个类的实例(比如说一个结构体),那么它不会报告它的父类的属性,即:class Person : PropertyNames { var name = "Bruce Wayne" } class Superhero : Person { var hasSuperpowers = true } Superhero().propertyNames() // ["hasSuperpowers"] — no "name"
你可以使用
superclassMirror()
根据你想要的行为来解决这个问题。
使用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"]
这不会在操场上工作。 只需将NSURL
replace为EachDayCell
(或重复使用与扩展相同的逻辑)即可。
这是另一个版本,我觉得这很简单纯粹。
Swift 2.0
protocol Reflectable { func properties()->[String] } extension Reflectable { func properties()->[String]{ var s = [String]() for c in Mirror(reflecting: self).children { if let name = c.label{ s.append(name) } } return s } } class Test:Reflectable { var name99:String = "" var name3:String = "" var name2:String = "" } Test().properties()
Swift 1.2
class Reflect:NSObject { func properties()->[String] { let m = reflect(self) var s = [String]() for i in 0..<m.count { let (name,_) = m[i] if name == "super"{continue} s.append(name) } return s } } class Test:Reflect { var name99:String = "" var name3:String = "" var name2:String = "" } Test().properties()
Swift 3.1
let contorller = UIActivityViewController(activityItems: [url], applicationActivities: nil) var count: UInt32 = 0 guard let properties = class_copyPropertyList(object_getClass(contorller), &count) else { return } for index in 0...count { let property1 = property_getName(properties[Int(index)]) let result1 = String(cString: property1!) print(result1) }