2011-12-05 17 views
2

ナビゲーションコントローラでいくつかのビューをセットアップしました。私は電話を振ると元のビューに戻ることができるようにしたい。まず、ここで私はAppDelegateで持っているコードスニペットです:なぜpopToRootViewContollerがフリーズしたり、実行に時間がかかりますか?

- (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がなぜポインタであるのか気にしないでください。

+0

ここで役に立つかもしれない、あなたの実際のログを表示する最も簡単な方法は、パラメータを取らない別のメソッドを追加することです。 – tia

+0

ログは単純に3行です...停止、ポッピング、コード内での実行。コードは問題なくこのメソッドを実行します。 – EDJ

答えて

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]; 
} 
+0

didFinishLaunchingWithOptionsから呼び出されます(コードを更新しました)。私はそれがバックグラウンドスレッドかメインであるかはわかりません。申し訳ありませんが、ここでIOSには非常に新しい:) – EDJ

+0

メソッド '-startAcceleratorUpdates'はおそらくメインスレッドで呼び出されますが、コールバックとして定義したブロック(' -startDeviceMotionUpdatesToQueue:withHandler'のwithHandlerパラメータ)はほぼ確実に他のパラメータに渡したキューからのバックグラウンドスレッドを呼び出します。 –

+0

天才、天才!説明と解決策をありがとう。 – EDJ

関連する問題