in Objective-C, I am using following codes to serialise a custom class to a dictionary which working fine. In order to being familiar to Swift, porting Objective-C codes to Swift. However I couldn’t achieve this one, how do I make this with Swift?
this is how I achieve with 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
when I wrote same code in swift i couldn’t manage to find out equivalent of [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()
}
}
so far i have tried:
let aClass = self.classForCoder
var propertiesCount : u_int
let propertiesInAClass : objc_property_t = class_copyPropertyList(aClass, &propertiesCount)
and
let aClass : AnyClass! = self.classForCoder()
no success, still same compiler error "Could not find an overload for '__conversion' that accepts the supplied arguments"
regarding to answers below I found this solution and it worked. Basically I have created extension for my class.
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
}
}
now this let myclazz = myClass().toDictionary()
gives me the NSDictionary. all suggestions are welcome.
This is how I implemented deep serialization.
If property is DictionarySerializedObject
then it's recursively serialized.
Be careful because class_copyPropertyList()
does not return properties of optional Swift types like Bool?
, [String?]
because Foundation does not provide bridges for them. For example it provides bridge for Bool
to NSNumber
but does not provide bridge for 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()
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With