2011-01-19 53 views
4

我需要将消息传递给控制类(它创建将发送消息的类的实例)所以,我无法直接引用类文件名称全球(这是荒谬做的,如果“NSNotification”通告到能够通过各种消息,无论在哪里/它们是什么类。NSNotification addObserver:someOtherClass

所以事不宜迟......

(从Say ClassB调用)

ClassA创建Clas实例胆红

现在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”回调...

回答

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中指定)。

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

+1

很好的回答....非常感谢! – chinasailor 2011-01-19 07:43:41

1

我在这里看到一些问题。

首先,您需要停止尝试交替使用类和实例。除非你对你的类和实例代表什么以及它们负责什么有一个合理的心智模型,否则在什么时候使用哪一个和OOP的时候会有各种各样的困惑。

NSNotificationCenter允许您将类的特定实例(单个对象)注册为特定通知的观察者。您需要了解并参考观察对象,才能将其注册为观察者。

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

我们假设您创建ObjectA作为ClassA的实例,并创建了ObjectB,它是ClassB的实例。现在ObjectA知道ObjectB,毕竟A刚刚创建B,所以A很容易引用B。ObjectB还不知道ObjectA; B被创建,但它不需要知道哪个对象,甚至哪个对象是什么类的实例。如果你想ObjectB能够与ObjectA沟通,你有几个选项。

  1. 团:ObjectA上设置ObjectB一个属性来指回ObjectA,现在乙可以将消息发送至A直接。现在你的两个对象被耦合在一起,这可能是有用的和有问题的。
  2. 通知:ObjectB可以发布通知,ObjectA可以观察通知。 B不需要知道A正在观察那些通知,A不需要知道通知是由B发起的(尽管它可以)。这些对象非常松散地耦合在一起,您可以在应用程序中改变很多事情,而无需知道它们。

重要的是,如果ObjectA要侦听通知,那么它有责任将自己添加为观察者。因为B不知道A,所以B不可能让A成为观察者。 A的创建者可能会因为该对象会提及A,但A的孩子不能,除非他们被给予对A的一些参考。

Alex看起来像一个很好的答案,所以希望这一切都会有用。

+0

这是一个很好的解释。 @chinasailor绝对应该尝试熟悉使用Cocoa框架提供的每种特定技术的最佳实践。我只是给了他一个快速的片段,以解决在湾问题的立即问题:) – 2011-01-19 07:56:26