简体   繁体   English

如何从另一个视图控制器呈现视图控制器

[英]How to present a view controller from another view controller

I am trying to open a ViewController from within another ViewController if certain conditions are met. 如果满足某些条件,我试图从另一个ViewController中打开一个ViewController。 The code seems to run without error but the view is never shown. 代码似乎运行没有错误,但视图永远不会显示。 I am new to xcode 4 /ios 5 so I must be missing something. 我是xcode 4 / ios 5的新手,所以我一定会遗漏一些东西。

Here is the code responsible for opening the second viewcontroller: 以下是负责打开第二个viewcontroller的代码:

CreateUserViewController *createUserController = [[CreateUserViewController alloc] initWithNibName:@"CreateUserView" bundle:[NSBundle mainBundle] keyWrapper:keyChainWrapper];

    [self presentViewController:createUserController animated:YES completion:nil];

In my project I have a xib called, "CreateUserView". 在我的项目中,我有一个名为“CreateUserView”的xib。 I have added a view controller to this xib and assigned it to, "CreateUserViewController". 我已经为这个xib添加了一个视图控制器并将其分配给“CreateUserViewController”。

Also I noticed in the apple documentation that is shows setting the delegate of the viewcontroller to be presented. 另外我注意到在apple文档中显示设置要呈现的viewcontroller的委托。 But it seems that no property called, "delegate" is on the viewcontroller object. 但似乎没有名为“delegate”的属性在viewcontroller对象上。 Is this documentation old? 这个文件是旧的吗? This is the document I am trying to use (section 9-1): 这是我试图使用的文件(第9-1节):

View Controller Programming 查看控制器编程

Can someone give me a hint? 有人能给我一个暗示吗? Thanks.. 谢谢..

edit Adding Custom Constructor 编辑添加自定义构造函数

    -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil keyWrapper:(KeychainItemWrapper *)keyWrapper
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if(self){
        [self setKeyChainWrapper:keyWrapper];
    } 
             return self;
}

Regarding CreateUserView.xib : you don't want to put a CreateUserViewController object in the nib. 关于CreateUserView.xib :您不希望在nib中放置CreateUserViewController对象。 You want to set the custom class of the File's Owner placeholder to CreateUserViewController . 您想要将File的Owner占位符的自定义类设置为CreateUserViewController Then you need to connect the view outlet of File's Owner to the top-level view in the nib. 然后,您需要将文件所有者的view插座连接到笔尖中的顶级视图。

Regarding the delegate property: The UIViewController class doesn't have its own delegate property. 关于delegate属性: UIViewController类没有自己的delegate属性。 The idea is that you add a delegate property to your subclass of UIViewController . 这个想法是你将一个delegate属性添加到你的UIViewController的子类。 The delegate provides a way for your presented view controller to pass custom information back to the presenting view controller. 委托为您呈现的视图控制器提供了一种将自定义信息传递回呈现视图控制器的方法。

Why would you want to do that? 你为什么想这么做? Let's consider the code you posted. 让我们考虑一下您发布的代码。 I'll assume you have a UserListViewController that shows a list of User objects, and has a "Create new user" button. 我假设你有一个显示用户对象列表的UserListViewController ,并有一个“创建新用户”按钮。 When the user touches the "Create new user" button, you create a CreateUserViewController and present it. 当用户触摸“创建新用户”按钮时,您将创建一个CreateUserViewController并显示它。

The user interacts with the CreateUserViewController to set the attributes of the new User object - name, rank, hairstyle, etc. Then he touches a "Done" button. 用户与CreateUserViewController交互以设置新User对象的属性 - 名称,等级,发型等。然后他触摸“完成”按钮。 Your CreateUserViewController creates the new User object and puts it in the database. 您的CreateUserViewController创建新的User对象并将其放入数据库中。 Then it needs to dismiss itself, so the UserListViewController 's list of User objects will appear again. 然后它需要解雇自己,因此UserListViewController的User对象列表将再次出现。

