3

子ビューコントローラーを任意の方向から表示できるようにする単純なコンテナービューコントローラーをまとめようとしています(標準のナビゲーションコントローラーのように右から、上、下、左からも配置できます)。

iOS 5向けに開発しているので、親子ビューコントローラーの関係を使用し、transitionFromViewControllerとカスタムアニメーションブロックを使用してビューをスライドさせます。

すべてのメッセージ(viewWillAppearなど)はすべて子ビューコントローラーに正しく渡されますが、問題は、たとえばviewWillAppear、アニメーションループ内から呼び出されているように見えることです(つまり、backgroundColorやサブビューのフレームなどのアニメーション化可能なプロパティを設定した場合) -子ビューコントローラのビューのうち、実際にはアニメーション化されています)。ビューコントローラを表示する前にviewWillAppearメソッドを使用して初期化を実行したいので、この動作は望ましくありません。このコードをアニメーション化したくありません。

これが私のコードの簡略版です:

@implementation ContainerViewController
@synthesize currentViewController;

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor yellowColor];

    self.currentViewController = [[SimpleViewController alloc] init];
    [self addChildViewController:self.currentViewController];
    self.currentViewController.view.frame = self.view.bounds;
    [self.view addSubview:self.currentViewController.view];
}

- (void) slideViewController {
    UIViewController* previousViewController = self.currentViewController;

    UIViewController* viewController = [[SimpleViewController alloc] init];
    viewController.view.frame = CGRectOffset(self.view.bounds, self.view.bounds.size.width, 0);
    [self addChildViewController:viewController];
    [previousViewController willMoveToParentViewController:nil];

    [self transitionFromViewController:previousViewController toViewController:viewController duration:1.0 options:UIViewAnimationOptionTransitionNone animations:^{
        viewController.view.frame = self.view.bounds;
    } completion:^(BOOL finished) {
        [previousViewController removeFromParentViewController];
        [viewController didMoveToParentViewController:self];
    }];

    self.currentViewController = viewController;
}

- (void) loop {
    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        [self slideViewController];
        [self loop];
    });
}

- (void)viewDidAppear:(BOOL)animated {
    [self loop];
}

@end


@implementation SimpleViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
}

- (void)viewWillAppear:(BOOL)animated {
    CGFloat red = (arc4random()%256)/255.0;
    CGFloat green = (arc4random()%256)/255.0;
    CGFloat blue = (arc4random()%256)/255.0;
    self.view.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1];
}

@end

このコードを実行しようとすると、新しいViewControllerが右からスライドするのがわかります。問題は、backgroundColorそのビューコントローラのビューが白からランダムな色にアニメーション化されることです(viewWillAppearの方法を参照SimpleViewController)。backgroundColorビューのはアニメーション化せずにすぐに設定されるようにしたいと思います。

4

2 に答える 2

2

viewWillAppear メソッドでプロパティのアニメーションを無効にすることで回避策を見つけました (詳細については、-[CALayer setNeedsDisplayInRect:]スレッドで暗黙的なアニメーションを無効にするを参照してください) 。

コードを CATransaction 内にラップして、アニメーションなしで変更をコミットできます。

- (void)viewWillAppear:(BOOL)animated {
    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

    CGFloat red = (arc4random()%256)/255.0;
    CGFloat green = (arc4random()%256)/255.0;
    CGFloat blue = (arc4random()%256)/255.0;

    self.view.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1];

    [CATransaction commit];
}

しかし、他の誰かがこの問題に遭遇したのか、それを解決するためのより良い方法があるのだろうか?

于 2012-08-26T18:59:10.097 に答える
0

もう少し考えた後、私はあなたのコメントに同意します。子コントローラーのすべてのロジックをそのクラスに保持する方がよいでしょう。したがって、子コントローラーでinit(またはviewDidLoadが機能する可能性があります)をオーバーライドし、そこに必要な属性を設定します。これにより、アニメーションが発生する前に設定が行われるはずです。

于 2012-08-26T02:07:40.950 に答える