iOS:识别通用对象

3

在我的应用程序中,我需要分析一个对象,我这样做:

 if ([object_selected isKindOfClass:[Person class]]) {

    Persone *obj = (Persone*)object_selected;
    NSString *name = obj.nome;
    NSString *surname = obj.surname;

}
else if ([object_selected isKindOfClass:[Animal class]]) {

        Animal *obj = (Animal*)object_selected;
        NSString *name = obj.nome;
        NSString *breed = obj.breed;

    }

这种方式可以验证我的对象是否属于一个类来获取其属性,但是有没有更快的方法从我的对象中获取“name”属性呢?所有对象都有“name”属性。

谢谢


只需使用[obj name],您会收到警告,但如果所有对象都响应此属性,则它可以正常工作。如果一个对象不响应属性“name”,当您尝试访问它时,应用程序将崩溃。 - Marco Pace
5个回答

3

上述代码存在一个常见问题:如果缺少name属性,则会导致核心转储。下面是我更加安全的版本,只有一行:

id name = ([object respondsToSelector:@selector(name)]) ? [object name] : nil;

希望三元运算符没有让你困惑。如果没有名字存在,nil可以被替换为任何合适的内容,例如:

static NSDictionary *defaultNameForClasses = @{@"FooClass": @"Foo", /* ... */};
// ...
id name = ([object respondsToSelector:@selector(name)]) ? [object name] : defaultNameForClasses[NSStringFromClass([object class])];

2
请看苹果开发者文档中关于Objective-C协议的内容
简而言之,您可以在协议中定义所需的所有属性,使您的类(如Person、Animal等)遵循该协议,然后使用[object_selected conformsToProtocol:MyProtocol]来安全地获取属性,就像这样:
if ([object_selected conformsToProtocol:MyNamingProtocol]) {
  id<MyNamingProtocol> namedObject = object_selected;
  NSString *name = [namedObject name];
}

1

在单独的.h文件中创建一个协议。代码类似于以下内容:

@protocol NamedObjectProtocol

@property (nonatomic, strong) NSString *name;

@end

然后,使这两个对象类都声明符合该协议。接下来,您可以像这样获取属性,而不管 anObjectPerson 类还是 Animal 类的实例,从而消除 if/else 混乱的代码。

id <NamedObjectProtocol> namedObject = anObject;
NSString *name = namedObject.name;

你还应该考虑让AnimalPerson类继承自一个超类,该超类具有所有共性属性,例如名称属性。这将使您能够编写如下代码:
Character *character = anObject;
NSString *name = character.name;

1

您可以使用键值编码来安全地访问属性。只需使用:

NSString* name = [object_selected valueForKey:@"nome"]

这样做的好处是,如果object_selected没有一个名为name的属性,应用程序不会崩溃,在这种情况下,name变量的值将为nil
另一种避免崩溃的方法是检查对象是否响应选择器,如下所示。
if ([object_selected respondsToSelector:@selector(name)]) {
//...
}

我正想建议同样的事情。这种方法只有一个缺点。作为程序员,您无法确定现有属性的值是nil(可能具有含义或表示错误),还是不存在(这可能仅表示对象属于不同的类)。 - Hermann Klecker

0

你可以直接调用[object_selected name],但是你可能会收到编译器警告,提示name可能不是一个属性(或类似的警告)。


属性名是 name 还是 nome?我刚刚注意到你在 if/else if 中调用的属性是 nome,但你在问题中列出的属性是 name - neilvillareal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接