我正在访问这样的已发送通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleUnpresent:) name:UNPRESENT_VIEW object:nil];
...
-(void)handleUnpresent:(NSNotification *)note;
{
NSLog(@"%@", note.object.footer);
//property 'footer' not found on object of type 'id'
}
某些传入的note.object
对象有“页脚”,有些则没有。但是,我不想让一个只有一个名为footer
的属性的类只是为了让这个工作。我甚至试过((NSObject *)note.object).footer)
,它在某些语言中有效,但显然不是obj-c。我该怎么办?
答案 0 :(得分:2)
检查isKindOfClass
肯定是更强大的选择。但是,如果您有多个不相关的类返回所需的属性,则还有另一种方法:respondsToSelector
。只要询问对象是否有footer
方法,您就可以安全地调用它。
-(void)handleUnpresent:(NSNotification *)note;
{
id noteObject = [note object];
if ([note respondsToSelector:@selector(footer)])
{
NSLog(@"Footer = %@", [noteObject footer]);
}
}
respondsToSelector
方法在适当的位置非常强大且方便,但不要随意使用它。此外,它无法告诉您有关返回类型的任何信息,因此您获得的footer
可能不属于您期望的类。
noteObject.footer
和[noteObject footer]
的语法很容易被视为等效语法。但是,当noteObject
的类未知时,编译器将接受后者但不接受前者。如果noteObject
有一个通常不会响应footer
的已定义类,它将发出警告,但仍然可以编译并运行。在这些情况下,您有责任保证方法在需要时确实存在,因此方法调用不会在运行时崩溃。
答案 1 :(得分:1)
NSObject
没有任何名为footer
的属性,这就是编译器抱怨的原因。将ID转换回NSObject
无济于事。如果您知道对象始终是您创建的某个自定义对象,则可以转换为该对象,然后调用页脚,编译器不会抱怨。最好实际检查一下。请参阅下面的示例(例如,我将具有footer
属性ViewWithFooter
的类命名为,因此请重命名):
- (void)handleUnpresent:(NSNotification*)note
{
ViewWithFooter view = (ViewWithFooter*)[note object];
NSParameterAssert([view isKindOfClass:[ViewWithFooter class]]);
UIView* footer = [view footer];
// Do something with the footer...
NSLog(@"Footer: %@", footer);
}
如果你有一堆不相关的类(即不在同一个类层次结构中),它们都呈现footer
属性,那么最好是创建一个具有所需footer
属性的协议并将对象转换为上面代码示例中的协议,并断言它响应-footer
选择器。
以下是使用该协议的示例:
@protocol ViewWithFooter <NSObject>
- (UIView*)footer; // this could also be a readonly property, or whatever
@end
- (void)handleUnpresent:(NSNotification*)note
{
id<ViewWithFooter> view = (id<ViewWithFooter>)[note object];
NSParameterAssert([view respondsToSelector:@selector(footer)]);
UIView* footer = [view footer];
// Do something with the footer...
NSLog(@"Footer: %@", footer);
}
答案 2 :(得分:1)
如果通知中传递的object
可能是众多类中的一个,并且您不想将对象强制转换为特定类,则可以使用performSelector:
来调用{{1}对象上的方法。如果您使用footer
打包此调用,则如果对象结果没有respondsToSelector:
方法,则会避免异常。
footer
使用-(void)handleUnpresent:(NSNotification *)note;
{
if ([[note object] respondsToSelector:@selector(footer)]) {
NSString *footer = [[note object] performSelector:@selector(footer)];
NSLog(@"%@", footer);
}
}
将阻止编译器抱怨在'id'类型的对象上找不到方法“'footer'。”