But you want the User list to include the newly created User object and you want to scroll the list so that the new User is on the screen. 但是您希望用户列表包含新创建的用户对象,并且您希望滚动列表以便新用户在屏幕上。 So you need a way to have your CreateUserViewController tell the UserListViewController about the newly created User object. 所以你需要一种方法让你的CreateUserViewController告诉UserListViewController关于新创建的User对象。 This is where the delegate comes in. 这是代表进来的地方。

You define a protocol like this: 您定义这样的协议:

@protocol CreateUserViewControllerDelegate

- (void)didCreateUser:(User *)user;

@end

and you give your CreateUserViewController a delegate property: 并为CreateUserViewController提供delegate属性:

@interface CreateUserViewController

@property (weak, nonatomic) id<CreateUserViewControllerDelegate> delegate;

// ...

When your CreateUserViewController 's "Done" button is touched, you notify your delegate of the new User: 触摸CreateUserViewController的“完成”按钮时,您将通知您的新用户代表:

- (IBAction)doneButtonWasTouched:(id)sender {
    User *user = [self createUser];
    [self.delegate didCreateUser:user];
    [self dismissViewControllerAnimated:YES completion:nil];
}

In your UserListViewController , you adopt and implement the protocol: UserListViewController ,您采用并实现协议:

@interface UserListViewController <CreateUserViewControllerDelegate, UITableViewDelegate, UITableViewDataSource>

// ...

@end

@implementation UserListViewController

- (void)didCreateUser:(User *)user {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.users count] inSection:0];
    [self.users addObject:user];
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation: UITableViewRowAnimationAutomatic];
    [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition: UITableViewScrollPositionNone animated:YES];
}

and when you need to present a CreateUserViewController , you set the new controller's delegate to the UserListViewController : 当您需要呈现CreateUserViewController ,将新控制器的委托设置为UserListViewController

- (IBAction)createUserButtonWasTouched:(id)sender {
    CreateUserViewController *createUserController = [[CreateUserViewController alloc] initWithNibName:@"CreateUserView" bundle:[NSBundle mainBundle] keyWrapper:keyChainWrapper];
    createUserController.delegate = self;
    [self presentViewController:createUserController animated:YES completion:nil];
}

In iOS5 the method for pushing new view controllers was really changed around quite a bit from iOS4 and Xcode 3. In summary, storyboards are now used to create your application view controller flow. 在iOS5中,用于推送新视图控制器的方法实际上已经从iOS4和Xcode 3改变了很多。总之,故事板现在用于创建应用程序视图控制器流。 Even though you may use standalone .xib files to build an application it is much less common in iOS5. 即使您可以使用独立的.xib文件来构建应用程序,但在iOS5中它更不常见。

Anyway, the main method for pushing new view controllers onto the screen is done using segues. 无论如何,使用segues完成将新视图控制器推送到屏幕上的主要方法。 Check out this tutorial for an introduction: http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1 查看本教程的介绍: http//www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1

It does a good job on explaining how to create a storyboard and use segues. 它在解释如何创建故事板和使用segue方面做得很好。 You can still present view controllers in code "the old way" but it is much much less common now with the introduction of these new technologies. 你仍然可以用“旧方式”代码呈现视图控制器,但现在引入这些新技术的情况要少得多。 There are also some absolutely awesome tutorials on iTunes U - search for CS193P. iTunes U上还有一些非常棒的教程 - 搜索CS193P。 It's the Stanford Introductory class to Objective-C and programming for iOS. 它是Objective-C的Stanford Introductory类和iOS编程。 This should get you started and maybe help you think of a way to push your createUserController in a way more up to speed with iOS5. 这应该可以让您入门,也许可以帮助您想出一种方法来推动您的createUserController以更快的速度使用iOS5。

UPDATE UPDATE

I just wanted to add. 我只是想补充一下。 If you configure your program to use storyboards and segues you can use the method performSegueWithIdentifier:sender: to perform the segue to your createUserController view if the proper conditions are met. 如果将程序配置为使用故事板和segues,则可以使用方法performSegueWithIdentifier:sender:在满足适当条件的情况下执行segue到createUserController视图。 See the Apple API for UIViewController for information on how to use this method. 有关如何使用此方法的信息,请参阅Apple API for UIViewController。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM