Skip to main content
 首页 » 操作系统

serialization之获取 Swift 类的属性列表

2024年01月01日47pander-it

我正在尝试获取 swift 类的属性列表。还有一个类似的问题here和 here .除了某些类型不会从 class_copyPropertyList 返回外,我的一切正常。到目前为止,我测试过的是 Int? 和枚举。我在下面有一个我正在尝试的示例类。

enum PKApiErrorCode: Int { 
    case None = 0 
    case InvalidSignature = 1 
    case MissingRequired = 2 
    case NotLoggedIn = 3 
    case InvalidApiKey = 4 
    case InvalidLogin = 5 
    case RegisterFailed = 6 
} 
 
class ApiError: Serializable { 
    let code: PKApiErrorCode? 
    let message: String? 
    let userMessage: String? 
 
    init(error: JSONDictionary) { 
        code = error["errorCode"] >>> { (object: JSON) -> PKApiErrorCode? in 
            if let c = object >>> JSONInt { 
                return PKApiErrorCode.fromRaw(c) 
            } 
 
            return nil 
        } 
 
        message = error["message"] >>> JSONString 
        userMessage = error["userMessage"] >>> JSONString 
    } 
} 

Serializable 类(在 https://gist.github.com/turowicz/e7746a9c035356f9483d 的帮助下)

public class Serializable: NSObject, Printable { 
    override public var description: String { 
        return "\(self.toDictionary())" 
    } 
} 
 
extension Serializable { 
     public func toDictionary() -> NSDictionary { 
        var aClass : AnyClass? = self.dynamicType 
        var propertiesCount : CUnsignedInt = 0 
        let propertiesInAClass : UnsafeMutablePointer<objc_property_t> = class_copyPropertyList(aClass, &propertiesCount) 
        var propertiesDictionary : NSMutableDictionary = NSMutableDictionary() 
        for var i = 0; i < Int(propertiesCount); i++ { 
 
            var property = propertiesInAClass[i] 
            var propName = NSString(CString: property_getName(property), encoding: NSUTF8StringEncoding) 
            var propType = property_getAttributes(property) 
            var propValue : AnyObject! = self.valueForKey(propName); 
            if propValue is Serializable { 
                propertiesDictionary.setValue((propValue as Serializable).toDictionary(), forKey: propName) 
            } else if propValue is Array<Serializable> { 
                var subArray = Array<NSDictionary>() 
                for item in (propValue as Array<Serializable>) { 
                    subArray.append(item.toDictionary()) 
                } 
                propertiesDictionary.setValue(subArray, forKey: propName) 
            } else if propValue is NSData { 
                propertiesDictionary.setValue((propValue as NSData).base64EncodedStringWithOptions(nil), forKey: propName) 
            } else if propValue is Bool { 
                propertiesDictionary.setValue((propValue as Bool).boolValue, forKey: propName) 
            } else if propValue is NSDate { 
                var date = propValue as NSDate 
                let dateFormatter = NSDateFormatter() 
                dateFormatter.dateFormat = "Z" 
                var dateString = NSString(format: "/Date(%.0f000%@)/", date.timeIntervalSince1970, dateFormatter.stringFromDate(date)) 
                propertiesDictionary.setValue(dateString, forKey: propName) 
 
            } else { 
                propertiesDictionary.setValue(propValue, forKey: propName) 
            } 
        } 
 
        return propertiesDictionary 
    } 
 
    public func toJSON() -> NSData! { 
        var dictionary = self.toDictionary() 
        var err: NSError? 
        return NSJSONSerialization.dataWithJSONObject(dictionary, options:NSJSONWritingOptions(0), error: &err) 
    } 
 
    public func toJSONString() -> NSString! { 
        return NSString(data: self.toJSON(), encoding: NSUTF8StringEncoding) 
    } 
} 

String 似乎只在 Optionals 是有效值时出现,而 code 如果它是枚举或 Int 则永远不会出现在对象上,除非 Int 具有默认值。

感谢您提供有关获取类的所有属性(无论它们是什么)的任何建议。

请您参考如下方法:

我在苹果开发者论坛上收到了关于这个问题的回复:

“class_copyPropertyList 仅显示暴露给 Objective-C 运行时的属性。Objective-C 不能表示 Swift 枚举或非引用类型的可选值,因此这些属性不会暴露给 Objective-C 运行时。”

Source

因此,总而言之,目前无法使用这种方法序列化为 JSON。您可能需要考虑使用其他模式来完成此操作,例如将序列化任务分配给每个对象,或者可能使用 reflect() method将对象序列化为 JSON。