项目修改的过程中出现一个自定义模型传值问题导致的bug,现记录一下方便以防以后再次出现同样的问题。
两个界面A,B(A页面push到B页面)同时将A的model传递到下一个页面,直接使用 B.model = model;
这样的话,A和B的model是同一块内存,会出现当在B修改了model后,A的model也随之改变,这样从B返回到A页面的时候会出现model值被改变的问题。
可以注意到两个model指向同一个地址, 因此解决办法可以想到copy出一份model然后再传给B。
- (id)copyWithZone:(NSZone *)zone {
TestModel * model = [[self class] allocWithZone:zone];
model.name = _name.copy;
return model;
}
但是项目中自定义的模型有很多,如果一个一个属性进行赋值,这样很不方便,不适合向我这样爱偷懒的,于是想有没有其他取巧方法。通过查询一些资料得知,可以采用runtime动态修改模型值来入手,于是出现了如下解决方案。
要在自定义模型里添加如下代码,当然不要忘记遵守< NSCopying >协议
- (id)copyWithZone:(NSZone *)zone {
TestModel *model = [[TestModel allocWithZone:zone] init];
unsigned int count = 0;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (int i = 0; i<count; i++) {
objc_property_t property = properties[i];
const char *name = property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:name];
id value = [self valueForKey:propertyName];
if (value) {
[model setValue:value forKey:propertyName];
}
}
free(properties);
return model;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
TestModel *model = [[TestModel allocWithZone:zone] init];
unsigned int count = 0;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for (int i = 0; i<count; i++) {
objc_property_t property = properties[i];
const char *name = property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:name];
id value = [self valueForKey:propertyName];
if (value) {
[model setValue:value forKey:propertyName];
}
}
free(properties);
return model;
}
解决方法再升级
注意到我们的项目中使用了YYModel,因此我们也可以采用如下方法解决
- (id)copyWithZone:(NSZone *)zone {
return [self yy_modelCopy];
}
在控制器里使用
好了,这个问题到此就解决了。