- (void)qy_clearPropertyValue {
// 1.存储属性的个数
unsigned int propertyCount = 0;
// 2.通过运行时获取当前类的所有属性
objc_property_t *properties = class_copyPropertyList([self class], &propertyCount);
// 3.遍历属性
for (int i = 0; i < propertyCount; i ++) {
objc_property_t property = properties[i];
NSString *propertyName = [NSString stringWithFormat:@"%s", property_getName(property)];
// 4.利用KVC 设置属性nil
[self setValue:nil forKey:propertyName];
}
// 释放指针
free(properties);
}
但是上面代码有一个重大bug:
当对象里面的属性不是对象属性时(例如NSInteger CGFloat等),程序会崩溃,控制台报错:could not set nil as the value for the key
解决办法:
-
第一种:重写setNilValueForKey:方法,逐个属性判断
-
第二种:异常捕捉,统一处理
- (void)setNilValueForKey:(NSString *)key {
if ([key isEqualToString:@"属性名1"]) {
_属性1 = 0;
} else if ([key isEqualToString:@"属性名2"]) {
_属性1 = 0;
}
...
...
...
else {
[super setNilValueForKey:key];
}
}
最优雅的写法应该是:
- (void)qy_clearPropertyValue {
// 1.存储属性的个数
unsigned int propertyCount = 0;
// 2.通过运行时获取当前类的所有属性
objc_property_t *properties = class_copyPropertyList([self class], &propertyCount);
// 3.遍历属性
for (int i = 0; i < propertyCount; i ++) {
objc_property_t property = properties[i];
NSString *propertyName = [NSString stringWithFormat:@"%s", property_getName(property)];
// 4.利用KVC 设置属性nil
@try {
[self setValue:nil forKey:propertyName];
} @catch (NSException *exception) {
[self setValue:@0 forKey:propertyName];
} @finally {
//
}
}
// 释放指针
free(properties);
}
PS:诡异的死锁Bug:
#pragma mark - 退出登录
- (void)loginOut {
UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:nil message:@"您真的要退出吗?" preferredStyle:UIAlertControllerStyleAlert];
[alertVc addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil]];
[alertVc addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// 下面👇 这一行执行会有死锁的bug, app会卡主,处于假死状态
[[QYMyInfoModel sharedMyInfoModel] qy_clearPropertyValue];
}]];
[self presentViewController:alertVc animated:YES completion:nil];
}
但是,把那句代码放到异步线程执行,就不会死锁,不知道什么原因,如果有人知道,麻烦告知一下
#pragma mark - 退出登录
- (void)loginOut {
UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:nil message:@"您真的要退出吗?" preferredStyle:UIAlertControllerStyleAlert];
[alertVc addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil]];
[alertVc addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// 下面👇 这一行执行会有死锁的bug, app会卡主,处于假死状态,所以在异步线程执行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[QYMyInfoModel sharedMyInfoModel] qy_clearPropertyValue];
});
}]];
[self presentViewController:alertVc animated:YES completion:nil];
}
网友评论