使用模态视图作为“正常”视图

Posted

技术标签:

【中文标题】使用模态视图作为“正常”视图【英文标题】:Use modal view as "normal" view 【发布时间】:2010-09-23 15:51:08 【问题描述】:

我想使用模态视图 (UIViewController) 作为“普通”视图,可以将其推送到导航控制器堆栈上。通常,模态视图是这样呈现的:

LoginViewController *myView = [[MyViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myView];
[self.navigationController presentModalViewController:navController animated:YES];
[myView release];
myView = nil;
[navController release];
navController = nil;

但我想做这样的事情:

[[self navigationController] pushViewController:myView animated:YES];

问题是我的模态视图有一个左右按钮。所以我必须检查视图是如何加载的,并以另一种方式呈现按钮。这背后的想法是有后退按钮。所以我可以多次使用相同的模态视图。

编辑:

@petert:

现在我按照你的例子。我的问题是我使用UINavigationBar 作为模态视图。为了得到这个UINavigationBar,我创建了一个导航控制器。我正在使用导航栏,因为其中有我的按钮。所以检查parentViewController 是否属于UINavigationController 类型对我不起作用。我总是得到一个模态视图。这是我的做法:

// load modal view
MyViewController *myView = [[MyViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myView];
[[self navigationController] presentModalViewController:navController animated:YES];
[navController release];
navController = nil;
[myView release];
myView = nil;


// load as normal view
MyViewController *myView = [[MyViewController alloc] init];
[[self navigationController] pushViewController:myView animated:YES];

【问题讨论】:

【参考方案1】:

此 *** 中的好提示 answer。

我更喜欢使用UIViewController的属性:

@property(nonatomic, readonly) UIViewController *parentViewController

在视图控制器的子类中:

查看控制器的parentViewController 属性的值。如果它是UINavigationController 的实例,那么您就在导航堆栈中。如果您以模态方式显示,它将是您最后一个视图控制器的实例。

所以以-viewDidLoad 为例:

- (void)viewDidLoad

   if ([self.parentViewController isKindOfClass:[UINavigationController class]])
     
        // navigation controller
        self.title = @"...";
     
   else
     
        // modal
        self.title = @"Modal";

        // add cancel and done buttons now...
     

或者,一个非常简单的解决方案是将您的 init 方法自定义到您的 MyViewController 类,以编码您对视图控制器的意图。

将以下内容添加到MyViewController 标头:

@interface MyViewController : UIViewController

  BOOL modal;


- (id)initForModal:(BOOL)isModal;

@end

现在在实现文件中:

@interface MyViewController ()
@property (nonatomic) BOOL modal;
@end

@implementation MyViewController

@synthesize modal;

- (id)initForModal:(BOOL)isModal;

  if (self = [super initWithNibName:@"MyViewController" bundle:nil])
    
      self.modal = isModal;
    

  return self;


- (void)viewDidLoad

  [super viewDidLoad];

  if (self.modal)
    
      // add cancel and done buttons …
    
  else
    
      // assuming we're presented from a navigation view …
    

现在以模态方式使用:

// load modal view
MyViewController *myView = [[MyViewController alloc] initForModal:YES];

或非模态:

// load as normal view
MyViewController *myView = [[MyViewController alloc] initForModal:NO];

我假设您是从 NIB 创建视图控制器,但一如既往地看到 View Controller Progamming Guide for ios,尤其是标题为“定义自定义视图控制器类”的部分。

【讨论】:

感谢您提供的示例代码。我认为它会很好用,但我使用UINavigationController 来展示我的模态视图。我为什么要这样做在我编辑的问题中进行了解释。也许你可以提供一个解决方案。 您的支持很棒!这个解决方案非常简单并且效果很好。现在有一些问题需要我的理解:1)为什么要在实现文件中做一个新的接口声明? 2) initForModal 中的 if 调用超级构造函数,如果成功则返回对象 (ViewController),否则返回 nil。它是否正确?在if 语句中,如果对象不为零,则仅设置一个选项。 3)我需要这里的属性,因为变量在方法边界上方使用? 很高兴它很有帮助 - 1)它隐藏了 modal 属性,因为它不能在这个类实现之外使用; 2) 是的,绝对是 init 方法的通用 obj-c 风格; 3)我使用属性只是为了让事情变得更简单,我认为你的问题的答案是肯定的?记得给答案投票,如果有帮助,谢谢。【参考方案2】:

澄清一下:myView 不是模态的。您只需将其呈现为模态的。

如果您只是将它推入 UINavigationController 层次结构,它的行为将像“正常”的那样。

您不能将同一个视图控制器多次推送到导航堆栈上。就一次。

有关如何自定义视图,另请参阅此内容:

SO modal question

【讨论】:

好的,我将它呈现为模态视图。你有一个“真实”模式视图的例子吗?我不想同时将它推入堆栈。只有一次是什么意思?我可以把它作为普通视图放在堆栈上,但以后不能作为模态视图?

以上是关于使用模态视图作为“正常”视图的主要内容,如果未能解决你的问题,请参考以下文章

导航栏视图作为模态视图?

iTunes Store 作为模态视图

模态视图控制器使背景变黑

Unwind segues 不适用于模态视图控制器

模态视图的 Ipad 方向问题

将视图作为参数传递给按钮,将其作为模态触发