1

我正在开发我的第一个应用程序。这是我想要完成的事情:

将有一个包含几个不同选项的菜单。为简单起见,假设它由带有 IBAction 插座的 UIButtons 组成,并且存在随时拉出菜单的功能。

每个菜单按钮在按下时应显示不同的导航控制器内容。如果用户调出菜单并做出不同的选择,他当前操作的导航控制器不应该受到影响;新选择的导航链显示在旧导航链的顶部,通过菜单,用户可以随时返回到上一个导航链离开的视图。

视觉插图(点击以获得更高的分辨率): 视觉的

请注意,有 3 种不同的导航控制器/链。根视图控制器(也是这个简化版本中的菜单)不是其中任何一个的一部分。当导航链之前已实例化时,重新实例化其中一个导航链是不够的,原因如下:如果用户在选项 2 的屏幕 3 上,然后从菜单中选择选项 1,然后(再次)从菜单,他应该正在查看选项 2 的屏幕 3——就在他离开的地方;他之前离开导航链时正在查看的视图控制器应该被带回顶部。

如果没有导航控制器,我可以使按钮实例化并从情节提要中呈现视图控制器:

- (IBAction)buttonPressed:(id)sender {
    UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"View 2"];
    [self presentViewController:controller animated:YES completion:nil];
}

但是,我不知道如何使这两种方法与涉及的导航控制器一起工作。此外,我不确定这两种方法是正确的选择,因为我不会总是想实例化一个新的视图控制器:当按下菜单按钮时,应该执行检查以查看视图(导航?)具有相应标识符的控制器已经被实例化。如果是这样,它应该简单地成为顶视图控制器。

总而言之,这是我的问题:

1) 我应该如何实例化和显示嵌入在导航控制器中的视图控制器,最好使用情节提要 ID?您使用导航控制器或视图控制器的情节提要 ID 吗?

2)我应该如何检查一个实例是否已经存在?同样,我应该检查现有的导航控制器还是视图控制器,最好的方法是什么?

3)如果选定的导航链已经被实例化并且在某处的视图控制器堆栈中,那么将它带到顶部的最佳方法是什么?

谢谢!!

旁注——很高兴知道如何粘贴保留缩进和颜色格式的代码片段:)

4

2 回答 2

1

正如 Rob 所建议的那样,标签栏控制器将为您的设计提供良好的组织原则。

添加一个 UITabBarController 到你的故事板,给它一个故事板 ID。将三组 viewController(及其各自的 navController)中的每组分配给 tabBarController 中的选项卡项。

 UITabBarController
      |--> UINavigationController --> VC1  ---> VC2  -->
      |--> UINavigationController --> VC1  ---> VC2  -->
      |--> UINavigationController --> VC1  ---> VC2  -->

在您的应用程序委托中,创建一个强大的属性来保存您的标签栏控制器的指针。由于选项卡栏控制器保留指向其所有选项卡项的指针,这将处理您的每组视图控制器的状态。您不必为它们中的任何一个保留单独的指针,并且可以通过 tabBarController 的viewControllers属性获取对它们的引用。

@property (strong, nonatomic) UITabBarController* tabVC;

在启动时初始化它

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard storyBoard = 
        [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil];

self.tabVC = [storyBoard instantiateViewControllerWithIdentifier:@"tabVC"];

    //hide the tab bar 
for (UINavigationController* navController in self.tabVC.viewControllers)
    [navController.viewControllers[0] setHidesBottomBarWhenPushed:YES];

    return YES;
}

隐藏选项卡栏的另一种方法是在属性检查器中为每个(初始)viewController 选中“Hides bottom bar on push”框。您不必为后续的 viewController 执行此操作,只需在该选项卡项中看到的第一个。

然后,当您需要导航到其中一个 navController 组时……</p>

- (IBAction)openTab:(UIButton*)sender {

    AppDelegate* appDelegate = 
            (AppDelegate*)[[UIApplication sharedApplication] delegate];

    if ([sender.titleLabel.text isEqualToString: @"Option 1"]) {
        appDelegate.tabVC.selectedIndex = 0;
    }else if ([sender.titleLabel.text isEqualToString: @"Option 2"]){
        appDelegate.tabVC.selectedIndex = 1;
    }else if ([sender.titleLabel.text isEqualToString: @"Option 3"]){
        appDelegate.tabVC.selectedIndex = 2;
    }
    [self presentViewController:appDelegate.tabVC
                       animated:YES completion:nil];
}

(此示例使用presentViewController,您的应用设计可能会以其他方式导航...)

更新

如果您想在没有标签栏控制器的情况下执行此操作,则可以实例化一个包含指向每个导航控制器的指针的数组:

UINavigationController* ncA =
    [storyboard instantiateViewControllerWithIdentifier:@"NCA"];
UINavigationController* ncB =
    [storyboard instantiateViewControllerWithIdentifier:@"NCB"];
UINavigationController* ncC =
    [storyboard instantiateViewControllerWithIdentifier:@"NCC"];

self.ncArray = @[ncA,ncB,ncC];

这样做的好处是没有要隐藏的标签栏……</p>

那么你的选择看起来像……</p>

- (IBAction)openNav:(UIButton*)sender {

    AppDelegate* appDelegate = 
           (AppDelegate*)[[UIApplication sharedApplication] delegate];
    int idx = 0;
    if ([sender.titleLabel.text isEqualToString: @"option 1"]) {
        idx = 0;
    }else if ([sender.titleLabel.text isEqualToString: @"option 2"]){
        idx = 1;
    }else if ([sender.titleLabel.text isEqualToString: @"option 3"]){
        idx = 2;
    }
    [self presentViewController:appDelegate.ncArray[idx]
                       animated:YES completion:nil];
}
于 2013-05-12T00:07:03.297 回答
0

1 /您可以在主 viewController 的 viewDidLoad 方法中实例化一个 viewController,因此它只会实例化 1 次。

现在如果你想显示你的控制器,你最好推动它:

- (IBAction)buttonPressed:(id)sender {
// Declare your controller in your .h file and do :
controller = [self.storyboard instantiateViewControllerWithIdentifier:@"View 2"];
// Note you can move this line in the viewDidLoad method to be called only 1 time

// Then do not use :
// [self presentViewController:controller animated:YES completion:nil];

// Better to use :
[self.navigationController pushViewController:controller animated:YES];
}

2 / 我不确定,但如果你想检查一个实例是否已经存在,只需检查:

if (controller) {
    // Some stuff here
} // I think this checks if controller is initiated.

3 /我知道这不是一个好建议,但我会告诉你不要担心检查你的控制器是否已经存在,因为我认为再次使用 2 行访问你的 viewController 会更容易:

controller = [self.storyboard instantiateViewControllerWithIdentifier:@"View 2"];
[self.navigationController pushViewController:controller animated:YES];

4 /由于特定的样式表,我不确定是否可以在此处使用颜色。

我不确定你的问题是否真的有很好的答案,但我希望这会对你有所帮助。

于 2013-05-11T20:38:41.867 回答