泄漏的听众firebase ios

时间:2016-04-15 18:40:27

标签: ios swift firebase

我正在尝试加载聊天功能的消息框数据。

消息框加载为:

override func viewDidAppear(animated: Bool) {
          super.viewDidAppear(animated)

if (PFUser.currentUser()!["firebaseUID"] !== nil)
{
    print(PFUser.currentUser()!["firebaseUID"])
   self.updateResultArray(PFUser.currentUser()!["firebaseUID"] as! String)
}
}

    func updateResultArray(uid: String) {


    let userName = String(PFUser.currentUser()!["username"])

    //print("updateResultArray is getting called")
    let userhandle = self.firebase.childByAppendingPath("users").childByAppendingPath(uid).childByAppendingPath("rooms").queryOrderedByValue()
        .observeSingleEventOfType(.Value, withBlock: { roomsnapshot in

            let enumerator = roomsnapshot.children
            while let rest = enumerator.nextObject() as? FDataSnapshot {
                self.roomArray.append(rest.key)
            }

            //get the latest message from all the rooms
            if self.roomArray.isEmpty == false
            {
                for i in 0...self.roomArray.count-1
                {
                    print("in the room loop \(self.roomArray[i])")

                    let messagehandle = self.messagesRef.childByAppendingPath(self.roomArray[i]).queryOrderedByKey().queryLimitedToFirst(1).observeSingleEventOfType(.Value, withBlock: {
                        messagesnapshot in

                        print("the messagesnapshot child count is \(messagesnapshot.childrenCount)")
                        let enumerator = messagesnapshot.children
                        while let rest = enumerator.nextObject() as? FDataSnapshot {

                            let sender = rest.value.objectForKey("sender") as? String
                            let reciever = rest.value.objectForKey("reciever") as? String

                            //print("sender is \(sender!) and reciever is \(reciever!)")


                            let eventhandle = self.firebase.childByAppendingPath("rooms").childByAppendingPath(self.roomArray[i]).observeSingleEventOfType(.Value, withBlock: { eventsnapshot in

                                if eventsnapshot.value is  NSNull {
                                    // The value is null
                                }
                                else
                                {
                                let eventAttr = eventsnapshot.value.objectForKey("eventAttributes") as? String
                                let eventDetails = eventsnapshot.value.objectForKey("eventDetails") as? String


                                //print("userName is \(userName)")
                                //print("sender is \(sender)")
                                if (userName !=  sender!) //for event joinee
                                {
                                    let firstname1 = eventsnapshot.value.objectForKey("firstname1") as? String
                                    self.otherNames.append(sender!)
                                    self.resultsNameArray.append(firstname1!)
                                    self.base4String = eventsnapshot.value.objectForKey("img1") as! String
                                    self.resultsImageFiles.append(self.base4String)

                                }
                                else //for event creator
                                {
                                    let firstname2 = eventsnapshot.value.objectForKey("firstname2") as? String
                                    self.otherNames.append(reciever!)
                                    self.resultsNameArray.append(firstname2!)
                                    self.base4String = eventsnapshot.value.objectForKey("img2") as! String
                                    self.resultsImageFiles.append(self.base4String)

                                }

                                let newlineChars = NSCharacterSet.newlineCharacterSet()
                                let evntArray = eventDetails!.componentsSeparatedByCharactersInSet(newlineChars).filter{!$0.isEmpty}
                                self.eventArray.append(evntArray[0])

                                self.eventdetailsArray.append(eventAttr!)

                                dispatch_async(dispatch_get_main_queue()) { () -> Void in
                                    self.resultsTable.reloadData()
                                }

                                }

                            })

                           // self.firebase.removeAuthEventObserverWithHandle(eventhandle)
                        }

                    })

                    //self.messagesRef.removeAuthEventObserverWithHandle(messagehandle)
                }

            }
        })


      //firebase.removeAuthEventObserverWithHandle(userhandle)


}

因为我使用observeSingleEventOfType我没有编码删除处理程序(我也试过了)。

在个人聊天中,代码如下:

func refreshResults() {

    print("the roomid is \(roomid)")

    //update from firebase
   let messagehandle = self.messagesRef.childByAppendingPath(roomid).queryOrderedByKey()
        .observeEventType(.Value, withBlock: { messageTextsnapshot in

            self.messageArray.removeAll()
            self.senderArray.removeAll()


            //                print("the messageTextsnapshot child count is \(messageTextsnapshot.childrenCount)") // I got the expected number of items
            let enumerator = messageTextsnapshot.children
            while let rest = enumerator.nextObject() as? FDataSnapshot {


                let text = rest.value.objectForKey("message") as? String
                let sender = rest.value.objectForKey("sender") as? String


                if text != nil && text != ""
                {

                    self.messageArray.append(text!)
                    self.senderArray.append(sender!)

                }

            }


            for subView in self.resultsScrollView.subviews {
                subView.removeFromSuperview()
            }

            for var i = 0; i <= self.messageArray.count-1; i++ {


                if self.senderArray[i] == userName {


                    if (self.messageArray[i].rangeOfString(self.acceptMessage) != nil)
                    {

                        let chatBubbleData = ChatBubbleData(text: self.messageArray[i], image:self.myImg, date: NSDate(), type: .AcceptMine)

                        self.addChatBubble(chatBubbleData)

                    }
                    else
                    {

                        let chatBubbleData = ChatBubbleData(text: self.messageArray[i], image:self.myImg, date: NSDate(), type: .Mine)

                        self.addChatBubble(chatBubbleData)

                    }

                } else {

                    if (self.messageArray[i].rangeOfString(self.acceptMessage) != nil)
                    {

                        let chatBubbleData = ChatBubbleData(text: self.messageArray[i], image:self.otherImg, date: NSDate(), type: .Accept)

                        self.addChatBubble(chatBubbleData)

                    }
                    else
                    {

                        let chatBubbleData = ChatBubbleData(text: self.messageArray[i], image:self.otherImg, date: NSDate(), type: .Opponent)

                        self.addChatBubble(chatBubbleData)
                    }
                }

                let bottomOffset:CGPoint = CGPointMake(0, self.resultsScrollView.contentSize.height - self.resultsScrollView.bounds.size.height)
                self.resultsScrollView.setContentOffset(bottomOffset, animated: false)

            }


        })

    self.messagesRef.removeAuthEventObserverWithHandle(messagehandle)
}

还有一些类似的其他听众。问题是,当我从这个视图返回时(单个聊天到消息框,内存消耗增加。我已经清除所有数组并在使用后立即关闭处理程序。但仍然内存消耗增加,有时在消息框中相同的行再次被复制我应该怎么解决这个问题。我试过用 observeSingleEventOfType但由于数据同步停止,因此它不是正确的解决方案。

用作参考: https://www.firebase.com/blog/2015-10-15-best-practices-uiviewcontroller-ios-firebase.html

2 个答案:

答案 0 :(得分:2)

由于侦听器回调块保持对消息框对象的引用而导致保留周期,因此看起来您的消息框对象未被释放。您可以通过在传递给其他对象的块中使用[weak self]来缓解此问题。例如:

            .observeSingleEventOfType(.Value, withBlock: 
                {
                    [weak self] roomsnapshot in

                    let enumerator = roomsnapshot.children
                    ...

这使'self'成为可选类型,然后您可以添加:

guard let strongSelf = self else { ... }

答案 1 :(得分:0)

问题是我关闭了父母的听众,而不关闭孩子。所以听众仍然记忆犹新。 当我在完整路径上关闭听众时,它就起作用了。