Objective-C如何避免大量if语句检查对象类型
嘿,这种层层嵌套的“厄运金字塔”确实写起来闹心,我给你分享几个能把代码捋清爽的实用技巧,都是OC原生就能实现的:
1. 写个通用的安全取值分类
最省心的方式是给NSObject加个分类,封装“按键路径取值+类型校验”的逻辑,以后所有地方都能复用:
@interface NSObject (SafeValueAccess) // 根据键路径取值,并校验是否为指定类型,符合则返回,否则返回nil - (nullable id)safeValueForKeyPath:(NSString *)keyPath ofClass:(Class)expectedClass; @end @implementation NSObject (SafeValueAccess) - (nullable id)safeValueForKeyPath:(NSString *)keyPath ofClass:(Class)expectedClass { if (!keyPath || !expectedClass) return nil; id result = [self valueForKeyPath:keyPath]; return [result isKindOfClass:expectedClass] ? result : nil; } @end
用这个分类重构你的代码,瞬间告别嵌套:
NSString *text = @""; id json = [NSJSONSerialization JSONObjectWithData:[data dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; // 先取data.value数组,校验类型 NSArray *valueArray = [json safeValueForKeyPath:@"data.value" ofClass:[NSArray class]]; if (valueArray) { // 这里注意:原代码里[value valueForKey:@"url"]返回的是数组(数组每个元素的url集合),如果要取单个元素的url,应该用firstObject NSString *url = [valueArray.firstObject safeValueForKeyPath:@"url" ofClass:[NSString class]]; if (url) text = url; }
2. 用“Guard宏”模拟Swift的提前退出
如果你不想写分类,还可以用宏来模拟Swift里的guard语句,把嵌套的条件判断平铺成顺序执行的检查,不满足就提前跳出:
// 定义Guard宏:条件不满足时执行block并退出当前方法 #define Guard(condition, exitBlock) if (!(condition)) { exitBlock; return; }
重构后的代码就变成了线性逻辑,没有多层缩进:
NSString *text = @""; id json = [NSJSONSerialization JSONObjectWithData:[data dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; // 逐层检查,不满足就直接返回 Guard([json isKindOfClass:[NSDictionary class]], { return; }); NSDictionary *jsonDict = (NSDictionary *)json; Guard([jsonDict[@"data"] isKindOfClass:[NSDictionary class]], { return; }); NSDictionary *dataDict = jsonDict[@"data"]; Guard([dataDict[@"value"] isKindOfClass:[NSArray class]], { return; }); NSArray *valueArray = dataDict[@"value"]; // 原代码这里有个小问题:数组调用valueForKey:@"url"返回的是数组,不是单个NSString,所以调整为取第一个元素的url id urlObj = valueArray.firstObject[@"url"]; Guard([urlObj isKindOfClass:[NSString class]], { return; }); text = (NSString *)urlObj;
额外小提示
原代码里[value valueForKey:@"url"]如果value是NSArray,返回的是所有元素的url组成的数组,这时候判断它是NSString永远不会成立,应该是你想取数组里某个元素的url(比如第一个),记得调整这部分逻辑哦~
内容的提问来源于stack exchange,提问作者Curt Rand
相关产品推荐
相关产品推荐

