如何消除像这样的Objective-C@try@catch块?
我是一名来自Python世界的开发人员,习惯于使用异常。我在许多地方发现,在这里使用异常并不是那么明智,并在需要时尽我所能转换为N错误。但后来我遇到了这样的情况:如何消除像这样的Objective-C@try@catch块?,objective-c,Objective C,我是一名来自Python世界的开发人员,习惯于使用异常。我在许多地方发现,在这里使用异常并不是那么明智,并在需要时尽我所能转换为N错误。但后来我遇到了这样的情况: NSMutableArray *results; for (NSDictionary *dict in dicts) { // Memory management code omitted SomeModel *model = [[SomeModel alloc] init]; model.attr1 = [[
NSMutableArray *results;
for (NSDictionary *dict in dicts)
{
// Memory management code omitted
SomeModel *model = [[SomeModel alloc] init];
model.attr1 = [[dict objectForKey:@"key1"] integerValue];
model.attr2 = [[dict objectForKey:@"key2"] integerValue];
model.attr3 = [[dict objectForKey:@"key3"] integerValue];
model.attr4 = [[dict objectForKey:@"key4"] integerValue];
[results addObject:model];
}
dict中的某些对象包含NSNull,这将导致“无法识别的选择器”异常。在这种情况下,我想完全删除该数据。我的第一反应是将for块的全部内容包装成一个@try-@catch块:
NSMutableArray *results;
for (NSDictionary *dict in dicts)
{
@try
{
SomeModel *model = [[SomeModel alloc] init];
model.attr1 = [[dict objectForKey:@"key1"] integerValue];
model.attr2 = [[dict objectForKey:@"key2"] integerValue];
model.attr3 = [[dict objectForKey:@"key3"] integerValue];
model.attr4 = [[dict objectForKey:@"key4"] integerValue];
[results addObject:model];
}
@catch(NSException *exception)
{
// Do something
}
}
但这是一个好办法吗?如果不对每个变量进行重复检查,我就无法想出一个解决方案,这在我看来真的很难看。希望我没有想到其他替代方法。提前感谢。正确的Objective-C方法是:
for (NSDictionary *dict in dicts)
{
if (! [dict isKindOfClass:[NSDictionary class]])
continue;
// ...
}
在Objective-C中,测试接收者在发送消息之前是否能够响应消息是一种典型模式
另外,请注意Objective-C中的异常始终是程序员错误,不会用于正常的执行流。许多人在这些情况下使用NSDictionary上的类别:
- (id)safeObjectForKey:(id)aKey
{
id obj = [self objectForKey:aKey];
if ([obj isKindOfClass:[NSNull class]])
{
return nil;
}
return obj;
}
您仍然需要确保您的dict是一个实际的字典实例。最后,我决定使用KVC解决这个问题。大概是这样的:
- (id)initWithPropertyDictionary:(NSDictionary *)dict
lookUpTable:(NSDictionary *)keyToProperty
{
self = [self init];
for (NSString *key in dict)
{
NSString *propertyName;
if ([keyToProperty objectForKey:key])
propertyName = [keyToProperty objectForKey:key];
else
propertyName = key;
if ([[dict objectForKey:key] isKindOfClass:[NSNull class]])
{
[self release];
return nil;
}
else
{
[self setValue:[dict objectForKey:key] forKey:propertyName];
}
}
}
这个解决方案的缺点是,我必须在属性中使用NSNumber,但是对于JSON数据,浮点数和整数之间实际上没有区别,所以这很好
如果您真的需要基元类型,可以将此方法与将这些NSNUMBER转换为适当类型的自定义设置器耦合
这样,在将对象添加到数组中之前,只需检查nil。除了模型类,其他地方都要干净得多
感谢Jayde3启发我专注于更改模型类。Objective-C的基本规则是
@try/catch
意味着您的程序将崩溃,并且将无法继续执行。如果“该数据”指的是:整个SomeModel对象,那么您使用try-catch的方法就可以了。没有规则禁止使用try-catch。如果“数据”的意思是:某个模型的特定属性,那么Jayde3的回答为您提供了一个很好的方法。我意识到在这里使用异常可能不是一个好主意,但是除了检查我的每一个条目,我真的没有别的选择吗?我相信要求是处理NSNull
的词典条目,而不是整个词典。@janusfidel苹果的所有代码都经过了优化,在O(0)
中运行。除非他们决定不再支持某个设备,否则他们会让它在O(n!!)
中运行。为什么要专门检查NSNull
?这似乎并不能解决问题……这正是我们所要求的。这是解析JSON后的常见问题。您可以在nil
对象上发送任何消息,但不能在NSNull
对象上发送任何消息。在他的情况下,调用integerValue
会发生崩溃。如果返回nil,它不会崩溃。但是在这种情况下,您是否应该检查而不是(![obj isKindOfClass:[NSNumber class]])
呢?一般的问题是您会得到NSNull
对象。你不能打电话给他们。通常,您希望从任何API获得特定类型。您需要实际数据,如果没有数据,则为零。NSNull是第三种情况,如果使用此类别,则不需要处理。当然,最好检查示例中所期望的每种类型。但这是一种更通用的方法,在大多数情况下已经足够了。哇,我想这是一个常见的问题,因为我甚至没有在我的帖子中提到我在解析。这并不能完全解决我的问题,因为我的主要诉求是有一种简单的方法来删除错误的数据,但我想如果我们以不同的方式查看数据,这是可以的。如果没有更好的东西出现,我会把这个标记为正确的。