类的属性列表在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) 

如果classToInspectNSURL则输出到控制台:

["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"]

这不会在操场上工作。 只需将NSURLreplace为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) }