为什么popToRootViewContoller会冻结或需要很长时间才能执行?

时间:2011-12-05 16:59:17

标签: iphone uinavigationcontroller ios5

我已使用导航控制器设置了一些视图。我希望能够在握手机时回到原始视图。首先,这是我在AppDelegate中的代码片段:

- (void)startAccelerometerUpdates
{

[motionManager startDeviceMotionUpdatesToQueue:queue withHandler:^(CMDeviceMotion *motion, NSError *error) {
    // based from 
    // http://stackoverflow.com/questions/5214197/simple-iphone-motion-detect/5220796#5220796
    float accelerationThreshold = 1; // or whatever is appropriate - play around with   different values
    CMAcceleration userAcceleration = motion.userAcceleration;
    if (fabs(userAcceleration.x) > accelerationThreshold || 
        fabs(userAcceleration.y) > accelerationThreshold || 
        fabs(userAcceleration.z) > accelerationThreshold) {



        if(!self->isRoot) {
            NSLog(@"Stopping motion manager");
            [motionManager stopDeviceMotionUpdates];
            NSLog(@"popping to top view controller");
            [navcon popToRootViewControllerAnimated:YES];
            NSLog(@"Done popping");
        }

    }

}];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
   .....

   motionManager = [[CMMotionManager alloc] init];
   motionManager.deviceMotionUpdateInterval = .5;

   isRoot = malloc(sizeof(BOOL));
   self->isRoot = NO;
   [self startAccelerometerUpdates];

   [navcon pushViewController:main animated:NO];
   ....
}

我原本以为会立即调用popToRoot。但是,大约需要30秒。有趣的是,您可以按下以手动返回上一页的顶部按钮此时不起作用。手机似乎正在做很多工作来冻结按钮。所以,我肯定在这里做错了。

它认为我可能会多次调用popToRootViewController,所以我在代码中添加了一个“isRoot”检查(请不要分心为什么BOOL是一个指针,我有理由这样做。) / p>

1 个答案:

答案 0 :(得分:4)

您的动作处理程序块似乎打算在后台队列上运行。 UIKit方法(如popToRootViewController)只应在主线程上调用,当你不遵守该规则时的行为通常与你所描述的类似。

-performSelectorOnMainThread:withObject:waitUntilDone是确保您的UIKit代码在主线程上运行的最简单方法,但由于-popToRootViewControllerAnimated:采用非对象参数,因此需要更多工作。最简单的方法是添加另一个不带参数的方法:

-(void)popToRootView {
    [navcon popToRootViewControllerAnimated:YES];
}

然后更新您的块以在主线程上调用该方法:

if(!self->isRoot) {
    [motionManager stopDeviceMotionUpdates];
    [self performSelectorOnMainThread:@selector(popToRootView) withObject:nil waitUntilDone:NO];
}