Phát triển ứng dụng cho iPhone và iPad - part 14 doc

10 304 0
Phát triển ứng dụng cho iPhone và iPad - part 14 doc

Đang tải... (xem toàn văn)

Thông tin tài liệu

Changes to the RootViewController Now you need to move on to the RootViewController . Here, you will add an NSMutableArray* to hold the collection of surveys. You cannot simply use an NSArray because you will need to be able to add surveys to the collection on - the - fl y. Remember, NSArray is immutable, meaning that once you have created it, you cannot modify it. In the RootViewController header fi le, add an instance variable called surveyDataArray of type NSMutableArray *: NSMutableArray* surveyDataArray; Add a property for your new surveyDataArray : @property (nonatomic, retain) NSMutableArray* surveyDataArray; Switch over to the RootViewController implementation fi le and modify the @synthesize statement to synthesize your new surveyDataArray property: @synthesize detailViewController ,surveyDataArray ; Modify the viewDidUnload and dealloc methods to clean up your new property: - (void)viewDidUnload { // Relinquish ownership of anything that can be recreated in viewDidLoad or // on demand. // For example: self.myOutlet = nil; self.surveyDataArray = nil; } - (void)dealloc { [detailViewController release]; [surveyDataArray release]; [super dealloc]; } RootViewController.m Finally, modify the viewDidLoad method to create and initialize the NSMutableArray : - (void)viewDidLoad { [super viewDidLoad]; self.clearsSelectionOnViewWillAppear = NO; self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0); NSMutableArray* array = [[NSMutableArray alloc] init]; self.surveyDataArray = array; [array release]; } RootViewController.m Displaying Master/Detail Data with the UISplitViewController ❘ 99 CH004.indd 99CH004.indd 99 9/18/10 9:30:30 AM9/18/10 9:30:30 AM 100 ❘ CHAPTER 4 IPAD INTERFACE ELEMENTS Modify the TableView Methods The next step is to modify the Table View datasource methods to use the surveyData array as the UITableView ’ s datasource. First, you will need to update the tableView:numberOfRowsInSection: method to return the number of items in the array, like this: - (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [self.surveyDataArray count]; } RootViewController.m Now, you should change the tableView:cellForRowAtIndexPath: method to get data from the surveyDataArray to use as the text in the table cells: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @”CellIdentifier”; // Dequeue or create a cell of the appropriate type. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; cell.accessoryType = UITableViewCellAccessoryNone; } // Configure the cell. NSDictionary* sd = [self.surveyDataArray objectAtIndex:indexPath.row]; cell.textLabel.text = [NSString stringWithFormat:@”%@, %@”, [sd objectForKey:@”lastName”], [sd objectForKey:@”firstName”]]; return cell; } RootViewController.m In this method, you get an NSDictionary object from the surveyDataArray with an index based on the row that the table has requested. Then, you get the lastName and firstName strings from the dictionary and display them in the cell ’ s textLabel . The last thing that you need to do in the Table View methods is to update the tableView: didSelectRowAtIndexPath: method. In this method, you need to set the detailItem in the detailViewController to the NSDictionary that you retrieve from the surveyDataArray . This passes the data that you want to display, the survey that the user has chosen, to the DetailViewController . Remember that the setter for the detailItem property contains code; CH004.indd 100CH004.indd 100 9/18/10 9:30:30 AM9/18/10 9:30:30 AM it is not just a synthesized property. This code calls the configureView method that updates the view to display the record that the user has chosen. Here is the code for the tableView: didSelectRowAtIndexPath: method: - (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { /* When a row is selected, set the detail View Controller’s detail item to the item associated with the selected row. */ [aTableView deselectRowAtIndexPath:indexPath animated:NO]; NSDictionary* sd = [self.surveyDataArray objectAtIndex:indexPath.row]; detailViewController.detailItem = sd; } RootViewController.m Adding Surveys To complete this example, you will add code to the project to enable the user to add surveys to the application. In the RootViewController header, you will need to declare a method to add a survey. You should call this method addSurveyToDataArray and the signature should look like this: -(void) addSurveyToDataArray: (NSDictionary*) sd; Recall that you are using an NSDictionary to hold the data for each survey. Therefore, the addSurveyToDataArray method accepts an NSDictionary* that holds the survey data that you want to add to the array of completed surveys. Next, switch over to the RootViewController implementation. You should implement the addSurveyToDataArray function as follows: -(void) addSurveyToDataArray: (NSDictionary*) sd { NSLog (@”addSurveyToDataArray”); // Add the survey to the results array [self.surveyDataArray addObject:sd]; // Refresh the tableview [self.tableView reloadData]; } RootViewController.m This method simply adds the dictionary object that it receives to the surveyDataArray . Then, because the user has modifi ed the data for the Table View, you need to tell the Table View to reload its data in order to refresh the display and show the new survey. Displaying Master/Detail Data with the UISplitViewController ❘ 101 CH004.indd 101CH004.indd 101 9/18/10 9:30:31 AM9/18/10 9:30:31 AM 102 ❘ CHAPTER 4 IPAD INTERFACE ELEMENTS Now, you need to move over to the DetailViewController to implement the addSurvey method. This method runs when the user taps the Add button in the user interface. First, however, you will need to add #import statements to the DetailViewController header to import the RootViewController and SurveyAppDelegate headers: #import “RootViewController.h” #import “SurveyAppDelegate.h” DetailViewController.h Now you can move into the DetailViewController implementation to implement the addSurvey method: -(IBAction)addSurvey:(id)sender { NSLog (@”addSurvey”); // Create a new NSDictionary object to add to the results array of the root // View Controller // Set the values for the fields in the new object from the text fields of // the form NSArray *keys = [NSArray arrayWithObjects:@”firstName”, @”lastName”, @”address”, @”phone”, @”age”, nil]; NSArray *objects = [NSArray arrayWithObjects:self.firstNameTextField.text, self.lastNameTextField.text, self.addressTextField.text, self.phoneTextField.text, [NSNumber numberWithInteger:[ self.ageTextField.text intValue]], nil]; NSDictionary* sData = [[NSDictionary alloc] initWithObjects:objects forKeys:keys]; // Get a reference to the app delegate so we can get a reference to the // Root View Controller SurveyAppDelegate* appDelegate = [[UIApplication sharedApplication] delegate]; RootViewController* rvc = appDelegate.rootViewController; // Call the addSurveyToDataArray method on the rootViewController to // add the survey data to the list [rvc addSurveyToDataArray:sData]; // Clean up [sData release]; } DetailViewController.m CH004.indd 102CH004.indd 102 9/18/10 9:30:31 AM9/18/10 9:30:31 AM In this method, you need to build an NSDictionary that you will pass to the RootViewController to add to the surveyDataArray . To create the dictionary, you fi rst create two NSArray s, one for the keys of the dictionary and one for the related objects. The keys can be any arbitrary NSString s. You obtain the objects for the dictionary from the UITextField objects that you added in Interface Builder. Once you have built your arrays, you create an NSDictionary by passing in the objects array and the keys array. Next, you need to call the addSurveyToDataArray method on the RootViewController . If you remember, the RootViewController holds a reference to the DetailViewController . However, the DetailViewController does not hold a reference to the RootViewController . There are a couple of ways that you can remedy this. For this example, I have chosen to simply get a reference to the RootViewController from the SurveyAppDelegate . You can get a reference to the app delegate at any time by calling the delegate method on the application ’ s UIApplication object. UIApplication is the core object at the root of all iPhone and iPad applications. UIApplication is a singleton class to which you can obtain a reference by calling the sharedApplication method. Once you obtain a reference to the application, you can call its delegate method to get a reference to your application delegate. In this case, the delegate holds references to both the RootViewController and the DetailViewController . The code then goes on to get a reference to the RootViewController from the application delegate. Finally, you call the addSurveyToDataArray method on the RootViewController to add the newly created survey dictionary to the array. You are now ready to build and run the application. You should be able to add new surveys and see them appear in the left hand pane in portrait mode. Select an item in the list and you will see the display in the right - hand pane change to the item you selected. Rotate the device to see how the UISplitViewController behaves in both landscape and portrait modes. DISPLAYING DATA IN A POPOVER Another user interface element that is new and unique to the iPad is the UIPopoverController . You can use this controller to display information on top of the current view. This allows you to provide context - sensitive information on top of the main application data without swapping views as would be required in an iPhone application. The UISplitViewController uses a UIPopoverController to display the master data list when the device is in portrait orientation and the user taps the button to disclose the master list. For example, when your Survey application is in portrait orientation and the user taps the Root List button, the RootViewController is displayed in a UIPopoverController . Another interesting feature of the popover is that the user can dismiss it by simply tapping outside its bounds. Therefore, you can use this controller to display information that might not necessarily require any user action. In other words, the user does not have to implicitly accept or cancel any action to dismiss the popover. The UIPopoverController displays a UIViewController as its content. You can build the content view in any way that you wish. You should, however, consider the size of the popover as you are building the view that it will contain. You should also consider the position in which you want to Displaying Data in a Popover ❘ 103 CH004.indd 103CH004.indd 103 9/18/10 9:30:32 AM9/18/10 9:30:32 AM 104 ❘ CHAPTER 4 IPAD INTERFACE ELEMENTS show the popover. You should display a popover next to the user interface element that displayed it. When presenting a popover, you can either attach it to a toolbar button or provide a CGRect structure to give the popover a reference location. Finally, you can specify the acceptable directions for the arrow that points from the popover to the reference location. You should generally permit UIKit to control the location of the popover by specifying UIPopoverArrowDirectionAny as the permitted direction for the arrow. In this section, you will create a UIPopoverController and display it in the Survey application. The popover will simply display a new UIViewController that will show some helpful information on performing surveys, as you can see in Figure 4 - 6. FIGURE 4 - 6: The Survey Application Informational Popover Building the InfoViewController The UIPopoverController is a container that you can use to display another View Controller anywhere on the screen on top of another view. Therefore, the fi rst thing that you need to do when you want to display content in the popover is build the View Controller that you would like to CH004.indd 104CH004.indd 104 9/18/10 9:30:33 AM9/18/10 9:30:33 AM display. For the Survey application, you will create a new class called InfoViewController . Then, you will display this class in a UIPopoverController when the user taps an informational button. The fi rst step is to create your new class. Add a new UIViewController subclass called InfoViewController to your project. As you add the class, make sure that the “ Targeted for iPad ” and “ With XIB for user interface ” checkboxes in the New File dialog box are selected. Open your new InfoViewController header fi le. Add a UILabel* instance variable called infoLabel . Then, add an IBOutlet property that you can use to set and get your new instance variable. Finally, add a method signature for a new method called setText . You will use the setText method to set the text that you want to display in the popover. The header fi le for the InfoViewController should look like this: #import < UIKit/UIKit.h > @interface InfoViewController : UIViewController { UILabel* infoLabel; } @property (nonatomic, retain) IBOutlet UILabel* infoLabel; -(void) setText: (NSString*) text; @end InfoViewController.h Next, you will open the InfoViewController XIB fi le with Interface Builder to build the user interface for the new View Controller. Double - click on the InfoViewController XIB fi le to open it in Interface Builder. For this application, the user interface will be extremely simple, just a lone UILabel . However, you can build views that are as complex as you want with Interface Builder and use the methodology outlined here to display those interfaces using popovers. Once you have the XIB fi le opened in Interface Builder, open the Attributes inspector for the View by pressing Command+1 or selecting Tools ➪ Attributes Inspector from the menu bar. Make sure that you have the View selected. In the Attributes Inspector, set the Status Bar attribute to Unspecifi ed because you do not want the view to have a status bar. Then, using the Size Inspector, which you can open by pressing Command+3 or selecting Tools ➪ Size Inspector from the menu bar, resize the view to a width of 320 pixels and a height of 175 pixels. Now that you have the view confi gured correctly, add a UILabel control and resize it to fi ll most of the view. The exact size and position are not particularly important for this example. Finally, connect the new UILabel to the infoLabel property of File ’ s Owner. This connects your code to the interface that you built in Interface Builder. You can now save your InfoViewController XIB fi le and close Interface Builder. Displaying Data in a Popover ❘ 105 CH004.indd 105CH004.indd 105 9/18/10 9:30:34 AM9/18/10 9:30:34 AM 106 ❘ CHAPTER 4 IPAD INTERFACE ELEMENTS Now, you will need to add some logic to the InfoViewController implementation fi le. First, you should add code to the viewDidUnload and dealloc methods to clean up the instance variable and property of the class: - (void)viewDidUnload { [super viewDidUnload]; self.infoLabel = nil; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (void)dealloc { [infoLabel release]; [super dealloc]; } InfoViewController.m Next, add a line to synthesize the infoLabel property: @synthesize infoLabel; The next step is to implement the viewDidLoad method. In this method, you will set the size of the View Controller to display in the popover. Here is the code: - (void)viewDidLoad { [super viewDidLoad]; CGSize size; size.width=320; size.height = 175; self.contentSizeForViewInPopover = size; } InfoViewController.m The original size of the popover comes from the View Controller ’ s contentSizeForViewInPopover property. The default size for a UIPopoverController is 320 pixels by 1100 pixels. There are two ways that you can change the size of the popover. First, you can set the size in the View Controller that the popover will hold by setting the View Controller ’ s size using the contentSizeForViewInPopover property. Alternatively, you can set the size of the popoverContentSize property of the Popover Controller. Keep in mind that if you use this method and change the View Controller that you are displaying in the popover, the popover will automatically resize to the size of the new View Controller. The custom size that you set in the popoverContentSize property is lost. CH004.indd 106CH004.indd 106 9/18/10 9:30:34 AM9/18/10 9:30:34 AM In this example, you created a CGSize struct to defi ne the size of the popover in the View Controller. You set the size to 320 pixels wide by 175 pixels high. Then, you set the contentSizeForViewInPopover property on the View Controller. Finally, you need to implement the setText method that clients who want to display the InfoViewController will use to set the text to display. This method does nothing more than set the text in the UILabel : -(void) setText: (NSString*) text { self.infoLabel.text = text; } InfoViewController.m Displaying the UIPopoverController Now that you have a View Controller, you need to display it in a popover. You will display the popover when the user taps a button in the DetailViewController . Therefore, you will need to make some changes to the DetailViewController header fi le. First, add a #import statement for the new InfoViewController.h header fi le: #import “InfoViewController.h” Next, you will add a new action method called showInfo . The user will invoke this method when he taps on the information button in the user interface. Here is the declaration: -(IBAction)showInfo:(id)sender; The next step is to add a new outlet and instance variable for the UIButton* called infoButton . Inside of the interface declaration, add the instance variable for the UIButton* : UIButton* infoButton; Outside of the interface declaration, declare the infoButton property: @property (nonatomic, retain) IBOutlet UIButton* infoButton; Now add an instance variable for the UIPopoverController . Call it infoPopover : UIPopoverController *infoPopover; Add a property for the infoPopover : @property (nonatomic, retain) UIPopoverController *infoPopover; Now you need to move over to the DetailViewController implementation fi le. Displaying Data in a Popover ❘ 107 CH004.indd 107CH004.indd 107 9/18/10 9:30:35 AM9/18/10 9:30:35 AM 108 ❘ CHAPTER 4 IPAD INTERFACE ELEMENTS In the implementation, synthesize the new infoButton and infoPopover properties: @synthesize infoButton,infoPopover; Next, you will implement the showInfo method to show the InfoViewController in the infoPopover : -(IBAction)showInfo:(id)sender { NSLog (@”showInfo”); // Instatiate Info View Controller InfoViewController *ivc = [[InfoViewController alloc] init]; UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:ivc]; [ivc setText:@”If the survey taker refuses, that is okay”]; [ivc release]; // Set the infoPopover property self.infoPopover = popover; // Clean up the local popover [popover release]; [self.infoPopover presentPopoverFromRect:self.infoButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } DetailViewController.m The fi rst thing that you do in this method, after logging the method name, is create an instance of the InfoViewController . Next, you allocate a UIPopoverController and initialize it by calling the initWithContentViewController method. You pass the View Controller that you want to display in the popover as a parameter to this method. Next, you set the text that you want to display in the popover and release the InfoViewController . You must send the InfoViewController the release message or you will leak memory. When you pass the View Controller in to the popover in the initWithContentViewController method, the popover will retain the View Controller. The next step is to set the infoPopover property to the new popover that you created in this method. Then, you can release the local popover. Finally, you call the presentPopoverFromRect:inView:permittedArrowDirections:animated: method to present the popover. The fi rst parameter to this method specifi es the CGRect structure from which the popover should emanate. In this example, you use the frame of the info button CH004.indd 108CH004.indd 108 9/18/10 9:30:35 AM9/18/10 9:30:35 AM . simply use an NSArray because you will need to be able to add surveys to the collection on - the - fl y. Remember, NSArray is immutable, meaning that once you have created it, you cannot modify. - (void)viewDidUnload { // Relinquish ownership of anything that can be recreated in viewDidLoad or // on demand. // For example: self.myOutlet = nil; self.surveyDataArray = nil; } -. updates the view to display the record that the user has chosen. Here is the code for the tableView: didSelectRowAtIndexPath: method: - (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath

Ngày đăng: 04/07/2014, 21:20

Tài liệu cùng người dùng

Tài liệu liên quan