我需要在我的自定义UIView子类的绝对帧时得到通知(不仅相对于其父级的帧,而且当superview&#s; / grandsuperview' s等帧发生变化时,我的视图和#39;要更改的帧)屏幕上的更改。我尝试在convertRect:toView:
,-(void)didMoveToSuperview
获取绝对帧-(void)didMoveToWindow
,并且我还在这两个内添加了此代码:
UIView *view = self.superview;
while (view) {
[view addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
[view addObserver:self forKeyPath:@"superview" options:NSKeyValueObservingOptionNew context:nil];
view = view.superview;
}
它们都被称为几次(这没关系),但我得到的坐标不正确。在所有设置实际可见帧的代码后,运行其他东西。我通过将其放入我的代码来验证这一点:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CGRect globalFrame = [view.superview.superview convertRect:view.superview.frame toView:[[view.delegate tutorialView] superview]];
NSLog(@"after 2 sec %@", NSStringFromCGRect(globalFrame));
if([view.delegate respondsToSelector:@selector(attachedViewFrameDidChange:)]){
[view.delegate attachedViewFrameDidChange:globalFrame];
}
});
忘记view.delegate
和我的其他自定义参数/对象/方法。两秒钟后,我在globalFrame
中获得了正确的值。我在-(void)didMoveToSuperview
,-(void)didMoveToWindow
,-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
中使用完全相同的代码,并且调用错误的帧值(在调用convertRect:toView:
时获取的值不正确。)为什么这样是的,我怎样才能得到绝对/真实的帧值(我在屏幕上看到的那个),因为我在两秒后得到了,显然没有等待?
答案 0 :(得分:1)
我认为您可以通过使自定义视图成为视图控制器的委托,并在viewDidLayoutSubviews中调用委托方法来实现此目的。所以,在视图controller.h中,我有了这个,
@protocol UIViewControllerLayoutChanged <NSObject>
-(void)layoutChanged;
@end
@interface ViewController : UIViewController
@property (weak,nonatomic) id<UIViewControllerLayoutChanged> delegate;
@end
在.m文件中,
- (void)viewDidLoad {
[super viewDidLoad];
[self setDelegate:(RDLabel *)self.label]; // self.label is the view I want to be notified when its absolute frame changes
}
-(void)viewDidLayoutSubviews {
[self.delegate layoutChanged];
}
在我的自定义视图类中,
-(void)layoutChanged {
NSLog(@"%@",NSStringFromCGRect([self.superview convertRect:self.frame toView:nil]));
}
每当我改变它时,这给了我正确的绝对帧。当然,每当任何视图需要重新布局时,即使它不涉及您关注的视图,也会调用viewDidLayoutSubviews。要处理这个问题,您可能需要在自定义类的代码中保留对框架的引用,并且只有在框架从旧值更改时才需要执行任何操作。