Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observe changes in a UIView's subviews array with KVO

I have looked around all over for an answer to this and I have tried to implement it, but nothing is working. Basically, I need to be able to observe changes in a VC view's subviews array. If an existing view is removed from that array, I want to be notified about it and run some code.

Is it possible?

EDIT - More information

I am trying to make a fix for a strange edge case bug where rapidly tapping on the UISearchBar of a UISearchDisplayController (very custom) causes the sdController (or rather the managed searchBar in navBar effect) to disappear from the view, but the sdController is STILL ACTIVE. Which means the navBar stays at the -y origin, and the tableView below isn't scrollable.

My original thought was to get to a state where the sdController was active, but the UISearchDisplayControllerContainerView wasn't in the view hierarchy. I tried testing this in the VC's viewDidLayoutSubviews, but alas, when you tap on a search bar and initiate the sdController animation, the sdController is active, and the UISearchDisplayControllerContainerView isn't in the view hierarchy :(.

like image 683
Lizza Avatar asked Nov 06 '14 18:11

Lizza


3 Answers

You can observe property sublayers of CALayer, which is KVO compliant, instead of UIView subviews.

like image 169
Vladimir Ozerov Avatar answered Nov 12 '22 06:11

Vladimir Ozerov


As with most properties in Apple's frameworks subviews is not KVO compliant.

If you control either the subview or the superview you can observe changes to the view hierarchy by subclassing and overriding:

In the superview you have to override...

- (void)willRemoveSubview:(UIView *)subview

... or, if you control the subview, you would override...

- (void)willMoveToSuperview

Both methods are called before the view is removed.

like image 35
Nikolai Ruhe Avatar answered Nov 12 '22 06:11

Nikolai Ruhe


Swift 3.x

use custom view iike

class ObervableView: UIView {
    weak var delegate:ObservableViewDelegate?

    override func didAddSubview(_ subview: UIView) {
        super.didAddSubview(subview)
        delegate?.observableView(self, didAddSubview: subview)
    }

    override func willRemoveSubview(_ subview: UIView) {
        super.willRemoveSubview(subview)
        delegate?.observableview(self, willRemoveSubview: subview)
    }

}

protocol ObservableViewDelegate: class {
    func observableView(_ view:UIView, didAddSubview:UIView)
    func observableview(_ view:UIView, willRemoveSubview:UIView)
}

//Use

class ProfileViewController1: UIViewController, ObservableViewDelegate {
    @IBOutlet var headerview:ObervableView! //set custom class in storyboard or xib and make outlet connection

    override func viewDidLoad() {
        super.viewDidLoad()
        headerview.delegate = self
    }

    //Delegate methods
    func observableView(_ view: UIView, didAddSubview: UIView) {
        //do somthing
    }

    func observableview(_ view: UIView, willRemoveSubview: UIView) {
        //do somthing
    }
}
like image 2
SPatel Avatar answered Nov 12 '22 08:11

SPatel