Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone NSNotification addObserver:someOtherClass_Iphone - Fatal编程技术网

Iphone NSNotification addObserver:someOtherClass

Iphone NSNotification addObserver:someOtherClass,iphone,Iphone,我需要将消息传递给控制类(该类创建将发送消息的类的实例),因此,我不能直接引用文件中的类名,而不将其设置为全局(如果“NSNotification”,则这样做很荒谬)广告能够传递各种各样的信息,无论它们在哪里/在什么级别 所以不用再多说了 (从Say ClassB打来) ClassA创建ClassB的实例 现在在ClassB中,我需要将有关按钮按下的消息传递回ClassA (insdie ClassB) - (void)viewDidLoad { [[NSNotificationCenter

我需要将消息传递给控制类(该类创建将发送消息的类的实例),因此,我不能直接引用文件中的类名,而不将其设置为全局(如果“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
它将被调用,但将导致堆栈转储
无法识别的选择器发送到实例
或者使用
addObserver:self


我很想删除Xcode并返回vim,使用一个很好的旧“C”回调…

因此,如果我做对了,您有一个
ClassA
,它创建
ClassB
的实例。这些实例反过来应该直接向
ClassA
发送通知,而不需要知道任何信息

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

ClassA
实现中添加一个
初始化
方法,如下所示:

@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]

我在这里看到了几个问题

首先,你需要停止尝试交替使用类和实例,直到你对类和实例所代表的内容以及它们的责任有了一个合理的心智模型,你才会对何时使用哪一个和OOP产生各种各样的困惑

NSNotificationCenter
允许您将类的特定实例、单个对象注册为特定通知的观察者。您需要了解观察对象并对其进行引用,才能将其注册为观察者

其次,你需要考虑每一个类,以及它们的实例化对象负责什么,他们应该知道什么,他们不需要知道,以及他们如何沟通。 假设您创建了
ObjectA
作为
ClassA
的一个实例,它创建了
ObjectB
,这是
ClassB
的一个实例。现在
ObjectA
意识到了
ObjectB
,毕竟A刚刚创建了B,所以A很容易对B进行引用。
ObjectB
还没有意识到
Obj创建了ectA
;B,但它不需要知道该对象是哪个对象,甚至不需要知道该对象是哪个类的实例。如果希望
ObjectB
能够与
ObjectA
通信,您有两个选项

  • 委派:
    ObjectA
    ObjectB
    上设置一个属性以指向
    ObjectA
    ,现在B可以直接向a发送消息。现在,您的两个对象耦合在一起,既有用又有问题
  • 通知:
    ObjectB
    可以发布通知,
    ObjectA
    可以观察通知。B不需要知道A正在观察这些通知,A也不需要知道通知是由B发起的(尽管它可以)。这些对象是松散耦合的,您可以在应用程序的许多方面进行更改,而不会让它们意识到
  • 重要的是,如果
    ObjectA
    要监听通知,那么A有责任将自己添加为观察者。因为B不知道A,所以B不可能成为观察者。A的创建者可以,因为该对象会引用A,但A的孩子不能,除非他们被赋予了A的某些引用


    看起来Alex给出了一个很好的答案,希望这一切都会有用。

    这是一个很好的解释。@Chinasaler一定要尝试熟悉使用Cocoa framework提供的每种特定技术的最佳实践。我刚才给了他一个快速片段,以解决当前的问题:)再次感谢Alex…但我要向jonah指出的是,它的核心是assm语言,无论您是像在object-C中那样实现“object”,还是如何在C中手动创建它们,使用指向“typedef结构”的指针**“ect,这只是一种让用户友好的方式,程序员可以管理您的数据、代码或Objs(如果您愿意的话)…@Chinasaler,恐怕我不理解您想表达的任何观点。我同意我们讨论的结构是抽象的,但这并不意味着它们可以互换。