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()
}
}
Update
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"
Solution
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.
I'm using this way archiving anything which conforms the
NSCoding
protocol.first I get the URL for the folder, like e.g.
Documents
folder:then I archive it into that folder:
and unarchiving later is quite similar to the recent way:
NOTE: that is a raw example, without checking anything whether or not it is
nil
or handling the possible error. you may need to add those for your final code.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 likeBool?
,[String?]
because Foundation does not provide bridges for them. For example it provides bridge forBool
toNSNumber
but does not provide bridge forBool?
.In Swift you never work with classes. You work with types:
All Obj-C methods that return a
Class
, e.g.classForCoder
are updated to return a Swift type instead (AnyClass
).Note that you have other type problems there:
If you actually need to access the Obj-C class as
AnyObject
, for example to create an array of classes and pass it to Obj-C, see thisI have written an objective c library that automatically does this based on key values and property names. I have a branch to support Swift classes and it works well. https://github.com/aryaxt/OCMapper