【问题标题】:Is it possible to pass data as part of NSNotifications?是否可以将数据作为 NSNotifications 的一部分传递?
【发布时间】:2012-03-19 01:42:24
【问题描述】:

卡牌游戏场景中的场景:

用户在屏幕上移动一张卡片。作为移动的结果,卡片的坐标发生变化。如果发现卡片位于某个特定位置,我们会确保更新卡片对象(模型)以包含这些坐标。

但是 View 不应该直接与 Model 对话..,所以

View 不会直接更新 Card,而是通知其控制器“Card 已着陆”。收到此通知后,我希望控制器更新卡片的位置而不是视图(控制器更新模型)

问题 1: 我对这种情况的思考是否正确?

问题 2: 是否可以将数据与通知一起发送到控制器?

【问题讨论】:

    标签: objective-c ios model-view-controller


    【解决方案1】:

    您的场景不需要NSNotifications:应该采用直接的基于委托的方法。

    视图应该定义一个委托接口,并提供一个非保留的delegate 属性。控制器应该实现委托接口,并将自己设置为视图的委托。然后视图会通知它的委托,甚至不知道它通知了控制器。然后控制器会将通知传递给模型。

    @protocol CardDelegate
    -(void)cardHasLanded:(SOCard*)card atPosition:(SOPosition*)pos;
    @end
    
    @interface MyView
    @property (weak, nonatomic,readwrite) id<CardDelegate> delegate;
    @end
    
    @implementation MyViewController
    -(id)init { // This should be in your designated initializer
        self = [super init];
        if (self) {
            MyView *view = [[MyView alloc] init];
            view.delegate = self;
            self.view = view;
        }
        return self;
    }
    -(void)cardHasLanded:(SOCard*)card atPosition:(SOPosition*)pos {
        // Update the model
    }
    @end
    
    @implementation MyView
    @synthesize delegate;
    -(void) doSomething {
        // ...
        if (cardHasLanded) {
            [delegate cardHasLanded:card atPosition:pos];
        }
        // ... more code
    }
    @end
    

    【讨论】:

    • 反应很好。谢谢
    • 在您的示例中,控制器是否需要实现协议?看起来不像,但我想确认一下
    • 虽然委托方法也是一种标准设计模式并且在这里肯定非常有用,但通知方法的优势在于它很容易让新的观察者响应动作。例如,想要进行一些统计的对象也可以简单地观察通知,发送方不需要进行任何更改。使用委托模式不会那么容易并且可能会产生更紧密的耦合。需要将其更改为侦听器模式以保持松散耦合。
    • 感谢您对 DarkDust 的见解。刚刚从你的评论中得到一个想法。谢谢
    【解决方案2】:

    这就是userInfo 字典和NSNotificationobject 的用途。在这种情况下,它就是您想要的 object。例如:

    // In your model header file
    
    extern NSString * const CardMovedNotification;
    
    // In your model implementation file
    
    NSString * const CardMovedNotification = @"CardMoved";
    
    ...
    
    [[NSNotificationCenter defaultCenter] postNotificationName:CardMovedNotification object:theCardThatMoved];
    

    然后您的观察员可以通过[notification object] 获得卡片。如果您需要传递更多信息,您可以创建一个字典并将其传递为userInfo,通过postNotificationName:object:userInfo:。然后观察者可以通过[notification userInfo]查询它。

    【讨论】:

      【解决方案3】:

      我同意不需要通知。通常对于 UI 对象坐标,我不会使用模型对象,因为坐标与 UI 对象耦合(否则您将在哪里绘制它?)。您需要做的是将您的控制器注册到传递触摸的 UI 对象的触摸结束事件,并更新(在响应控制器方法中)对象的坐标(如果它们确实在所需的位置)。 (与按钮和其他 UI 对象一样)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-12
        • 1970-01-01
        • 2012-02-09
        • 2017-08-17
        相关资源
        最近更新 更多