nicklockwood / layout

A declarative UI framework for iOS
MIT License
2.23k stars 97 forks source link

use ivar instead of getter of viewController #166

Closed flexih closed 5 years ago

flexih commented 5 years ago
public extension LayoutLoading where Self: UIViewController {
    /// Default layoutNode implementation for view controllers
    var layoutNode: LayoutNode? {
        get {
            return objc_getAssociatedObject(self, &layoutNodeKey) as? LayoutNode
        }
        set {
            layoutNode?.unmount()
            objc_setAssociatedObject(self, &layoutNodeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            layoutNode?.unmount()
            if let layoutNode = layoutNode {
                do {
                    try layoutNode.mount(in: self)
                    layoutDidLoad(layoutNode)
                } catch {
                    layoutError(LayoutError(error, for: layoutNode))
                }
            }
        }
    }
}

second unmount() calls viewControllers

    public func unmount() {
        guard parent == nil else {
            // If not a root node, treat the same as `removeFromParent()`
            // TODO: should this be an error instead?
            removeFromParent()
            return
        }
        unbind()
        for controller in viewControllers {
            controller.removeFromParent()
        }
        _view?.removeFromSuperview()
    }
    public var viewControllers: [UIViewController] {
        guard let viewController = viewController else {
            return children.flatMap { $0.viewControllers }
        }
        return [viewController]
    }

which calls setUpExpressions() even before mount(in:) calls.

    public var viewController: UIViewController? {
        if _class is UIViewController.Type {
            attempt(setUpExpressions)
        }
        return _viewController
    }
coveralls commented 5 years ago

Coverage Status

Coverage increased (+1.1%) to 59.105% when pulling b0a4ee5cd95cb5feed8d37e23044acb38083ea86 on flexih:master into 2c6d11a01ebc8e48953b6a838773656314b63ae0 on schibsted:master.

nicklockwood commented 5 years ago

@flexih thanks for catching this. I think I want to retain the behavior that calling viewControllers initializes the view though.

The solution is probably to extract the logic for the viewControllers getter into a private method that doesn't do that, but I'll think on it some more.

flexih commented 5 years ago

The fix code breaks the getter rule, needs a better solution :)

nicklockwood commented 5 years ago

@flexih I’ve pushed an alternative fix to the develop branch - does that work for you?

flexih commented 5 years ago

Yes, it works. Thanks.