奇怪的行为让我无法理解 - 当我将第二个视图控制器推到UINavigationController上时,在新视图出现之前有5-10秒的延迟。正在根据NSNotificationCenter通知推送第二个视图控制器。
奇怪:延迟只发生在从后台线程而不是主线程发布事件时(参见下面示例代码中的注释)。
为什么会出现这种延迟?这在模拟器和设备上都会发生。
这是控制台输出。如您所见,所有日志都会及时显示,而不是第二个视图控制器,它在大约5-10秒后突然出现。
2015-04-27 06:58:47.973 DelayedViews[49845:5005806] Background thread started 2015-04-27 06:58:49.978 DelayedViews[49845:5005806] Pushing second view controller 2015-04-27 06:58:49.979 DelayedViews[49845:5005806] Done pushing second view controller 2015-04-27 06:58:49.980 DelayedViews[49845:5005806] In completion block 2015-04-27 06:58:49.980 DelayedViews[49845:5005783] Back on main thread
这是我的简单示例AppDelegate.m,它演示了这个问题。
#import "AppDelegate.h"
@interface AppDelegate ()
@property (nonatomic, strong) UINavigationController *navController;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
self.navController = [[UINavigationController alloc] init];
self.window.rootViewController = self.navController;
UIViewController *vc = self.viewControllerOne;
[self.navController pushViewController:vc animated:YES];
// register for notification center
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pushSecondViewController) name:@"PushSecondVC" object:nil];
// start background thread that posts notification and calls completion block
void (^completion)() = ^void() {
NSLog(@"In completion block");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Back on main thread");
// If I do the notification here, the 2nd view controller is pushed immediately
// [[NSNotificationCenter defaultCenter] postNotificationName:@"PushSecondVC" object:self];
});
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSLog(@"Background thread started");
[NSThread sleepForTimeInterval:2]; // simulate some work
// if the notification is posted here, there is a 5-10 second delay on simulator before second VC appears
// even though the 2nd VC was pushed onto navigationcontroller.
[[NSNotificationCenter defaultCenter] postNotificationName:@"PushSecondVC" object:self];
// call completion block now
completion();
});
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
- (UIViewController*)viewControllerOne {
UIViewController *vc = [[UIViewController alloc] init];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(8, 100, 100, 100)];
label.text = @"View #1";
[vc.view addSubview:label];
return vc;
}
- (UIViewController*)viewControllerTwo {
UIViewController *vc = [[UIViewController alloc] init];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 200, 100, 100)];
label.text = @"View #2";
[vc.view addSubview:label];
return vc;
}
- (void)pushSecondViewController {
NSLog(@"Pushing second view controller");
UIViewController *vc = self.viewControllerTwo;
[self.navController pushViewController:vc animated:YES];
NSLog(@"Done pushing second view controller");
}
@end
答案 0 :(得分:1)
谢谢,A-Live,似乎是它。
我将pushSecondViewController更改为以下内容,现在看起来效果很好。我想知道幕后发生了什么以及为什么这个观点出现需要这么长时间?
- (void)pushSecondViewController {
if (![[NSThread currentThread] isMainThread]) {
dispatch_sync(dispatch_get_main_queue(), ^{
[self pushSecondViewController];
});
return;
}
NSLog(@"Pushing second view controller");
UIViewController *vc = self.viewControllerTwo;
[self.navController pushViewController:vc animated:NO];
NSLog(@"Done pushing second view controller");
}