NSNotification addObserver:someOtherClass

时间:2011-01-19 06:57:47

标签: iphone

我需要将一条消息传递给一个控制类(它会创建一个将要发送消息的类的实例)所以,我不能直接在我的文件中引用类名,而不能将它作为Global(如果“NSNotification”宣传能够传递各种信息,无论他们在哪里/什么班级都是荒谬的。

所以没有进一步的... ...

  

(从Say ClassB打电话)

     

ClassA创建ClassB

的实例

现在在ClassB,我需要将有关按钮按下的消息传递回ClassA

(insdie ClassB)
- (void)viewDidLoad
{
  [[NSNotificationCenter defaultCenter] addObserver:ClassA 
                                        selector:@selector(doLoginAction)      
                                        name:@"SomeButton" 
                                        object:nil];
  [super viewDidLoad];
}

这不会编译,即使我包含,抱歉,"#import "ClassA.h" 现在,如果我做一些愚蠢的事情,

ClassA *classa = [[ClassA alloc]init];

然后在addObserver:classa中使用这个新创建的classa实例它会编译,但正如我想的那样,绝对不会做任何事情......(我知道,但令人惊讶的是这种代码在Iphone编程中很流行书......)所以无论如何我都试过了。

但如果我将此功能放在ClassA中并使用addObserver:ClassB 它会被调用,但会导致堆栈转储unrecognized selector sent to instance 或使用addObserver:self

我很想删除Xcode并回到vim并使用旧的“C”回调...

2 个答案:

答案 0 :(得分:9)

所以,如果我做得对,你有ClassA创建ClassB的实例。反过来,这些实例应该直接向ClassA发送通知,而不知道任何相关信息。

如果这是正确的,那么NSNotificationCenter正是您所需要的。

ClassA实施中添加initialialize方法,如下所示:

@implementation ClassA

+ (void)initialize
{
    [[NSNotificationCenter defaultCenter]
        addObserver:self
           selector:@selector(YourSelector:)
               name:@"YourNotificationName"
             object:nil];
}

+ (void)YourSelector:(NSNotification *)notification
{
    NSDictionary *userInfo = [notification userInfo];

    // ...
}

// ...

@end

然后,ClassB的实例应仅使用其名称发布通知:

@implementation ClassB

- (void)postNotification
{
    NSDictionary *userInfo = ...;    // may be nil
    [[NSNotificationCenter defaultCenter]
        postNotificationName:@"YourNotificationName"
                               // the same name is used in the `addObserver` call
                               // in the previous code snippet
                      object:nil
                    userInfo:userInfo];
}

// ...

@end

总而言之,如果您使用的是NSNotificationCenter,则无需了解有关通知接收方的任何信息。实际上,您可以订阅任意数量的对象以接收相同的通知,并且每个对象都会在收到通知对象时调用其相应的方法(在addObserver中指定)。

请记住,在您将类实例添加为观察者而不是类对象本身的情况下,您应该在该实例的[[NSNotificationCenter defaultCenter] removeObserver:self]方法中调用dealloc

答案 1 :(得分:1)

我在这里看到了几个问题。

首先,您需要停止尝试交替使用类和实例。直到你有一个合理的心理模型来表明你的类和实例代表什么以及它们对你负责什么,你会对何时使用哪一个和一般的OOP产生各种各样的困惑。

NSNotificationCenter允许您注册一个类的特定实例,一个对象,作为特定通知的观察者。您需要了解并参考观察对象,以便将其注册为观察者。

其次,您需要考虑每个类的内容,以及它们的实例化对象所负责的内容。他们应该知道什么,他们不需要知道什么,以及他们如何沟通。

假设您创建ObjectA作为ClassA的实例,并创建ObjectB,这是ClassB的一个实例。现在ObjectA知道ObjectB,在所有A刚创建的B之后,因此A很容易引用B. ObjectB还不知道ObjectA; B已创建,但它不需要知道哪个对象,甚至不知道该对象是哪个类的实例。如果您希望ObjectB能够与ObjectA进行通信,那么您有几个选择。

  1. 授权:ObjectAObjectB上设置一个属性,指向ObjectA,现在B可以直接向A发送消息。现在你的两个对象耦合在一起,既有用也有问题。
  2. 通知:ObjectB可以发布通知,ObjectA可以观看通知。 B不需要知道A正在观察那些通知,并且A不需要知道通知源自B(尽管可能)。这些对象非常松散耦合,您可以在不了解应用程序的情况下更改应用程序的许多内容。
  3. 重要的是,如果ObjectA要收听通知,则A有责任将自己添加为观察者。由于B不知道A,因此B无法使A成为观察者。 A的创造者可能因为该对象会引用A,但A的子女不能,除非他们被提到A。

    看起来亚历克斯给出了一个很好的答案,所以希望这一切都很有用。