ios - 在任何 UIViewController 之间交替?

标签 ios uiviewcontroller

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

众所周知,有两种显示 Controller 的方法:推送或呈现。还有两个复合 Controller :选项卡 Controller 和导航 Controller 。用这些可以制作复杂的 View Controller 树。 现在我有一个像这样的复杂的 View Controller 树。

T:标签栏 Controller N:导航 Controller V:普通 View Controller 普:推 S:现在

所以PV2的意思是推送一个 View Controller ,这是六种组合,但是PN是被禁止的,你不能推送一个导航 Controller 。当我研究时

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

now the current view controller is V2. i wanna to jump to N3 and push a V3. i wrote this code:

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

它可以工作,但仍然很糟糕,太糟糕了。 1:N3必须知道v3,viewcontroller之间的耦合性很强。 2:它无法在复杂的情况下工作......还会导致动画问题。

我的一个 friend 告诉我,他们制作了一个 PageConductor,可以轻松地在任何 View Controller 之间切换。 这真的让我很困惑......

最佳答案

  1. N3 知道 V3 有什么问题吗?你的意思是 V2 知道 V3 吗?无论如何,我在了解 T 的 V2 中发现了一个更大的问题。如果您确实必须执行此复杂的屏幕流程,请将其委托(delegate)给专用对象(例如您 friend 提到的 PageConductor)。根据用户操作而不是 Controller 操作(例如 [screens showUserProfile:userId] 或其他)来与此对象交谈,这将为您提供 Controller 之间真正的解耦。

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

关于ios - 在任何 UIViewController 之间交替?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14422315/

相关文章:

ios - 从 AppDelegate 向 ViewController 的属性添加值

ios - UIViewController 中的 UIRefreshControl

objective-c - 由于未捕获的异常 'NSInvalidArgumentException' 而终止应用程序,原因 : '-[NSCFString objectForKey:]: unrecognized selector sent to instance

javascript - 如何使用 UIWebView 让 html5 播放器在 Ipad 全屏上播放

ios - 为 CLLocationManager 创建插件

iphone - 如何在 Xcode 4.3.2 中再创建一个 AppDelegate?

ios - StackView插入偏移问题

ios - 使用未声明的类型 "ViewController"

ios - 对于包含 UIDatePicker 的单元格,dequeueReusableCellWithIdentifier 需要 0.5 秒

ios - 界面 View Controller !不符合协议(protocol) "LogicValue"