iOS:这是检查 JSON 字典对象是否为 NSString 的好方法吗?
iOS: Is this a good way to check if JSON dictionary object is an NSString?
我想检查 JSON 对象是否是 NSString,如果不是,则为其分配一个默认字符串。我的最终目标是无论如何都防止崩溃并为属性分配适当的值。这是我正在使用的数据模型示例,其中 dict
是 JSON 字典 API returns.
Data *data = [[self alloc] init];
data.name = [NSString validateString:dict[@"name"] defaultString:@""];
data.status = [NSString validateString:dict[@"status"] defaultString:@"OPEN"];
这是我正在使用的分类方法validateString
。
+ (NSString *)validateString:(NSString *)aString defaultString:(NSString *)defaultString {
if ([aString isKindOfClass:[NSString class]]) {
return aString;
}
return defaultString;
}
强制转换 (NSString *)aString
然后询问这是否实际上是一个 NSString 是没有意义的,也是非常糟糕的做法。
还有,如果是nil怎么办?
当你从字典中获取时,你所知道的就是你得到一个 id
。不要假设更多。
我建议写得非常直白:说出你的意思,说出你的意思。这是 Objective-C 中的最佳实践。否则,动态类型和 "nil trickery" 会使您陷入微妙的错误。在这种特殊情况下你可能没有任何问题,但坏习惯就是坏习惯,最好不要让它们养成。我会这样重写:
+ (NSString *) checkType:(nullable id)obj defaultString:(NSString *)def {
if (obj == nil || ![obj isKindOfClass:[NSString class]]) {
return def;
}
return obj;
}
就像其他评论中提到的:如果你想防止崩溃,你还需要检查它是否是 nil
,特别是如果将来有机会将你的代码移植到 Swift .
只是为了澄清我的最后一句话,即使 aString
是 nil
:
,下面的行在 Objective-C 中也有效
if ([aString isKindOfClass:[NSString class]]) {
那是因为,在 Objective-C 的制作方式中,调用 nil
对象 returns nil
上的函数,所以 if
将被视为 false
,函数将 return defaultString
。是的......当他们创建 Objetive-C 时,这肯定是个坏主意,因为这会导致很多错误。下面是有关该行为的更多详细信息:
无论如何,仅在检查对象类型后才强制转换对象也是一个好习惯,因此我建议您调整您的函数:
+ (NSString *)validateString:(id)obj defaultString:(NSString *)defaultString {
if (obj != nil && [obj isKindOfClass:[NSString class]]) {
return (NSString*)obj;
}
return defaultString;
}
每个实现NSObject*
的对象都有isKindOfClass:
(而NSDictionary*
只存储实现NSObject*
的对象),所以我们不需要检查对象是否回应它。此外,即使我们想要,respondsToSelector:
也是一个 NSObject*
函数。
不过,您使用的方法仍然有效。上面修改后的功能只是为了更好的实践和避免将来需要将此代码移植到 Swift(或任何其他语言)时出现问题。
编辑:根据@matt 的建议更新了代码。
我想检查 JSON 对象是否是 NSString,如果不是,则为其分配一个默认字符串。我的最终目标是无论如何都防止崩溃并为属性分配适当的值。这是我正在使用的数据模型示例,其中 dict
是 JSON 字典 API returns.
Data *data = [[self alloc] init];
data.name = [NSString validateString:dict[@"name"] defaultString:@""];
data.status = [NSString validateString:dict[@"status"] defaultString:@"OPEN"];
这是我正在使用的分类方法validateString
。
+ (NSString *)validateString:(NSString *)aString defaultString:(NSString *)defaultString {
if ([aString isKindOfClass:[NSString class]]) {
return aString;
}
return defaultString;
}
强制转换 (NSString *)aString
然后询问这是否实际上是一个 NSString 是没有意义的,也是非常糟糕的做法。
还有,如果是nil怎么办?
当你从字典中获取时,你所知道的就是你得到一个 id
。不要假设更多。
我建议写得非常直白:说出你的意思,说出你的意思。这是 Objective-C 中的最佳实践。否则,动态类型和 "nil trickery" 会使您陷入微妙的错误。在这种特殊情况下你可能没有任何问题,但坏习惯就是坏习惯,最好不要让它们养成。我会这样重写:
+ (NSString *) checkType:(nullable id)obj defaultString:(NSString *)def {
if (obj == nil || ![obj isKindOfClass:[NSString class]]) {
return def;
}
return obj;
}
就像其他评论中提到的:如果你想防止崩溃,你还需要检查它是否是 nil
,特别是如果将来有机会将你的代码移植到 Swift .
只是为了澄清我的最后一句话,即使 aString
是 nil
:
if ([aString isKindOfClass:[NSString class]]) {
那是因为,在 Objective-C 的制作方式中,调用 nil
对象 returns nil
上的函数,所以 if
将被视为 false
,函数将 return defaultString
。是的......当他们创建 Objetive-C 时,这肯定是个坏主意,因为这会导致很多错误。下面是有关该行为的更多详细信息:
无论如何,仅在检查对象类型后才强制转换对象也是一个好习惯,因此我建议您调整您的函数:
+ (NSString *)validateString:(id)obj defaultString:(NSString *)defaultString {
if (obj != nil && [obj isKindOfClass:[NSString class]]) {
return (NSString*)obj;
}
return defaultString;
}
每个实现NSObject*
的对象都有isKindOfClass:
(而NSDictionary*
只存储实现NSObject*
的对象),所以我们不需要检查对象是否回应它。此外,即使我们想要,respondsToSelector:
也是一个 NSObject*
函数。
不过,您使用的方法仍然有效。上面修改后的功能只是为了更好的实践和避免将来需要将此代码移植到 Swift(或任何其他语言)时出现问题。
编辑:根据@matt 的建议更新了代码。