0

我正在访问一个发送的通知,如下所示:

[[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。我能做些什么?

4

3 回答 3

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,它会给出警告,但仍会编译和运行。在这些情况下,您有责任保证该方法在需要时确实存在,因此该方法调用不会在运行时崩溃。

于 2012-04-15T05:11:18.110 回答
1

NSObject没有任何名为 的属性footer,这就是编译器抱怨的原因。将 id 转换回 anNSObject无济于事。如果您知道该对象始终是您创建的某个自定义对象,则可以转换回该对象,然后调用 footer,编译器不会抱怨。最好实际检查一下。请参见下面的示例(例如,我将具有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);
}
于 2012-04-15T04:30:25.203 回答
1

如果object传入的通知可能是多个类之一,并且您不想将对象强制转换为特定类,则可以使用该类performSelector:调用footer对象上的方法。如果你用 a 包装这个调用,respondsToSelector:如果对象没有方法,你将避免异常footer

-(void)handleUnpresent:(NSNotification *)note;
{
    if ([[note object] respondsToSelector:@selector(footer)]) {
        NSString *footer = [[note object] performSelector:@selector(footer)];

        NSLog(@"%@", footer);
    }
}

使用performSelector将停止编译器抱怨方法“'footer' not found on object of 'id'”。

于 2012-04-15T05:36:31.440 回答