【问题标题】:How to post to NSNotificationCenter regarding bool state?如何发布关于布尔状态的 NSNotificationCenter?
【发布时间】:2012-03-23 14:15:24
【问题描述】:

我正在尝试掌握使用通知的窍门。在我的视图控制器类中,我有一个 bool isFullScreen。当这个 bool 的值发生变化时,我想向所有观察类发送通知。我不太确定如何去做,因为 BOOL 不是对象。我将如何做到这一点?

【问题讨论】:

    标签: iphone objective-c ios


    【解决方案1】:
    [[NSNotificationCenter defaultCenter] postNotificationName:YourNotificationName object:[NSNumber numberWithBool:isFullScreen]]; //YourNotificationName is a string constant
    

    KVO 示例:

    如果你用 KVO 来做,它会像下面这样......:

    [self addObserver:self forKeyPath:@"isFullScreen" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
    
    - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString: @"isFullScreen"]) {
            BOOL newValue = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
        }
    }
    
    //and in dealloc
    [self removeObserver:self forKeyPath:@"isFullScreen" ];
    

    【讨论】:

    • 所以只要 isFullScreen 值发生变化,就会发送此通知?
    • 您可能更喜欢在 isFullScreen 变量上添加 KVO。阅读此内容。您注册为 isFullScreen 的 KVO 观察者,任何时候它发生变化,您都会收到通知
    • 每次更改值时都必须手动发送通知?我该怎么做?
    • 如果你要使用通知,你可以覆盖 - (void) setIsFullScreen:(BOOL)fullScreen { } 并把你的通知放在那里
    • 他回答的第一行是每次更改值时必须键入/复制粘贴的内容。编辑:或者你可以做bandejapsaisa建议的更好=P
    【解决方案2】:

    只需wrap NSNumber 中的 BOOL:

    [NSNumber numberWithBool:myBool]
    

    【讨论】:

      【解决方案3】:

      您可以在 NSNumber 中包装一个 BOOL,例如提到的 bandejapaisa 和铍。但是,为了通知观察者对简单属性的更改,最好使用键值观察 (KVO),而不是 NSNotificationCenter。只要您实现或符合@synthesized KVC 的访问器方法,您就可以“免费”获得 KVO。像这样的:

      // In your .h:
      
      @interface YourViewController : UIViewController
      
      @property (getter = isFullScreen) BOOL fullScreen;
      
      @end
      
      // In your .m:
      
      @implementation YourViewController
      
      @synthesize fullScreen;
      
      @end
      
      // In your observer class(es):
      
      // Start observing the viewController for changes to fullScreen (in awakeFromNib, or wherever it makes sense)
      [self.viewController addObserver:self forKeyPath:@"fullScreen" options:0 context:NULL];
      
      // This method is called when an observed value changes
      - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
      {
          if (object == viewController && [keyPath isEqualToString:@"fullScreen"]) 
          {
              if (self.viewController.isFullScreen)
              {
                  // Do whatever you need to do in response to isFullScreen being true
              }
              else
              {
                  // Do whatever you need to do in response to isFullScreen being false
              }
          } 
      }
      

      为此,您需要确保实际调用了 fullScreen 属性的设置器。因此,请始终使用 self.fullScreen = YES[self setFullScreen:YES] 而不是 fullScreen = YES。否则不调用setter方法,也不触发KVO。

      您应该阅读documentation on KVO。理解它对于成为一名优秀的 iOS 程序员非常重要。

      【讨论】:

      • 所以我有两个班级,FirstClass 和 SecondClass。 FirstClass 有属性 isFullScreen。如果我希望 SecondClass 知道对 FirstClass.isFullScreen 的任何更改,这会是什么样子?
      • SecondClass 必须通过 Interface Builder 连接或通过以编程方式设置的关系了解您的 FirstClass 实例。 SecondClass 将自己注册为 FirstClass 实例的 fullScreen 属性更改的观察者,然后将收到属性更改的通知。
      【解决方案4】:

      您可以通过使用 NSMutableString* 作为@"YES" 和@"NO" 来解决这个问题。然后,当您将字符串设置为 @"YES" 并且在 KVO 中观察到的所有内容都会收到通知:

      [myStringProperty setString:@"YES"];
      

      您必须使用 NSString setString 值。这就是它的实际调用方式。

      警告不要使用:

      myStringProperty = @"YES";
      

      (这不会产生 KVO 通知。)

      【讨论】:

        【解决方案5】:

        通知的object 应该是发布通知的对象,而不是NSNumber。这一点很重要,这样观察者可以观察特定的实例,并且调用者可以清楚地知道所有的值是什么。在object 中传递数据是获得“不响应选择器”崩溃的简单方法。更改数据通常放在 userInfo 字典中,但简单的 BOOL 通常使用两个通知来处理。在这种情况下,您将拥有:

        MYViewControlDidEnterFullScreenNotification
        MYViewControlDidExitFullScreenNotification
        

        object 应该是相关的视图控制器。

        请注意,这些通知的时间安排非常明确。两者都发生在状态改变之后。您还可以拥有等效的Will 通知。查看notification listNSWindow 以获得如何正确执行此操作的一个很好的示例。特别注意NSWindowDidEnterFullScreenNotification 及其亲属。

        您可能还对Some thoughts on NSNotifications感兴趣。

        KVO 上的 cmets 很好,而且 KVO 通常是实现这一目标的不错方式。但是通知也很好,并且比 KVO 更容易理解和调试。

        【讨论】:

          【解决方案6】:

          通知的对象字段旨在传递发送者而不是附加参数

          正确的做法是使用userInfo发送键值字典

          例如

          - (void)postNotificationFullScreen //post notification method and logic
          {
              NSString *notificationName = @"applicationFullScreen";
              NSString *key = @"fullScreen";
              NSDictionary *dictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:self.fullScreen] forKey:key];
              [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:nil userInfo:dictionary];
          }
          

          阅读本文

          NSString *notificationName = @"applicationFullScreen";
          
          [[NSNotificationCenter defaultCenter] 
              addObserver:self
              selector:@selector(useFullScreen:) 
              name:notificationName 
              object:nil];
          
          - (void)useFullScreen:(NSNotification *)notification //use notification method and logic
          {
              NSString *key = @"fullScreen";
              NSDictionary *dictionary = [notification userInfo];
              BOOL boolValue;
              if([dictionary valueForKey:key]) 
                 boolValue =[[dictionary valueForKey:key] boolValue];
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-03-14
            • 2017-10-07
            • 2020-02-27
            • 2014-11-20
            • 1970-01-01
            • 2018-04-07
            • 1970-01-01
            相关资源
            最近更新 更多