Objective-C中将id动态类型转换为类的方法

8

我希望能够在Objective C中动态地进行类型转换,并访问实例属性。以下是伪代码:

id obj;
if (condition1)
    obj = (Class1*)[_fetchedResults objectAtIndex:indexPath.row];
else
    obj = (Class2*)[_fetchedResults objectAtIndex:indexPath.row];

NSNumber *latitude = obj.latitude;

然后编译器告诉我以下内容:在__strong id对象类型中找不到“latitude”属性 无论Class1和Class2是否为核心数据实体,它们几乎具有相同类型的属性。在条件1中,_fetchedResults返回Class1类型的对象,在条件2中_fetchedResults返回Class2类型的对象。
有人能给我提示如何解决这种问题吗?
谢谢!

我认为你首先应该确保[_fetchedResults objectAtIndex:indexPath.row]返回的是具有latitude属性的类。此外,将非NSManagedObject类型强制转换为NSManagedObject类型也是错误的。无论何时创建NSManagedObject实例,都需要一个NSManagedObjectContext。 - Owen Zhao
2个回答

7
您可以通过键值编码(KVC)访问属性:
[obj valueForKey:@"latitude"]

请注意,使用KVC来完成此操作将使您失去编译器的任何类型检查。 - ipmcc
6
当然可以,但使用id本身也是如此 :-) - Monolo
@Monolo 这是不必要的,与[obj latitude]具有相同的效果。 - hooleyhoop
@hooleyhoop 确实。我敢说使用 KVC 可以更好地传达意图,但这是编码风格的问题。你会在运行时得到不同的错误消息。如果我们想涵盖它,你理论上也可以定义一个不同名称的 getter。 - Monolo
键-值编码是托管对象的常见做法,所以我唯一要改变的是将 id 替换为 NSManagedObject * - Martin R

3

obj变量需要是具有相关属性的类型。如果两个实体都具有相同的属性,则可以通过在共同基类上声明该属性来实现此目的。如果这两种类型不适合共享一个公共基类,那么您可以让它们采用一个共同的协议,例如:

@protocol LatitudeHaving
@property (copy) NSNumber* latitude;
@end

@interface Class1 (AdoptLatitudeHaving) <LatitudeHaving>
@end

@interface Class2 (AdoptLatitudeHaving) <LatitudeHaving>
@end

接着,您需要将obj声明为一个id<LatitudeHaving>,如下所示:

id<LatitudeHaving> obj;
if (condition1)
    obj = (Class1*)[_fetchedResults objectAtIndex:indexPath.row];
else
    obj = (Class2*)[_fetchedResults objectAtIndex:indexPath.row];

NSNumber *latitude = obj.latitude;

完成了。顺便提一下,协议类似于Java中的接口。


Class1和Class2转换有什么作用? - hooleyhoop
objectAtIndex: 返回的是 id 而不是 id<LatitudeHaving>。这些强制转换可能并不是严格必要的,只是为了避免编译器的警告,但我试图让代码尽可能接近 OP 的代码。 - ipmcc

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