Swift和Objective-C的runtime的差異

最近寫swift的時候,用到了一些運行時的東西,但是有部分與oc還是有差異的,得不到想要的東西,於是記錄一下目前自己遇到的兩者之間的差別。


  1. ivar_getTypeEncoding
    在swift中,我用這個函數,就是得不到一個對象屬性的類型。
首先定義了一個Person類作爲測試
/******************這是swift*********************/
class Person: NSObject {
    var name = "123"
    var age = 18
    var color = UIColor.white
}

var count: UInt32 = 0
let ivars = class_copyIvarList(Person.self, &count)
for i in 0..<Int(count) {
    let ivar = ivars![i]
    let name = String(utf8String: ivar_getName(ivar)!)
    let type = String(utf8String: ivar_getTypeEncoding(ivar)!)
    print(name, type)
}

//輸出結果如下:swift中拿不到對象的屬性的類型。
Optional("name") Optional("")
Optional("age") Optional("")
Optional("color") Optional("")

/******************這是objective-c*********************/
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, strong) UIColor *color;
@end

unsigned int count = 0;
Ivar *ivars = class_copyIvarList([Person class], &count);
for (int i = 0; i < (int)count; i++) {
   Ivar ivar = ivars[i];
   const char *cName = ivar_getName(ivar);
   const char *cType = ivar_getTypeEncoding(ivar);
   NSString *name = [NSString stringWithUTF8String:cName];
   NSString *type = [NSString stringWithUTF8String:cType];
   NSLog(@"name = %@, type = %@", name, type);
}

//輸出結果如下:oc中是都可以拿到屬性的類型的。
name = _age, type = i
name = _name, type = @"NSString"
name = _color, type = @"UIColor"

可以看出,在swift中已經拿不到一個對象屬性的類型了。


  1. object_setIvar
    這個方法在swift中現在只有給類申明的變量設置值纔有效,其他的都無效。
/******************這是swift*********************/
class func modelWithDic(_ dic: [String: Any]) -> Any {
    let obj = self.init()
    for (key, value) in dic {
        guard let ivar = class_getInstanceVariable(self, key) else {
            continue
        }
        object_setIvar(obj, ivar, value)
    }
    return obj
}

let p = Person.modelWithDic(["name": "swift", "age": 25 ,"color": UIColor.blue]) as! Person
print(p.name, p.age, p.color)

//打印結果如下:可以看出,用String、Int定義的變量,設置的值是無效的,他們在swift中類型都是結構體,而用類定義的變量,設置的值是有效的。
\220r$ -5764607523034234477 UIExtendedSRGBColorSpace 0 0 1 1


/******************這是objective-c*********************/
+ (instancetype)modelWithDic:(NSDictionary *)dic {
    id obj = [[self alloc] init];
    [dic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull value, BOOL * _Nonnull stop) {
        NSString *ivarKey = [NSString stringWithFormat:@"_%@", key];
        Ivar ivar = class_getInstanceVariable([self class], [ivarKey cStringUsingEncoding:NSUTF8StringEncoding]);
        if (ivar != nil) {
            object_setIvar(obj, ivar, value);
        }
    }];
    return obj;
}


Person *p = [Person modelWithDic:@{@"name": @"oc", @"age": @10, @"color": [UIColor blueColor]}];
NSLog(@"name = %@, age = %d, color = %@", p.name, p.age, p.color);

//運行結果如下:可以看出,oc中是全部可以設置值的。
name = oc, age = 162, color = UIExtendedSRGBColorSpace 0 0 1 1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章