【问题标题】:Alternate between ANY UIViewControllers?在任何 UIViewControllers 之间交替?
【发布时间】:2013-01-20 06:39:13
【问题描述】:

这个问题很长,请耐心等待。

我们知道有两种显示控制器的方法:推送或呈现。还有两个复合控制器:tabbarcontroller 和导航控制器。有了这些可以制作复杂的视图控制器树。 现在我有一个像这样的复杂视图控制器树。

T: 标签栏控制器 N:导航控制器 V:普通视图控制器 P:推 S:在场

所以PV2就是push一个viewcontroller,这是六种组合,但是禁止PN,不能push一个navigation controller。在我研究的时候

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,viewcontroller之间的耦合性很强。 2:不能在复杂的情况下工作……也会导致动画问题。

我的一个朋友告诉我,他们制作了一个 PageConductor,可以轻松地在任何视图控制器之间切换。 这真的让我很困惑......

【问题讨论】:

    标签: ios uiviewcontroller


    【解决方案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 显示用户个人资料”、“显示用户列表”和“在地图上显示某个位置”。人们可能会调整这个基本解决方案以满足他们的应用程序需求,但它的想法是将标签/屏幕管理逻辑与本地控制器逻辑分离。所有操作都返回一个布尔值,指示在此期间是否切换了选项卡,因此客户端代码可以根据此进行一些调整(例如在选项卡更改时弹出其导航堆栈)。

    【讨论】:

    • 1.我在N3.m中导入V3只是为了一句话;我使用通知来解耦,所以 V2 不知道 T,pageConductor 是最好的解决方案,但我不知道如何实现它(就像你说的[screens showUserProfile:userId])。 2.复杂情况的例子是V3出现了一个tabbarcontroller T2,我想跳到V3。它会导致很多动画问题,引用:“至于这种特殊情况下的动画问题,请在弹出 T1 堆栈之前尝试切换到 T3。”这不是一个常见的解决方案。
    • 抱歉这么久才回复,工作比较忙。 1. N3是导航,你实现自己的导航控制器吗?无论如何,这不是行数问题,而是应用程序语义问题。 2. 我不确定我是否在关注您:V3 出现在选项卡 2 上,您想切换到它吗?这里有什么复杂的?至于页面指挥 - 请参阅更新。
    猜你喜欢
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    相关资源
    最近更新 更多