Coordinating Efforts Between View Controllers--UIApplicationMain 初始化的步骤

Coordinating Efforts Between View Controllers

Few iOS apps show only a single screenful of content. Instead, they show some content when first launched and then show and hide other content in response to user actions. These transitions provide a single unified user interface that display a lot of content, just not all at once.

By convention, smaller pieces of content are managed by different view controller classes. This coding convention allows you to create smaller and simpler controller classes that are easy to implement. However, dividing the work between multiple classes imposes additional requirements on your class designs. To maintain the illusion of a single interface, your view controllers must exchange messages and data to coordinate transitions from controller to another. Thus, even as your view controller classes look inwards to control views and perform the tasks assigned to them, they also look outwards to communicate with other collaborating view controllers.

When Coordination Between View Controllers Occurs

Communication between view controllers is tied to the role those view controllers play in your app. It would be impossible to describe all of the possible interactions between view controllers, because the number and nature of these relationships is dependent on the design of your app. However, it is possible to describe when these interactions occur and to give some examples of the kinds of coordination that might take place in your app.

The lifetime of a view controller has three stages during which it might coordinate with other objects:

View controller instantiation. In this stage, when a view controller is created, an existing view controller or another object was responsible for its creation. Usually, this object knows why the view controller was created and what task it should perform. Thus, after a view controller is instantiated, this intent must be communicated to it.

The exact details of this initial configuration vary. Sometimes, the existing view controller passes data objects to the new controller. At other times, it may configure the presentation style for that, or establish lasting links between the two view controllers. These links allow further communication later in the view controller’s lifetime.

During the view controller’s lifetime. In this stage, some view controllers communicate with other view controllers during their lifetime. The recipient of these messages could be the view controller that created it, peers with similar lifetimes, or even a new view controller that it itself created. Here are a few common designs:

  • The view controller sends notifications that the user performed a specific action. Because this is a notification, the object receiving this message is just being notified that something happened.

  • The view controller sends data to another view controller. For example, a tab bar controller doesn’t establish a built-in relationship between its children, but your app might establish such a relationship when the tabs are displaying the same data object, just in different ways. When a user leaves one tab, the view controller associated with that tab sends the selection information to the view controller about to be displayed. In return, the new view controller uses this data to configure its views so that the transition appears seamless. In this particular case, no new view controller is instantiated by the action. Instead, the two view controllers are peers with the same lifetime and can continue to coordinate as the user switches between them.

  • A view controller sends messages to give another view controller authority over its actions. For example, if a view controller allows users to enter data, it might send messages to allow another controller to decide whether the data the user entered is valid. If the data is invalid, the view controller can disallow the user from accepting the invalid data or adjust its interface to display an error.

View controller destruction. In this stage, many view controllers send messages when their task completes. These messages are common because the convention is for the controller that created a view controller to also release it. Sometimes, these messages simply convey that the user finished the task. At other times, such as when the task being performed generated new data objects, the message communicates the new data back to another controller.

During a view controller’s lifetime, it is common for it to exchange information with other view controllers. These messages are used to notify other controllers when things happen, send them data, or even ask them to exert control over the controller’s activities.


With Storyboards, a View Controller is Configured When It Is Instantiated

Storyboards provide direct support for configuring newly instantiated controllers before they are displayed. When a storyboard instantiates new view controllers automatically, it calls an object in your app to allow it to configure the new controller or to create links to or from the new controller. When your app first launches, the app delegate configures the initial view controller. When a segue is triggered, the source view controller configures the destination view controller.

There are a few conventions used to implement destination view controllers:

  • A destination view controller exposes properties and methods used to configure it.

  • A destination view controller communicates as little as possible with view controllers that it did not create personally. When it does so, these communication paths should use delegation. The destination view controller’s delegate is configured as one of its properties.

Carefully following these conventions helps organize your configuration code and carefully limits the direction of dependencies between view controller classes in your app. By isolating dependencies in your app, you increase the opportunity for code reuse. You also design view controllers that are easier to test in isolation from the rest of your app.


Configuring the Initial View Controller at Launch

If you define a main storyboard in your project, iOS automatically does a lot of work for you to set up your app. When your app calls the UIApplicationMain function, iOS performs the following actions:

  1. It instantiates the app delegate based on the class name you passed into the UIApplicationMainfunction.

  2. It creates a new window attached to the main screen.

  3. If your app delegate implements a window property, iOS sets this property to the new window.

  4. It loads the main storyboard referenced in the app’s information property list file.

  5. It instantiates the main storyboard’s initial view controller.

  6. It sets the window’s rootViewController property to the new view controller.

  7. It calls the app delegate’s application:didFinishLaunchingWithOptions: method. Your app delegate is expected to configure the initial view controller (and its children, if it is a container view controller).

  8. It calls the window’s makeKeyAndVisible method to display the window.


Listing 11-1 shows an implementation of the application:didFinishLaunchingWithOptions: method from the Your Second iOS App: Storyboards tutorial. In this example, the storyboard’s initial view controller is a navigation controller with a custom content controller that displays the master view. The code first retrieves references to the view controller it is interested in. Then, it performs any configuration that could not be performed in Interface Builder. In this example, a custom data controller object is provided to the master view controller by a custom data controller object.

Listing 11-1  The app delegate configures the controller

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UINavigationController *navigationController = (UINavigationController*) self.window.rootViewController;
    BirdsMasterViewController * firstViewController = [[navigationController viewControllers] objectAtIndex:0];
 
    BirdSightingDataController *dataController = [[BirdSightingDataController alloc] init];
    firstViewController.dataController = dataController;
 
    return YES;
}

If your project does not identify the main storyboard, the UIApplicationMain function creates the app delegate and calls it but does not perform any of the other steps described earlier. You would need to write code to perform those steps yourself. Listing 11-2 shows the code you might implement if you needed to perform these steps programmatically.

Listing 11-2  Creating the window when a main storyboard is not being used

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MyStoryboard" bundle:nil];
    MainViewController *mainViewController = [storyboard instantiateInitialViewController];
    self.window.rootViewController = mainViewController;
 
    // Code to configure the view controller goes here.
 
    [self.window makeKeyAndVisible];
    return YES;
}


你可能感兴趣的:(ios,xcode)