John
John

Reputation: 839

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. 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")
}

Upvotes: 0

Views: 198

Answers (2)

Chris Trahey
Chris Trahey

Reputation: 18290

You may need to use a weak or unowned reference to self in the closure you are giving to your DataService. 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. 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. 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:

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. I don't think you can know that when you're passing to a 3rd party. So use [weak self] and then you'll have to treat self as an optional, which is great for this case!

Upvotes: 1

Manoj
Manoj

Reputation: 1069

This will call your 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)
        }
    }
})

Upvotes: 0

Related Questions