2013-01-20 37 views
0

這個問題很長,所以請耐心等待。任何UIViewControllers之間的替代?

正如我們所知,有兩種顯示控制器的方法:推送或呈現。還有兩個複合控制器:tabbarcontroller &導航控制器。這些可以使複雜的視圖控制器樹。 現在我有一個像這樣的複雜的viewcontroller樹。

T:tabbarcontroller N:navigationcontroller 五:正常的ViewController ,P:推 S:本

所以PV2裝置推的ViewController,這是六種組合,但PN被forbiddened,則無法推送導航控制器。當我研究

 
    T1 
    --------------------- 
    N1  N2  N3 
    |    | 
    PV1    PV3 
    | 
    PV2 

現在當前視圖控制器是V2。我想跳到N3然後推V3。 我寫了這個代碼:

[self.navigationcontroller popToRootViewControllerAnimated:NO]; // No is important 
tabbarcontroller.selectIndex = 2; 
[N3 pushViewController:V3]; 

它的工作原理,但仍然很糟糕,太糟糕了。 1:N3必須知道v3,viewcontrollers之間的耦合是強大的。 2:它不能在複雜的情況下工作......也會導致動畫問題。

我的一位朋友告訴我他們製作了一個PageConductor,可以輕鬆地在任何視圖控制器之間切換。 真的讓我困惑......

回答

1
  1. N3知道V3有什麼問題嗎?你是否認識V2瞭解V3?無論如何,我發現在瞭解T的過程中,V2中存在一個更大的問題。如果您真的需要做這些複雜的屏幕流,請將其委託給專用對象(如您的朋友提到的PageConductor)。根據用戶操作而不是控制器操作(如[screens showUserProfile:userId]或其他)討論這個對象,這會給你一個真正的控制器之間的解耦。

  2. 什麼是「複雜情況」的例子?至於在這個特殊情況下的動畫問題,嘗試在彈出T1堆棧之前切換到T3。

更新

一些假想應用的屏幕管理器的一小人爲的例子。

@implementation ScreenManager { 
} 

@synthesize tabController = _tabController; 

- (BOOL)goToUserList 
{ 
    // user list is a root controller of tab 0 navigation controller 
    BOOL switched = [self switchToTab:0]; 
    UINavigationController *nc = [self rootNavigationAtTab:0]; 
    [nc popToRootViewControllerAnimated:!switched]; // we should animate popping if we didn't change tabs 
    return switched; 
} 

- (BOOL)showUserProfile:(NSUInteger)userId 
{ 
    BOOL switched = [self goToUserList]; 
    UIViewController *uc = [[UserDetailsController alloc] initWithUserId:userId]; 
    UINavigationController *nc = [self rootNavigationAtTab:0]; 
    [nc pushViewController:uc animated:YES]; 
    return switched; 
} 

- (BOOL)showMapAtLocation:(CLLocation *)location 
{ 
    MapController *mc = [self downcast:[self rootControllerAtTab:1] to:[MapController class]]; 
    mc.location = location; 
    return [self switchToTab:1]; 
} 

/* returns if we actually switched tabs as a result of this action */ 
- (BOOL)switchToTab:(NSUInteger)tabIdx 
{ 
    NSUInteger prevTabIdx = _tabController.selectedIndex; 
    _tabController.selectedIndex = tabIdx; 
    return prevTabIdx != tabIdx; 
} 

- (BOOL)pushController:(UIViewController *)controller animated:(BOOL)animated toTab:(NSUInteger)tabIdx 
{ 
    BOOL switchedTabs = [self switchToTab:tabIdx]; 
    UINavigationController *nc = [self rootNavigationAtTab:tabIdx]; 
    [nc pushViewController:controller animated:animated]; 
    return switchedTabs; 
} 

- (UINavigationController *)rootNavigationAtTab:(NSUInteger)tabIdx 
{ 
    return [self downcast:[self rootControllerAtTab:tabIdx] to:[UIViewController class]]; 
} 

- (id)downcast:(id)obj to:(Class)klass 
{ 
    return [obj isKindOfClass:klass] ? obj : nil; 
} 

- (UINavigationController *)rootControllerAtTab:(NSUInteger)tabIdx 
{ 
    return [_tabController.viewControllers objectAtIndex:tabIdx]; 
} 

+ (ScreenManager *)currentManager 
{ 
    static ScreenManager *manager; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
    manager = [ScreenManager new]; 
}); 

    return manager; 
} 


@end 

在這裏,我們提供給用戶3個行動 - 「通過ID顯示用戶配置文件」,「顯示用戶列表」和「在地圖上顯示某個位置」。人們可以調整這個基本的解決方案來滿足他們的應用需求,但是它想要將標籤/屏幕管理邏輯從本地控制器邏輯中分離出來。所有操作都會返回一個布爾值,表示在此期間是否切換了選項卡,以便客戶端代碼可以根據此操作進行一些調整(例如,如果選項卡更改時彈出其導航堆棧)。

+0

1.我在N3.m中只輸入一個句子;我使用notifaition來解耦,所以V2不知道T,pageConductor是最好的解決方案,但我不知道如何實現它(就像你說的'[screen showUserProfile:userId]')。 <\n> 2.複雜情況下的例子是V3提供了一個tabbarcontroller T2,我想跳到V3。它會引發大量的動畫問題,引用:「至於在這種特殊情況下的動畫問題,在彈出T1堆棧之前嘗試切換到T3。「這不是一個普通的解決方案 – Spec

+0

對不起,需要很長時間才能回答,我忙於工作1. N3是導航,你是否實現了自己的導航控制器?無論如何,這不是一個在線數量問題,而是應用程序語義問題。 。我不確定我是否按照你的說法:V3出現在標籤2上,你想切換到它?這裏有些複雜嗎?至於頁面導體 - 請參閱更新。 – hoha

相關問題