简体   繁体   English

Deinit永远不会被调用,内存问题

[英]Deinit never gets called, Memory issue

So my deinit func never get called, I've already search for an answer, but none of them works for me. 因此,我的deinit func从未被调用过,我已经在寻找答案了,但是它们都不适合我。 And the viewcontroller keep crashing because of memory issue. 而且由于内存问题,视图控制器不断崩溃。 Thanks for your help! 谢谢你的帮助!

Here's my code: 这是我的代码:

@IBOutlet weak var scnView: SCNView!
@IBOutlet weak var artInfoView: UIView!
@IBOutlet weak var mainTitleLbl: UILabel!
@IBOutlet weak var textView: UITextView!
@IBOutlet weak var timeLbl: UILabel!
@IBOutlet weak var stackView: UIStackView!
@IBOutlet weak var artistImg: RoundImage!
@IBOutlet weak var artistNameLbl: UILabel!
@IBOutlet weak var artistView: UIView!

var artRoomScene = ArtRoomScene(create: true)
var artImage = UIImage()
var artInfo: [Any] = []
var posts = [Art]()
var post: Art!
var user: Users!
var showInfo: Bool = false
var showSimilar: Bool = false
let alert = Alerts()

override func viewDidLoad() {
    super.viewDidLoad()

    scnView = self.scnView!
    let scene = artRoomScene
    scnView.scene = scene
    scnView.autoenablesDefaultLighting = true
    scnView.isJitteringEnabled = true
    scnView.backgroundColor = UIColor.white


    if let info = self.artInfo[1] as? Art {
        let image = self.artInfo[0] as? UIImage
        let height = (image?.size.height)! / 900
        let width = (image?.size.width)! / 900
        self.artRoomScene.setup(artInfo: image, height: height, width: width)
        self.mainTitleLbl.text = info.title

        let date = info.postDate/1000
        let foo: TimeInterval = TimeInterval(date)
        let theDate = NSDate(timeIntervalSince1970: foo)
        let time = timeAgoSinceDate(date: theDate as Date, numericDates: true)
        self.timeLbl.text = "\(time)"
        self.textView.text = "\(info.artHeight)'H x \(info.artWidth)'W - \(info.price)$ / month - \(info.type) \n \(info.description)."

        DataService.instance.REF_USERS.child("\(info.userUid)").observe(.value, with: { (snapshot) in
            if let postDict = snapshot.value as? Dictionary<String, AnyObject> {
                let key = snapshot.key
                self.user = Users(key: key, artistData: postDict)

                if let user = self.user {
                    self.artistNameLbl.text = user.name
                    self.artistImg.sd_setImage(with: URL(string: "\(user.profilePicUrl!)") , placeholderImage: UIImage(named:"Placeholder") , options: .continueInBackground)
                }
            }
        })
    }
 }


deinit {
    print("viewcontroller is being deallocated")
}

You may need to use a weak or unowned reference to self in the closure you are giving to your DataService. 在提供给DataService的闭包中,您可能需要使用弱引用或无主引用来对self进行引用。 Or, you may want to look into that code and make sure that it releases it's references to this closure when you expect it to. 或者,您可能希望查看该代码,并确保它在您期望的时候释放对此闭包的引用。 Given the observe verb, I would expect that it holds the reference to this closure indefinitely. 给定observe动词,我希望它会无限期地包含对该闭包的引用。 So I recommend this: 因此,我建议这样做:

  1. Use a weak reference to self in the closure 在闭包中使用弱引用自我
  2. Inside your dealloc, or a some other time like viewWillDisappear, tell the DataService that you wish to unsubscribe/stop observing. 在您的dealloc内,或其他类似viewWillDisappear的时间,告诉DataService您希望退订/停止观察。 This is important so that you don't end up with the opposite problem: A dangling pointer from within your closure. 这很重要,这样您就不会遇到相反的问题:闭包中的悬挂指针。

For #1, the key piece is just inside your closure, Swift has a designated way to declare that self should be a weak pointer: 对于#1,关键部分就在您的闭包内部,Swift有一种指定的方式来声明self应该是一个弱指针:

DataService.instance.REF_USERS.child("\(info.userUid)").observe(.value, with: { (snapshot) in

becomes 变成

DataService.instance.REF_USERS.child("\(info.userUid)").observe(.value, with: { [weak self] (snapshot) in

Note that you could also use [unowned self] , but you would be asserting that you know self will never be non-nil when this block executes. 请注意,您也可以使用[unowned self] ,但是您将断言,知道执行此代码块时self永远不会为非零。 I don't think you can know that when you're passing to a 3rd party. 我认为您传递给第3方时不会知道。 So use [weak self] and then you'll have to treat self as an optional, which is great for this case! 因此,使用[weak self] ,然后必须将self作为可选项,这在这种情况下非常有用!

This will call your deinit 这将调用您的deinit

weak var weakSelf = self
DataService.instance.REF_USERS.child("\(info.userUid)").observe(.value, with: { (snapshot) in
     if let postDict = snapshot.value as? Dictionary<String, AnyObject>, let strongSelf = weakSelf {
        let key = snapshot.key
        strongSelf.user = Users(key: key, artistData: postDict)

        if let user = strongSelf.user {
            strongSelf.artistNameLbl.text = user.name
                strongSelf.artistImg.sd_setImage(with: URL(string: "\(user.profilePicUrl!)") , placeholderImage: UIImage(named:"Placeholder") , options: .continueInBackground)
        }
    }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM