问题
I'm swizzling willMoveToWindow:
and I came across an issue where it was being called twice on views.
When a new view controller is pushed onto a UINavigationController
,
willMoveToWindow:
is called on the existing view with nil
value (Makes sense since the view is moving offscreen)
After that time, the method willMoveToWindow:
is called again , but now with with the original window.
My initial thought is that swizzling and calling the window
property before the original method has kicked in.
To be on the safe side I've created a small sample project and confirmed the the same behavior.
Basically I need a way to know for sure that the view is not on the window
(Because I am triggering logic when a view is moving to window which in reality shouldn't be run (at least not twice))
For reference the problem can be reproduced with the following code:
@implementation RandomView
-(void)willMoveToWindow:(UIWindow *)newWindow {
// when the new view controller is pushed -
//the method is called twice on the existing view (on the screen view)-
//first time will be called with nil -
//second time with the original window
NSLog(@"********%s <RandomView %p> <Window %p>",__PRETTY_FUNCTION__,self,newWindow);
}
-(void)didMoveToWindow {
NSLog(@"********%s <RandomView %p> <Window %p>",__PRETTY_FUNCTION__,self,self.window);
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
RandomView *k = [[RandomView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:k];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
ViewController *vc = [[ViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
});
});
//[self becomeFirstResponder];
}
@end
EDIT Console
[RandomView willMoveToWindow:] <RandomView 0x7f8b21e16630> <Window 0x7f8b21d220d0>
[RandomView didMoveToWindow] <RandomView 0x7f8b21e16630> <Window 0x7f8b21d220d0>
//THIS IS THE ISSUE
[RandomView willMoveToWindow:] <RandomView 0x7f8b21e16630> <Window 0x0>
[RandomView didMoveToWindow] <RandomView 0x7f8b21e16630> <Window 0x0>
[RandomView willMoveToWindow:] <RandomView 0x7f8b21e16630> <Window 0x7f8b21d220d0>
[RandomView didMoveToWindow] <RandomView 0x7f8b21e16630> <Window 0x7f8b21d220d0>
[RandomView willMoveToWindow:] <RandomView 0x7f8b21e16630> <Window 0x0>
[RandomView didMoveToWindow] <RandomView 0x7f8b21e16630> <Window 0x0>
回答1:
I also facing with the same problem
but after lookup the view hierarchy through responder chain, there is a small different can check. I am not sure this is safe or not.
but I think Apple did the animation code in wrong order, if they add the animation view to window first, the willMoveToWindow:
will not call twice.
2017-03-08 22:49:35.167 view[36189:410065] show
0x7fa9c36059f0,MyView
0x7fa9c3407cb0,UIView
0x7fa9c340b9d0,ViewController
0x7fa9c3403c50,UIViewControllerWrapperView
0x7fa9c340ee90,UINavigationTransitionView
0x7fa9c5802d10,UILayoutContainerView
0x7fa9c381ee00,UINavigationController
0x7fa9c3609c40,UIWindow
0x7fa9c3400020,UIApplication
0x608000038900,AppDelegate
2017-03-08 22:49:54.501 view[36189:410065] hide
0x7fa9c36059f0,MyView
0x7fa9c3407cb0,UIView
0x7fa9c340b9d0,ViewController
0x7fa9c3500bd0,UIView <----- not real hide
2017-03-08 22:49:54.501 view[36189:410065] show
0x7fa9c36059f0,MyView
0x7fa9c3407cb0,UIView
0x7fa9c340b9d0,ViewController
0x7fa9c3500bd0,UIView
0x7fa9c3403c50,UIViewControllerWrapperView
0x7fa9c340ee90,UINavigationTransitionView
0x7fa9c5802d10,UILayoutContainerView
0x7fa9c381ee00,UINavigationController
0x7fa9c3609c40,UIWindow
0x7fa9c3400020,UIApplication
0x608000038900,AppDelegate
2017-03-08 22:49:54.501 view[36189:410065] show
0x7fa9c35062f0,MyView
0x7fa9c3505ae0,UIView
0x7fa9c58030c0,ViewController
0x7fa9c3506c10,_UIParallaxDimmingView
0x7fa9c35022c0,UIView
0x7fa9c3403c50,UIViewControllerWrapperView
0x7fa9c340ee90,UINavigationTransitionView
0x7fa9c5802d10,UILayoutContainerView
0x7fa9c381ee00,UINavigationController
0x7fa9c3609c40,UIWindow
0x7fa9c3400020,UIApplication
0x608000038900,AppDelegate
2017-03-08 22:49:55.037 view[36189:410065] hide
0x7fa9c36059f0,MyView
0x7fa9c3407cb0,UIView
0x7fa9c340b9d0,ViewController <----- real hide
来源:https://stackoverflow.com/questions/34484518/willmovetowindow-is-called-twice