在Objective-C中,我使用以下代码将自定义类序列化为一个工作正常的字典。为了熟悉Swift,将Objective-C代码移植到Swift。但是我无法实现这一点,我如何使用Swift实现这一点?
这就是我用Objective-C实现的方式
.h
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface NSObject (aClass_NSDictionary)
- (NSDictionary *)NSDictionaryFromClass;
@end
.m
@implementation NSObject (aClass_NSDictionary)
- (NSDictionary *)NSDictionaryFromClass {
Class aClass = [self class];
u_int propertiesCount;
objc_property_t *propertiesInAClass = class_copyPropertyList(aClass, &propertiesCount);
NSMutableDictionary *propertiesDictionary = [[NSMutableDictionary alloc] initWithCapacity:propertiesCount];
for (int i = 0; i < propertiesCount; i++)
{
NSString *strAKey = [NSString stringWithCString:property_getName(propertiesInAClass[i])
encoding:NSUTF8StringEncoding];
[propertiesDictionary setValue:[self valueForKey:strAKey]
forKey:strAKey];
}
free(propertiesInAClass);
return propertiesDictionary;
}
@end
当我在swift中编写相同的代码时,我无法找到相当于[self class]
的内容。
class class2dicti : NSObject {
class func nsdictionaryFromAClass() -> NSDictionary {
let aClass = self.classForCoder
var propertiesCount : u_int
let propertiesInAClass : objc_property_t = class_copyPropertyList(aClass, &propertiesCount)
//return NSDictionary()
}
}
let aClass = self.classForCoder
var propertiesCount : u_int
let propertiesInAClass : objc_property_t = class_copyPropertyList(aClass, &propertiesCount)
和
let aClass : AnyClass! = self.classForCoder()
没有成功,仍然是相同的编译器错误&#34;无法找到&#39; __转换的过载&#39;接受提供的参数&#34;
关于下面的答案,我找到了这个解决方案并且有效。基本上我已经为我的班级创建了扩展。
class myClass : NSObject {
var propertyOne = "prop One"
var propertyTwo = [1, 2, 3]
var propertyThree = ["A":1, "B":2, "C":3]
}
extension myClass {
func toDictionary() -> NSDictionary {
var aClass : AnyClass? = self.dynamicType
var propertiesCount : CUnsignedInt = 0
let propertiesInAClass : UnsafePointer<objc_property_t> = class_copyPropertyList(aClass, &propertiesCount)
var propertiesDictionary : NSMutableDictionary = NSMutableDictionary()
for var i = 0; i < Int(propertiesCount); i++ {
var strKey : NSString? = NSString(CString: property_getName(propertiesInAClass[i]), encoding: NSUTF8StringEncoding)
propertiesDictionary.setValue(self.valueForKey(strKey), forKey: strKey)
}
return propertiesDictionary
}
}
现在这个let myclazz = myClass().toDictionary()
给了我NSDictionary。欢迎提出所有建议。
答案 0 :(得分:2)
这是我实现深度序列化的方法。
如果属性为DictionarySerializedObject
,那么它将被递归序列化。
要小心,因为class_copyPropertyList()
不返回Bool?
,[String?]
等可选Swift类型的属性,因为Foundation不为它们提供桥接。例如,它为Bool
提供了NSNumber
的桥梁,但没有为Bool?
提供桥梁。
import Foundation
protocol DictionarySerializable {
func serializeToDictionary() -> [String:AnyObject]
}
class DictionarySerializableObject: NSObject {
}
extension NSObject: DictionarySerializable {
func serializeToDictionary() -> [String:AnyObject] {
var aClass: AnyClass? = self.dynamicType
var propertiesCount: CUnsignedInt = 0
let properties = class_copyPropertyList(aClass, &propertiesCount)
var dictionary = [String: AnyObject]()
for var i = 0; i < Int(propertiesCount); i++ {
if let name = NSString(CString: property_getName(properties[i]), encoding: NSUTF8StringEncoding) as? String {
dictionary[name] = getDictionaryValueForObject(self.valueForKey(name))
}
}
free(properties)
return dictionary
}
private func getDictionaryValueForObject(object: AnyObject?) -> AnyObject {
if let object: AnyObject = object {
if let object = object as? DictionarySerializableObject {
return object.serializeToDictionary()
} else if let object = object as? [AnyObject] {
var array = [AnyObject]()
for item in object {
array.append(getDictionaryValueForObject(item))
}
return array
} else if let object = object as? NSData {
return object.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(0))
} else {
return object
}
} else {
return NSNull()
}
}
}
答案 1 :(得分:1)
在Swift中,你从不使用类。您使用类型:
var clazz: AnyClass? = self.dynamicType
class_copyPropertyList(clazz, nil)
返回Class
的所有Obj-C方法,例如更新classForCoder
以返回Swift类型(AnyClass
)。
请注意,您还有其他类型问题:
var propertiesCount : CUnsignedInt = 0
let propertiesInAClass : UnsafePointer<objc_property_t> = class_copyPropertyList(clazz, &propertiesCount)
如果您确实需要以AnyObject
的形式访问Obj-C类,例如创建一个类数组并将其传递给Obj-C,请参阅this
答案 2 :(得分:0)
我正在使用这种方式归档符合NSCoding
协议的任何内容。
首先我获取该文件夹的URL,例如Documents
文件夹:
var error: NSError?
let documentURL : NSURL = NSFileManager.defaultManager().URLForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomain: NSSearchPathDomainMask.UserDomainMask, appropriateForURL: nil, create: true, error: &error)
然后我将其存档到该文件夹中:
let object: AnyObject = // ...
let filename: String = "<filename>"
let customExtension: String = "<extension>"
let urlForFile: NSURL = documentURL.URLByAppendingPathComponent(filename).URLByAppendingPathExtension(customExtension)
let result: Bool = NSKeyedArchiver.archivedDataWithRootObject(object).writeToURL(urlForFile, atomically: true)
以后取消归档与最近的方式非常相似:
let data: NSData = NSData.dataWithContentsOfFile(urlForFile.path, options: NSDataReadingOptions.DataReadingUncached, error: &error)
let object: AnyObject = NSKeyedUnarchiver.unarchiveObjectWithData(data)
注意:这是一个原始示例,不检查是否 nil
或处理可能的错误。您可能需要为最终代码添加这些内容。
答案 3 :(得分:0)
我编写了一个目标c库,它根据键值和属性名称自动执行此操作。我有一个支持Swift类的分支,它运行良好。 https://github.com/aryaxt/OCMapper