【问题标题】:Firebase removing observersFirebase 移除观察者
【发布时间】:2014-11-25 10:23:30
【问题描述】:

我在代码中删除 Firebase 观察者时遇到问题。下面是结构的分解:

var ref = Firebase(url:"https://MY-APP.firebaseio.com/")
var handle = UInt?

override func viewDidLoad() {
    handle = ref.observeEventType(.ChildChanged, withBlock: {
        snapshot in

        //Do something with the data
    }
}

override func viewWillDisappear(animated: Bool) {
    if handle != nil {
        println("Removed the handle")
        ref.removeObserverWithHandle(handle!)
    }
}

现在,当我离开视图控制器时,我看到打印了“已删除句柄”,但是当我返回视图控制器时,每个事件都会调用我的观察者两次。当我离开并再次返回时,它被调用了三遍。等等 为什么观察者没有被移除?

我也确实在后面的代码中调用了ref.setValue("some value"),这与它有什么关系吗?

【问题讨论】:

  • 也有这个问题,刚刚向 Firebase 支持发送了一个错误报告。由于它在 2 个月内没有修复,可能不会很快修复
  • @Cymric 嘿伙计,这有什么更新吗?任何回应 ?我真的需要一些解决方案。
  • 很遗憾没有。 4 个月前,我确实向 Firebase 支持团队提交了一个重现该错误的示例程序,但从那以后就没有收到他们的消息。我建议您尝试以下 Daniel K 的解决方法。
  • @Cymric 坏消息。就是这样。我正试图像丹尼尔解释的那样管理这个。谢谢大佬

标签: ios swift firebase


【解决方案1】:

以为我遇到了这个错误,但实际上我试图删除错误引用上的观察者。

原始代码:

let ref: FIRDatabaseReference = FIRDatabase.database().reference()
var childAddedHandles: [String:FIRDatabaseHandle] = [:]

func observeFeedbackForUser(userId: String) {
    if childAddedHandles[userId] == nil { // Check if observer already exists

        // NOTE: - Error is caused because I add .child(userId) to my reference and
        //     do not when I call to remove the observer.

        childAddedHandles[userId] = ref.child(userId).observeEventType(.ChildAdded) { 
            [weak self] (snapshot: FIRDataSnapshot) in

            if let post = snapshot.value as? [String:AnyObject],
               let likes = post["likes"] as? Int where likes > 0 {             

                self?.receivedFeedback(snapshot.key, forUserId: userId)          
            }
        }
    }
}

func stopObservingUser(userId: String) {
    // THIS DOES NOT WORK

    guard let cah = childAddedHandles.removeValueForKey(userId) else {
        print("Not observing user")
        return
    }

    // Error! I did not add .child(userId) to my reference
    ref.removeObserverWithHandle(cah)
}

固定代码:

func stopObservingUser(userId: String) {
    // THIS WORKS

    guard let cah = childAddedHandles.removeValueForKey(userId) else {
        print("Not observing user")
        return
    }

    // Add .child(userId) here
    ref.child(userId).removeObserverWithHandle(cah)
}

【讨论】:

    【解决方案2】:

    鉴于现在是 2015 年 4 月并且该错误仍然存​​在,我会针对该问题提出一个解决方法:

    • 保留句柄的引用(假设在字典中,在为相同的事件类型启动新的观察者之前,检查观察者是否已经存在。

    周围有把手占用的空间非常小(基于一些官方的 cmets :))所以不会有那么大的伤害。

    【讨论】:

    • 抱歉,回复缓慢,我已经开始从事其他一些项目,所以我花了一段时间来尝试你的建议。虽然不理想,但它确实提供了一种解决方法,所以谢谢你:)
    • 如果你在块中使用了一个无主的 self 引用,这是一个大问题。我是否必须编辑所有对 weak 的引用或检查实例是否每次都为零?
    【解决方案3】:

    观察者必须在它们被放置的相同参考路径上移除。并且它们发出的次数相同,或者对每个路径使用 ref.removeAllObservers()。

    这是我用来保持整洁的一个技巧:

    var fbObserverRefs = [FIRDatabaseReference]()    // keep track of where observers defined.
    

    ...然后,将观察者放入 viewDidLoad():

    fbObserverRefs.append(ref.child("user/\(uid)"))
    fbObserverRefs.last!.observe(.value, with: { snap in
        // do the work...
    })
    

    ...然后,在 viewWillDisappear() 中,删除所有已发布的观察者:

    // Only true when popped from the Nav Controller stack, ignoring pushes of 
    // controllers on top.
    if isBeingDismissed || isMovingFromParentViewController {
        fbObserverRefs.forEach({ $0.removeAllObservers() })
    }
    

    【讨论】:

      猜你喜欢
      • 2017-07-29
      • 1970-01-01
      • 1970-01-01
      • 2014-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      相关资源
      最近更新 更多