【问题标题】:Swift Observer (KVO): Checking for ExistenceSwift Observer (KVO):检查存在
【发布时间】:2018-09-11 12:34:00
【问题描述】:

我有一个用户可以平移的框。为此,我添加了一个观察者来检查它的中心是否发生了变化:

self.boxView!.addObserver(self, forKeyPath: "center", options: .old, context: &BoxCenterContext)

这是在显示框的动画之后添加的。

当框消失时,我将其删除:

self.boxView!.removeObserver(self, forKeyPath: "center", context: &BoxCenterContext)

问题

用户有可能在盒子展示完成之前关闭盒子,即。在添加 KVO 之前。

发生这种情况时,应用程序在尝试删除不存在的 KVO 时会崩溃。

问题

有没有办法检查 KVO 是否存在(在尝试删除之前)?

【问题讨论】:

    标签: ios swift xcode key-value-observing


    【解决方案1】:

    observationInfo属性在添加观察者时设置

    if self.boxView!.observationInfo != nil {
    
       self.boxView!.removeObserver(self, forKeyPath: "center", context: &BoxCenterContext) 
    }
    

    【讨论】:

    • 这似乎可行,因为只有一个观察者。
    • 它也适用于许多人,只有当观察者为零时,该属性才设置为 nil
    • 我同意@Gizmodo,如果您注册了多个观察服务器,这将不是零,因此您将无法判断您要删除的那个是否真的注册了
    • @Sh_Khan 我注释掉了我的 avplayer 观察者(它没有观察者),然后使用它,我遇到了一个崩溃,说 avplayer 从未注册为观察者。我检查了 vc 并没有其他地方有任何观察员注册。我事先打印了值并返回了一些东西: print("observationInfo: (player!.observationInfo as Any)") 打印 observationInfo: Optional(0x0000600002507a60)跨度>
    【解决方案2】:

    Apple 不提供任何 API 来检查观察者的存在,但您可以为此管理 Bool 标志。就像您注册 KVO 时一样,您将 isObserver bool 设置为 true,然后在删除观察者之前,您需要检查 isObserver 是否为真,如果 isObserver 为真,则删除观察者,如果为假,则不要做任何事情。

    【讨论】:

      【解决方案3】:

      使用这个扩展

      extension NSObject {
        func safeRemoveObserver(_ observer: NSObject, forKeyPath keyPath: String) {
          switch self.observationInfo {
          case .some:
            self.removeObserver(observer, forKeyPath: keyPath)
          default:
            debugPrint("observer does no not exist")
          }
        }
      }
      

      【讨论】:

        【解决方案4】:

        根据Apple doc 观察者删除代码应该包装在@try @catch 块中,因为没有API 可以检查特定对象是否是观察者。例如(请原谅我的目标 c):

            @try {
                [self.event removeObserver:self forKeyPath:@"eventTimeZone"];
            } @catch (NSException *exception) {
                NSLog(@"Tried to remove observer from event, but there was no observer anymore.");
            }
        

        【讨论】:

        • 这在 Swift 中不起作用。非常烦人的是,“removeObserver”调用没有标有“throw”,因此基本语言设计不可能从中捕获异常。
        猜你喜欢
        • 2011-10-21
        • 2017-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-12
        相关资源
        最近更新 更多