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

10 319 0
Phát triển ứng dụng cho iPhone và iPad - part 9 potx

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

Thông tin tài liệu

each time, but parameterized queries offer the performance advantage of preparing and compiling the statement once and the statement being cached for reuse. Writing to the Database If you modify the sample application, or create your own SQLite application that attempts to write to the database, you will have a problem. The version of the database that you are using in the sample code is located in the application bundle, but the application bundle is read - only, so attempting to write to this database will result in an error. To be able to write to the database, you need to make an editable copy. On the iPhone, this editable copy should be placed in the documents directory. Each application on the iPhone is “ sandboxed ” and has access only to its own documents directory. The following code snippet shows how to check to see if a writable database already exists, and if not, create an editable copy. // Create a writable copy of the default database from the bundle // in the application Documents directory. - (void) createEditableDatabase { // Check to see if editable database already exists BOOL success; NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error; NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [paths objectAtIndex:0]; NSString *writableDB = [documentsDir stringByAppendingPathComponent:@”ContactNotes.sqlite”]; success = [fileManager fileExistsAtPath:writableDB]; // The editable database already exists if (success) return; // The editable database does not exist // Copy the default DB to the application Documents directory. NSString *defaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@”Catalog.sqlite”]; success = [fileManager copyItemAtPath:defaultPath toPath:writableDB error: & error]; if (!success) { NSAssert1(0, @”Failed to create writable database file:’%@’.”, [error localizedDescription]); } } You would then need to change your database access code to call this function and then refer to the editable copy of the database instead of the bundled copy. Connecting to Your Database ❘ 49 CH002.indd 49CH002.indd 49 9/20/10 2:31:41 PM9/20/10 2:31:41 PM 50 ❘ CHAPTER 2 THE IPHONE AND IPAD DATABASE: SQLITE Displaying the Catalog Now that you have the DBAccess class done, you can get on with displaying the catalog. In the RootViewController , you will implement code to retrieve the products array from the DBAccess class and display it in the TableView . In the header, RootViewController.h , add import statements for the Product and DBAccess classes: #import “Product.h” #import “DBAccess.h” Add a property and its backing instance variable to hold your products array: @interface RootViewController : UITableViewController { // Instance variable to hold products array NSMutableArray *products; } @property (retain,nonatomic) NSMutableArray* products; Notice that the products property is declared with the retain attribute. This means that the property setter method will call retain on the object that is passed in. You must specify the retain attribute to ensure that the products array is available for use when you need it. Recall that in the DBAccess class, you called autorelease on the array that is returned from the getAllProducts method. If you did not add the retain attribute, the products array would be released on the next pass through the application event loop. Trying to access the products property after the array is released would cause the application to crash. You avoid this by having the setter call retain on the array. In the RootViewController.m implementation class, you need to synthesize the products property below the @implementation line: @synthesize products; Synthesizing a property causes the compiler to generate the setter and getter methods for the property. You can alternatively defi ne the getter, setter, or both methods yourself. The compiler will fi ll in the blanks by defi ning either of these methods if you don ’ t. Continuing in the RootViewController.m implementation class, you ’ ll add code to the viewDidLoad method to get your products array from the DBAccess class: - (void)viewDidLoad { [super viewDidLoad]; // Get the DBAccess object; DBAccess *dbAccess = [[DBAccess alloc] init]; // Get the products array from the database self.products = [dbAccess getAllProducts]; CH002.indd 50CH002.indd 50 9/20/10 2:31:42 PM9/20/10 2:31:42 PM // Close the database because we are finished with it [dbAccess closeDatabase]; // Release the dbAccess object to free its memory [dbAccess release]; } RootViewController.m Next, you have to implement your TableView methods. The fi rst thing you have to do is tell the TableView how many rows there are by implementing the numberOfRowsInSection method as you did in the previous chapter. You will get the count of items to display in the TableView from your products array: - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.products count]; } RootViewController.m Finally, you have to implement cellForRowAtIndexPath to provide the TableView with the TableViewCell that corresponds with the row that the TableView is asking for. The code is similar to the example from the previous chapter. The difference is that now you get the text for the cell from the Product object. You look up the Product object using the row that the TableView is asking for as the index into the array. The following is the cellForRowAtIndexPath method: // Customize the appearance of table view cells. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @”Cell”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } // Configure the cell. // Get the Product object Product* product = [self.products objectAtIndex:[indexPath row]]; cell.textLabel.text = product.name; return cell; } RootViewController.m Connecting to Your Database ❘ 51 CH002.indd 51CH002.indd 51 9/20/10 2:31:43 PM9/20/10 2:31:43 PM 52 ❘ CHAPTER 2 THE IPHONE AND IPAD DATABASE: SQLITE To set the Catalog text at the top in the Navigation Controller, double - click MainWindow.xib . Then, click on the navigation item in Interface Builder and set the Title property to Catalog . You should now be able to build and run the application. When you run it, you should see the product catalog as in Figure 2 - 15. When you touch items in the catalog, nothing happens, but the application should display the details of the product that is touched. To accomplish this, the TableView function didSelectRowAtIndexPath needs to be implemented. But before you do that, you need to build the view that you will display when a user taps a product in the table. Viewing Product Details When a user taps a product in the table, the application should navigate to a product detail screen. Because this screen will be used with the NavigationController , it needs to be implemented using a UIViewController . In Xcode, add a new UIViewController subclass to your project called ProductDetailViewController . Make sure that you select the option “ With XIB for user interface. ” This creates your class along with a NIB fi le for designing the user interface for the class. In the ProductDetailViewController.h header, add Interface Builder outlets for the data that you want to display. You need to add an outlet for each label control like this: IBOutlet UILabel* nameLabel; IBOutlet UILabel* manufacturerLabel; IBOutlet UILabel* detailsLabel; IBOutlet UILabel* priceLabel; IBOutlet UILabel* quantityLabel; IBOutlet UILabel* countryLabel; You will use the outlets in the code to link to the UI widgets created in Interface Builder. The use of Interface Builder is beyond the scope of this book. There are several good books on building user interfaces for the iPhone including iPhone SDK Programming: Developing Mobile Applications for Apple iPhone and iPod Touch by Maher Ali (Wiley, 2009). You will transfer the data about the product that the user selected to the detail view by passing a Product object from the RootViewController to the ProductDetailViewController . Because you will be referencing the Product object in your code, you need to add an import statement for the Product class to the ProductDetailViewController header. You also need to add the FIGURE 2 - 15: Running the Catalog application CH002.indd 52CH002.indd 52 9/20/10 2:31:43 PM9/20/10 2:31:43 PM method signature for the setLabelsForProduct method that will be used to receive the Product object from the RootViewController and set the text of the labels. The complete header should look like this: #import < UIKit/UIKit.h > #import “Product.h” @interface ProductDetailViewController : UIViewController { IBOutlet UILabel* nameLabel; IBOutlet UILabel* manufacturerLabel; IBOutlet UILabel* detailsLabel; IBOutlet UILabel* priceLabel; IBOutlet UILabel* quantityLabel; IBOutlet UILabel* countryLabel; } -(void) setLabelsForProduct: (Product*) theProduct; @end ProductDetailViewController.h Now, open up the ProductDetailViewController.xib fi le in Interface Builder. Here you will add a series of UILabels to the interface as you designed in the mockup. Your interface should look something like Figure 2 - 16. Next, you ’ ll need to hook up your labels in Interface Builder to the outlets that you created in the ProductDetailViewController.h header fi le. Make sure that you save the header fi le before you try to hook up the outlets or the outlets that you created in the header will not be available in Interface Builder. To hook up the outlets, bring up the ProductDetailViewController.xib fi le in Interface Builder. Select File ’ s Owner in the Document window. Press Cmd+2 to bring up the Connections Inspector. In this window, you can see all of the class ’ s outlets and their connections. Click and drag from the open circle on the right side of the outlet name to the control to which that outlet should be connected in the user interface. You should see the name of the control displayed on the right side of the Connections Inspector as in Figure 2 - 17. FIGURE 2 - 16: Product detail view Connecting to Your Database ❘ 53 CH002.indd 53CH002.indd 53 9/20/10 2:31:44 PM9/20/10 2:31:44 PM 54 ❘ CHAPTER 2 THE IPHONE AND IPAD DATABASE: SQLITE In ProductDetailViewController.m , implement setLabelsForProduct to set the text in the labels: -(void) setLabelsForProduct: (Product*) theProduct { // Set the text of the labels to the values passed in the Product object [nameLabel setText:theProduct.name]; [manufacturerLabel setText:theProduct.manufacturer]; [detailsLabel setText:theProduct.details]; [priceLabel setText:[NSString stringWithFormat:@”%.2f”,theProduct.price]]; [quantityLabel setText:[NSString stringWithFormat:@”%d”, theProduct.quantity]]; [countryLabel setText:theProduct.countryOfOrigin]; } ProductDetailViewController.m This code accepts a Product object and uses its properties to set the text that is displayed in the interface labels. In order to be able to navigate to your new screen, you need to add code to the RootViewController to display this screen when a user selects a product. FIGURE 2 - 17: Building the detail view with Interface Builder CH002.indd 54CH002.indd 54 9/20/10 2:31:45 PM9/20/10 2:31:45 PM In the RootViewController header, you must add an import for ProductDetailViewController because you will create an instance of this class to push onto the navigation stack: #import “ProductDetailViewController.h” In the RootViewController implementation, add code to the tableView: didSelectRowAtIndexPath: method to instantiate a ProductDetailViewController , populate the data, and push it onto the navigation stack: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Get the product that corresponds with the touched cell Product* product = [self.products objectAtIndex:[indexPath row]]; // Initialize the detail view controller from the NIB ProductDetailViewController *productDetailViewController = [[ProductDetailViewController alloc] initWithNibName:@”ProductDetailViewController” bundle:nil]; // Set the title of the detail page [productDetailViewController setTitle:product.name]; // Push the detail controller on to the stack [self.navigationController pushViewController:productDetailViewController animated:YES]; // Populate the details [productDetailViewController setLabelsForProduct:product]; // release the view controller becuase it is retained by the // Navigation Controller [productDetailViewController release]; } ProductDetailViewController.m That ’ s all there is to it. Now you should be able to build and run your application. Try tapping on an item in the catalog. The application should take you to the detail page for that item. Tapping the Catalog button in the navigation bar should take you back to the catalog. Tapping another row in the TableView should take you to the data for that item. You now have a fully functioning catalog application! I know that it doesn ’ t look very nice, but you ’ ll work on that in the next chapter where you dive into customizing the UITableView . MOVING FORWARD Now that you have a functioning application, feel free to play with it as much as you like! Spruce up the interface or add additional fi elds to the database tables and Product class. Moving Forward ❘ 55 CH002.indd 55CH002.indd 55 9/20/10 2:31:46 PM9/20/10 2:31:46 PM 56 ❘ CHAPTER 2 THE IPHONE AND IPAD DATABASE: SQLITE There are a lot of good books on the SQL language, so if you were confused by any of the SQL used in this chapter, it may be a good idea to pick up a copy of SQL For Dummies by Allen Taylor. Another resource that you should be aware of is the SQLite web site at http://www.sqlite.org/ . There you will fi nd extensive documentation of the database and the C language APIs that are used to access the database. Although you ’ ve learned how to get your data out of SQLite and into an iPhone application, the catalog doesn ’ t look that great. In the next chapter, you will learn how to display your data with more fl air by customizing the TableView. CH002.indd 56CH002.indd 56 9/20/10 2:31:46 PM9/20/10 2:31:46 PM Displaying Your Data: The UITableView WHAT ’ S IN THIS CHAPTER? Customizing the TableView by creating your own TableView cells Searching and fi ltering your result sets Adding important UI elements to your tables such as indexes and section headers Avoiding and troubleshooting performance issues with your TableViews The focus of the book thus far has been on how to get your data on to the iPhone and how to access that data on the device. This chapter focuses on how you can enhance the display of your data by customizing the TableViewCell . It also examines how to make your data easier to use by adding an index, section headings, and search functionality to the UITableView . In the next several sections, you take a closer look at how to use the TableView to display your data in ways that make it more useful to your target audience. CUSTOMIZING THE TABLEVIEW You begin by taking a look at the default TableView styles that are available in the iPhone SDK. Then, you learn the technique of adding subviews to the content view of a TableViewCell . In the event that neither of these solutions meets your needs for customizing the display of your data, you will examine how to design your own TableViewCell from scratch using Interface Builder. If you had trouble with IB in the previous chapter, now is a good time to review Apple ’ s documentation on using IB, which you can fi nd at http://developer.apple.com/ . ➤ ➤ ➤ ➤ 3 CH003.indd 57CH003.indd 57 9/18/10 9:26:13 AM9/18/10 9:26:13 AM 58 ❘ CHAPTER 3 DISPLAYING YOUR DATA: THE UITABLEVIEW TableViewCell Styles Several pre - canned styles are available to use for a TableViewCell : UITableViewCellStyleDefault : This style displays a cell with a black, left - aligned text label with an optional image view. UITableViewCellStyleValue1 : This style displays a cell with a black, left - aligned text label on the left side of the cell and an additional blue text, right - aligned label on the right side. UITableViewCellStyleValue2 : This style displays a cell with a blue text, right - aligned label on the left side of the cell and an additional black, left - aligned text label on the right side of the cell. UITableViewCellStyleSubtitle : This style displays a cell with a black, left - aligned text label across the top with a smaller, gray text label below. In each style, the larger of the text labels is defi ned by the textLabel property and the smaller is defi ned by the detailTextLabel property. Let ’ s change the Catalog application from the last chapter to see what each of these styles looks like. You will change the application to use the name of the part manufacturer as the subtitle. In the RootViewController.m implementation fi le, add a line to the tableView:cellForRowAt IndexPath: method that sets the cell ’ s detailTextLabel text property to the product ’ s manufacturer: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @”Cell”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } // Configure the cell. // Get the Product object Product* product = [self.products objectAtIndex:[indexPath row]]; cell.textLabel.text = product.name; cell.detailTextLabel.text = product.manufacturer; return cell; } RootViewController.m When you run the application, you will see something like Figure 3 - 1 (a). Nothing has changed. You may be wondering what happened to the subtitle. When you initialized the cell, the style was set to UITableViewCellStyleDefault . In this style, only the cell ’ s textLabel is displayed, along with an optional image, which you will add in a moment. ➤ ➤ ➤ ➤ CH003.indd 58CH003.indd 58 9/18/10 9:26:17 AM9/18/10 9:26:17 AM . bundled copy. Connecting to Your Database ❘ 49 CH002.indd 49CH002.indd 49 9/20/10 2:31:41 PM9/20/10 2:31:41 PM 50 ❘ CHAPTER 2 THE IPHONE AND IPAD DATABASE: SQLITE Displaying the Catalog . Figure 2 - 17. FIGURE 2 - 16: Product detail view Connecting to Your Database ❘ 53 CH002.indd 53CH002.indd 53 9/ 20/10 2:31:44 PM9/20/10 2:31:44 PM 54 ❘ CHAPTER 2 THE IPHONE AND IPAD DATABASE:. 51CH002.indd 51 9/ 20/10 2:31:43 PM9/20/10 2:31:43 PM 52 ❘ CHAPTER 2 THE IPHONE AND IPAD DATABASE: SQLITE To set the Catalog text at the top in the Navigation Controller, double - click MainWindow.xib

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

Từ khóa liên quan

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

  • Đang cập nhật ...

Tài liệu liên quan