Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Controller doesn't deallocate when ASCollectionNode AsyncDelegate is set #1868

Closed
iwheelbuy opened this issue Jul 8, 2016 · 5 comments
Closed

Comments

@iwheelbuy
Copy link

Hello. I expect all controllers in my project to be deallocated when they are removed from UINavigationController stack. It looks like this:

deinit {
        debugPrint("Deallocated ", self.abstractControllerType)
}

"Deallocated " My.ControllerType.ProfileCity_18
"Deallocated " My.ControllerType.Question_13
"Deallocated " My.ControllerType.Profile_15
"Deallocated " My.ControllerType.Settings_19

But there is one controller that doesn't deallocate and this controller is based on ASCollectionNode. And I've found that it doesn't deallocate only when AsyncDelegate is set

collectionNode.view.asyncDelegate = self

I have no idea how to fix it. Any feedback is welcome.

@hannahmbanana
Copy link
Contributor

hannahmbanana commented Jul 8, 2016

@iwheelbuy: I'm not aware of any issues in ASDK that should cause this. The best way to debug this is probably to use the Memory Graph / Debugger in XCode 8, which allows exploring object's retain relationships. If you provide us with some more code (feel free to post a sample project here or email your code to AsyncDisplayKit@gmail.com) we can try to help out. It's possible that you have inadvertently created a retain cycle.

Also, FYI, in the future you can just do collectionNode.delegate = self.

@appleguy
Copy link
Contributor

appleguy commented Jul 8, 2016

@iwheelbuy check out minute 48:30 in the state of the union, it shows the Memory Graph thing - https://developer.apple.com/videos/play/wwdc2016/102/

Would love to help find your issue if you can share some of your code, or of course a reproduction case. If you set the asyncDelegate / delegate to nil, does it deallocate?

@iwheelbuy
Copy link
Author

Hello again. I've found a place with a retain cycle.

It took me hours to understand that I should carefully explore not only ASCollectionDelegate methods. The retain cycle was in one of ASCollectionDataSource methods:

// MARK: - ASCollectionDataSource

extension CompaniesViewController:ASCollectionDataSource {

    func collectionView(collectionView: ASCollectionView, nodeForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> ASCellNode {

        switch kind {
        case UICollectionElementKindSectionHeader where indexPath.section == 0:
            return self.header
        default:
            return ASCellNode()
        }
    }
}

Anyway, I have fixed a problem.

But now I have a new question:
Why ASCollectionDelegate is responsible for nodeForSupplementaryElementOfKind while it is listed in ASCollectionDataSource?

public protocol ASCollectionDataSource : ASCommonCollectionViewDataSource {

    /**
     * Asks the collection view to provide a supplementary node to display in the collection view.
     *
     * @param collectionView An object representing the collection view requesting this information.
     * @param kind           The kind of supplementary node to provide.
     * @param indexPath      The index path that specifies the location of the new supplementary node.
     */
    optional public func collectionView(collectionView: ASCollectionView, nodeForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> ASCellNode
}

I would love to get an answer for a new question.
Feel free to close the issue. Thanks.

@appleguy
Copy link
Contributor

@iwheelbuy Could you clarify what the retain cycle was? Referencing self in that instance / delegate method should not be an issue...

Regarding the delegate / datasource, that's a good question for @levi. A similar issue is described / fixed here: #1740

@iwheelbuy
Copy link
Author

@appleguy self.header contains an UISearchBar. And there was a custom variable for UISearchBarDelegate. And the variable was strong (without weak prefix). I have removed this UISearchBarDelegate variable and now I set UISearchBar delegate directly.

class CompaniesNodeHeader:ASCellNode {

    private let searchBar:UISearchBar = {
        let searchBar = UISearchBar.init()
        searchBar.placeholder = "Поиск"
        searchBar.returnKeyType = .Done
        searchBar.searchBarStyle = .Minimal
        searchBar.enablesReturnKeyAutomatically = false
        return searchBar
    }()

    // MARK: - Initialization

    override init () {

        super.init()
        view.addSubview(searchBar)
    }

    // MARK: - Public Methods

    func setDelegate(delegate:UISearchBarDelegate?) {

        self.searchBar.delegate = delegate
    }
}

I hope I use a word variable correctly in this context (:

Well, I really hope @levi will fix it some day. I will inform my team about such weird behaviour and we will move firther (:

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants