当一个对象在另一个对象上调用方法时,Objective-C使用复杂的消息传递系统。我想知道在被调用的方法中是否有可能确定调用对象是什么?
例如:
@implementation callingClass
- (void)performTest
{
calledObject = [[[calledClass alloc] init] autorelease];
id result = [calledObject calledMethod];
assert(result == this);
}
@end
@implementation calledClass
- (id)calledMethod
{
id objectThatCalledThisMethod = ... // <-- what goes here?
return objectThatCalledThisMethod;
}
@end
我可以在注释行中写什么,以便在执行performTest
时使断言通过?
答案 0 :(得分:11)
不是运行时。所有消息发送最终都会在objc_msgSend(id receiver, SEL selector, /*method arguments*/...)
的行中进行函数调用。如您所见,没有传递有关发送消息的对象的信息。通过遍历堆栈来确定调用对象可能是可能的,但这种方式就是疯狂。告诉谁调用该方法的唯一实用方法是给它一个sender
参数,就像所有IBAction方法一样。
答案 1 :(得分:4)
我希望这会有所帮助:
NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1];
// Example: 1 UIKit 0x00540c89 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:@" -[]+?.,"];
NSMutableArray *array = [NSMutableArray arrayWithArray:[origen componentsSeparatedByCharactersInSet:separatorSet]];
[array removeObject:@""];
NSLog(@"Pila = %@", [array objectAtIndex:0]);
NSLog(@"Framework = %@", [array objectAtIndex:1]);
NSLog(@"Memory address = %@", [array objectAtIndex:2]);
NSLog(@"Class caller = %@", [array objectAtIndex:3]);
NSLog(@"Function caller = %@", [array objectAtIndex:4]);
NSLog(@"Line caller = %@", [array objectAtIndex:5]);
答案 2 :(得分:2)
不,你无法确定叫你的对象。好吧,从技术上讲,它可能会在堆栈后面跟踪,但对于真正的代码来说肯定不实用。
如果查看大多数委托方法,可以看到标准委托调用格式如下所示:
- (NSSize) windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize;
- (BOOL) windowShouldClose:(id)window;
- (void) windowWillMove:(NSNotification *)notification;
注意窗口(调用者)如何作为第一个参数传递,以及“window”如何作为方法名称的第一部分。在最后一种情况下,窗口调用者隐含在NSNotification中(notification.object是窗口)。
答案 3 :(得分:2)
您可以尝试从NSInvocation
派生自己的类,其中包含调用者信息。或者围绕NSInvocation包装一个类,重新实现那里的一些调用。