3

我创建了一个名为Foo

@interface Foo:NSObject{
     int myInt;
}
@property int myInt;
@end

和一个Foo名为的子类Bar

@interface Bar:Foo{
     NSString *myString;
}
@property (copy) NSString *myString;
@end

我正在尝试将对象Bar作为Foo对象存储在数组中,如下所示:

-(void)createBar{
     Foo *object = [[Bar alloc]init];

     // myArray is an instance of NSMutableArray
     [myArray addObject:object];
}

我这样做是因为我实际上有不止一个子类Foo(我不想全部列出)。当我从数组中抓取一个对象并将消息发送到对象以获取myString变量时,应用程序不执行任何操作。 例子:

-(NSString *)getStringFromFooAtIndex(NSUInteger)index{
     Foo *object = [myArray objectAtIndex:index];

     return [object myString];
}

我是否误解了“消息”的工作原理?我假设我可以向一个对象发送消息,并且无论它是否存在,它都会调用它。我需要以其他方式这样做吗?该数组将保存所有不同类型的Foo子类,我需要将它们存储在那里。

4

3 回答 3

3

我假设我可以向一个对象发送消息,并且无论它是否存在,它都会调用它。

您确实可以向任何对象发送任何消息;这就是 Objective-C 的乐趣所在。变量的类型(Foo *Bar *id或其他任何东西)对消息发送没有影响。变量指向的对象知道它的类。相应方法的查找是在运行时通过该类完成的。编译器将括号中的表达式转换为对函数的调用,objc_msgSend.

您应该[object myString]在构建时收到警告,说“'Foo'可能不会响应'myString'” - 编译器知道某处至少有一个类具有对应于的方法myString,并且它知道,在编译时 -时间,Foo似乎不是其中之一,但它不能保证Foo将无法在运行时对消息执行某些操作。消息可以在运行时以自定义方式解析。请注意,如果您将变量的类型更改为id,警告就会消失——编译器无法再推断出哪些方法可用。

如果事实证明您发送的对象myString 没有响应(即,如果该对象确实是aFoo而不是 a Bar,或者Foo是未实现 的子类之一myString),则会引发异常。NSObject这是对无法识别消息的默认响应(通过继承自 的任何内容)。

如果您需要向其发送消息的对象的异构集合,您可能需要先测试每个对象。您可以按照 jstevenco 的建议进行操作,并测试功能:

if( [object respondsToSelector:@selector(myString)] ){

或测试身份:

if( [object isKindOfClass:[Bar class]] ){

Bar如果对象是 a或任何的子类,则后者将通过Bar。仅用于isMemberOfClass:测试您指定的类。

于 2011-12-13T19:23:49.683 回答
1

有关如何处理消息传递逻辑的良好摘要,请参见此处。如果不覆盖,最终会产生错误-(void)doesNotRecognizeSelector:(SEL)aSelector

如果您要拥有一个多态的对象集合,您可能应该respondsToSelector:首先测试该对象,然后直接调用该方法或performSelector:根据您的需要使用其中一个变体。另一种可能性是myString在基类中包含一个什么都不做的实现。

于 2011-12-13T18:11:28.607 回答
0

我弄清楚了问题所在。

在我的 AppDelegate.m 文件中,我有以下方法:

- (void)createFoo{
     Foo *foo = [[Bar alloc]init];

     [myArrayController add:foo];
}

这是将“foo”对象插入到我的数组控制器中。我也定义了这个方法:

- (void) insertObject:(Foo *)object intoMyArrayControllerAtIndex:(NSUInteger)index{
     // handles the inserting of the object as well as working with the undo manager
}

现在,呼叫[myArrayController add:foo]是导致问题的原因。如果我替换那条线,[self insertObect:foo intoMyArrayControllerAtIndex:0]那么一切都会完美。

非常感谢您,很抱歉浪费您的时间。

于 2011-12-14T13:50:02.233 回答