2012-08-25 34 views
3

我想放在一起一個簡單的容器視圖控制器,這將允許我從任何方向呈現子視圖控制器(從右側像標準導航控制器,也從頂部,底部和左側。從動畫視圖停止transitionFormViewControllerWillAppear

發展新世紀的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 

如果您嘗試運行這段代碼,你會看到從右邊一個新的視圖控制器幻燈片。問題是該視圖控制器視圖的backgroundColor從白色變爲隨機顏色(請參閱viewWillAppear方法SimpleViewController)。我希望該視圖的backgroundColor將立即設置,而不是動畫。

+0

不能在slideViewController方法中設置背景顏色,在該方法中您將SimpleViewController分配給init並設置其視圖的框架? – rdelmar

+0

我教過這些,但我真的想保持能夠分離代碼的邏輯。在子視圖控制器中,我希望在顯示視圖時初始化視圖,而不是在容器視圖控制器中進行初始化。此外,萬一我會從不同的容器視圖控制器類呈現相同的子視圖控制器類,我不想複製初始化代碼。 – quentinadam

回答

2

我發現一種解決方法,通過禁用在viewWillAppear中方法屬性的動畫(參見Disabling implicit animations in -[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]; 
} 

但是我不知道其他人已經遇到了這個問題,如果有更好的方法來解決呢?

0

再想一想,我同意你的評論,最好是把孩子控制器的所有邏輯都保存在它的類中。因此,在您的子控制器中覆蓋init(或者可能是viewDidLoad會起作用),並設置您想要的任何屬性 - 這應該在動畫發生之前設置事件。

+0

這將工作,但我希望能夠執行一些初始化代碼,每次視圖控制器顯示。非常像標準表格視圖和導航控制器:當您從表格中選擇一個項目時,您會在詳細視圖控制器中看到詳細信息。標準做法(來自Apple文檔)是重用相同的詳細視圖控制器對象並在viewWillAppear中執行初始化代碼。這裏的問題是,當使用自定義視圖控制器的遏制時,viewWillAppear方法是動畫的,每當你開始移動子視圖時,看起來很有趣。 – quentinadam