iOS: Adding observer to a UIView's frame.origi

2020-07-05 10:56发布

问题:

I'm trying to monitor and react to the changing value of the origin of a UIView's frame. My code:

[cell.bottomView addObserver:self forKeyPath:@"frame.origin" options:NSKeyValueObservingOptionNew context:NULL];

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"%@ Changed", keyPath);
}

I'm getting the following error message that I don't understand:

An instance 0x7587d10 of class NSConcreteValue was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
<NSKeyValueObservationInfo 0x7587fd0> (
<NSKeyValueObservance 0x7587f70: Observer: 0x7587bd0, Key path: origin, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x7587ff0>
)

Really, I'm only interested in the y position of the origin but the code won't even compile if I set the keyPath to "frame.origin.y".

If I set the keyPath to simply "frame", there are no errors but the method observeValueForKeyPath never gets called. I guess a change to a frame's origin doesn't count as a change to the frame..?

How do I accomplish adding an observer to a UIView's frame.origin.y ?

回答1:

Although I could not solve my problem exactly in the way that I initially wanted, I have found out that I am able to add observers correctly to the UIView's center. By monitoring the center of my view I can determine that the frame's origin has changed.

[cell.bottomView addObserver:self forKeyPath:@"center" options:NSKeyValueObservingOptionNew context:NULL];


回答2:

With ReactiveCocoa is as simple as:

[RACObserve(self.view, frame) subscribeNext:^(NSNumber *rect) {
        NSLog(@"position y: %f", rect.CGRectValue.origin.y);
    }];

for example.



回答3:

I don't think it is possible observe only the y value of the frame. But instead of observing the frame property you could overwrite the setFrame: method

Like this:

- (void)setFrame:(CGRect)frame 
{
    [super setFrame:frame]
    if (self.frame.origin.y != frame.origin.y){
         // Do your stuff here
    }
 }


标签: ios frame