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

10 126 0
Phát triển ứng dụng cho iPhone và iPad - part 39 ppt

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

Thông tin tài liệu

Instruments ❘ 349 This method simply creates an NSMutableString object, appends four strings to it, and logs the string to the console. Take a second and see if you can discover the memory leak on your own. The leak occurs because you allocated the NSMutableString object theString using a call to alloc , but you never released this object. After this method ends, the pointer to the string object will be gone. This memory is now unrecoverable, resulting in a memory leak. Build and run the application. When the simulator comes up, click on the Go button. You should see this text in the console: theString is: This is a string . Analyzing a Memory Leak in Instruments Now that you have the sample application coded and ready to go, it ’ s time to fi nd the memory leak in the application using Instruments. In Xcode, select Run ➪ Run with Performance Tool ➪ Leaks from the menu bar. Once the application starts in the simulator, you will see a dark gray triangle at the top of the Track pane start to move from left to right. This indicates that Instruments is recording data from the running application. The Leaks instrument is confi gured to auto - detect leaks in your application every ten seconds. You can force manual detection of leaks at any time by clicking on the Check for Leaks Now button that appears in the left side of the Detail pane when you have the Leaks instrument selected in the Instruments pane. After the application starts and Instruments is running, click the Go button in the iPhone simulator. In a few moments, when the leak check occurs, you will see a red bar in the top part of the Leaks tool in the Track pane and a purple repeating bar below, as you can see in Figure A - 4. You have now collected the data that you need, so stop Instruments from collecting data by clicking the Stop button in the top - left corner of the application. FIGURE A - 4: Memory leak in Instruments APP-A.indd 349APP-A.indd 349 9/17/10 7:24:09 PM9/17/10 7:24:09 PM 350 ❘ APPENDIX A TOOLS FOR TROUBLESHOOTING YOUR APPLICATIONS The red bar indicates that a leak was found, and in fact, shows the number of leaks. The purple bar shows the total number of bytes leaked. For the sake of clarity, I have stopped Instruments on this run after triggering the memory leak one time. If you repeatedly tap on the Go button in the application, you will see a stair step pattern in the Leaks instrument, as memory is lost each time the button is pressed. Make sure that you have the Leaks instrument selected by clicking Leaks in the Instruments pane. If you examine the Detail pane, you will see that there are two line items. Each line item in the Detail pane shows you a leaked block of memory. In this case, there were two leaked blocks. The fi rst block is the NSCFString that holds your NSMutableString . The mutable string allocated the second block behind the scenes to hold the new contents of the string after you append data to your mutable string. If you had coded the application to release the NSMutableString , as you will in a moment, you would not see either of these blocks in the Detail pane. Now, let ’ s see how Instruments can help pin down where the leak has occurred. Make sure that you have the Extended Detail pane open. Then, click on the NSCFString line item in the Detail pane. The Extended Detail pane should show a stack trace that indicates the state of your application at the time that the leak occurred. Notice that the fourth line down in the stack trace is in your code, specifi cally, in the MemoryLeakerViewController goPressed method. Double - click on the line item in the Extended Detail pane and the source code for the MemoryLeakerViewController goPressed method will replace the leaked blocks in the Detail pane, as you can see in Figure A - 5. FIGURE A - 5: Source code in the Detail pane APP-A.indd 350APP-A.indd 350 9/17/10 7:24:11 PM9/17/10 7:24:11 PM If you examine the Detail pane, you will see the code fragment that Instruments is reporting as a leak. In this case, the Leaks instrument has fl agged the line where you allocated theString as being responsible for 50.0% of the memory leak and the fi rst call to the appendString as responsible for the other 50.0%. Instruments is telling you that you have allocated theString on the indicated line and then the object leaked. It is up to you to draw your own conclusion from there, but using the Leaks instrument has given you the exact location of the origin of the leaked object. Now, you just need to clean it up. To fi x the memory leak, you need to release the NSMutableString object when you are fi nished with it. So, change the code in the goPressed method as follows: -(IBAction) goPressed:(id) sender { NSMutableString *theString = [[NSMutableString alloc] init]; [theString appendString:@”This”] ; [theString appendString:@” is”] ; [theString appendString:@” a”] ; [theString appendString:@” string”] ; NSLog(@”theString is: %@”, theString); [theString release]; } Now, re - run the application with Instruments. No matter how many times you press the Go button in the application, you should not see a memory leak. Congratulations, you just learned how to use the Instruments tool to track down and fi x a memory leak, one of the most diffi cult types of bugs to locate! THE STATIC ANALYZER In the most recent versions of the Xcode tool set, Apple has included the Clang static analyzer. Clang is an open source tool that you can use to analyze your code for problems before you even attempt to execute it. You can do a one - time analysis of your code by selecting Build ➪ Build and Analyze from the Xcode menu bar. However, I recommend confi guring your Xcode project to run the analyzer each time that you build. You can do this by selecting Project ➪ Edit Project Settings from the menu bar. Under Build Options, select Run Static Analyzer. Now, you will see the static analyzer in action. Go back into the MemoryLeaker project and the goPressed method and remove the line that releases the NSMutableString variable theString . You have now reintroduced the memory leak into your application. Select Build and Analyze from the Build menu. You should see an icon in the left - hand margin at the end of the goPressed method. This indicates that the static analyzer has found an issue. On the right margin of the same line, you will notice that the analyzer has noted that there is a potential leak of an object. Click on this notifi cation and you should see something like Figure A - 6. The Static Analyzer ❘ 351 APP-A.indd 351APP-A.indd 351 9/17/10 7:24:12 PM9/17/10 7:24:12 PM 352 ❘ APPENDIX A TOOLS FOR TROUBLESHOOTING YOUR APPLICATIONS Sometimes a picture is worth a thousand words and that is defi nitely the case with the static analyzer. The lines and arrows tell the story. The arrow on line 58 shows that you have created an NSMutableString . The line going from line 58 to the end of the method shows that you have not released the string at the end of the method. The comments that the static analyzer adds to the right margin explain the problem in detail. The comment associated with line 58 tells you that the alloc method returns an Objective - C object with a +1 retain count. This is also called the owning reference . On line 67, at the end of the method, the analyzer is reporting that the object allocated on line 58 is no longer referenced after this point, yet it still has a retain count of 1. Therefore, you have leaked the object. Once again, add the line of code to release theString after the NSLog statement. Re - run the analyzer by selecting Build ➪ Build and Analyze from the Xcode menu bar. You should see the analyzer messages disappear as you have corrected the memory leak. The static analyzer can fi nd many other problems, too. For instance, it will fl ag a dead store in which you write to a variable but never read the value back. To see this, change the goPressed method as follows: -(IBAction) goPressed:(id) sender { NSMutableString *theString = [[NSMutableString alloc] init]; FIGURE A - 6: Using the static analyzer APP-A.indd 352APP-A.indd 352 9/17/10 7:24:13 PM9/17/10 7:24:13 PM int i=0; i=5; [theString appendString:@”This”] ; [theString appendString:@” is”] ; [theString appendString:@” a”] ; [theString appendString:@” string”] ; NSLog(@”theString is: %@”, theString); [theString release]; } You can see that you are declaring the variable i , setting it to 5, and then never reading it again. If you run the static analyzer now, you will get an error indicating that the value stored in i is never read. Dead stores can often be a sign of a logic problem in your application. Another logic error is using an uninitialized variable as the left - hand operand in an equality operation. Change the goPressed method as follows: -(IBAction) goPressed:(id) sender { NSMutableString *theString = [[NSMutableString alloc] init]; int i; if (i==5) { [theString appendString:@”This”] ; [theString appendString:@” is”] ; [theString appendString:@” a”] ; [theString appendString:@” string”] ; } NSLog(@”theString is: %@”, theString); [theString release]; } In this case, you have declared the variable i , but you are using it in an equality test without assigning a value to it. Run the analyzer on this code and you will get a fl ag on the line where you declared the variable i saying that it has been declared without an initial value. Then, on the next line, the analyzer informs you that the left operand of the == operator is a garbage value. There are many more problems that you can fi nd even before you run your code using the static analyzer. Although it slows down your build slightly, you should defi nitely enable the analyzer to run during each build. It will save you many hours of debugging in the end. The Static Analyzer ❘ 353 APP-A.indd 353APP-A.indd 353 9/17/10 7:24:14 PM9/17/10 7:24:14 PM APP-A.indd 354APP-A.indd 354 9/17/10 7:24:14 PM9/17/10 7:24:14 PM 355 INDEX ? (question marks), 48, 317 A abstract entities, 148 accessor methods fetchedResultsController, 170, 207 persistentStoreCoordinator, 240 properties and, 220 accessories cells, 60 types, 60 views, 88 accessoryType, 60 accuracy in Core Location framework, 311 action methods, stub implementation, 169 addGestureRecognizer method, 112 addSurvey: method, 97–98 addSurvey method, 96, 102 addSurveyToDataArray method, 101 ADO.NET, 304 Ali, Maher, iPhone SDK Programming: Developing Mobile Applications for Apple iPhone and iPod Touch, 52 allocating memory, arrays, 10 analysis, Instruments, 264 App Delegate, 94 Apple Human Interface Guidelines, 92–93 applications communication, 304 directories, 115 model-view-controller architecture, 6–7 applicationWillTerminate method, 115 architecture client-server, 302–303 model-view-controller, 6–7 network applications, 301–302 application communication, 304 three-tier, 303–304 two-tier architecture, 302–303 Web applications, 272 arrays fetched properties, 202 fi ltering, 81 fl attening, 82 list functions, 221 memory allocation, 10 populating, 10 products, 41, 76 section arrays, 72 sort descriptors, 233 AttributedChild node, 296 attributes entities, 149–150 retain, 50 text, 170 autorelease message, 41, 347 @avg function, 221 awakeFromInsert method, 212 bindex.indd 355bindex.indd 355 9/17/10 7:26:01 PM9/17/10 7:26:01 PM 356 B backgroundView property, 61 BAD_CAST parameter, 295 binary data, storage, 259 bind functions, 48 binding parameters, 48 bitwise OR operator, 223 blocking calls, moving, 252–257 Boolean attributes, 150 Boolean fl ag variable, 286 Boolean properties NSNumber conversion, 211 numberWithBool method, 212 bounds checking, 10 Bucanek, James, Professional Xcode 3, 168 Build and Run icon, 8 buttons adding, 168 Show Differences, 244 buttonTapped method, 229–231, 275 C cachePolicy parameter, 277 callbacks, KVO, 223 capturedCharacters instance variable, 290 capturedCharacters mutable string, 291 catalog displaying, 22, 50–52 product details, viewing, 52–55 CatalogProductView header, import statement, 67 catalogProductView property, 67 CatalogTableViewCell class, 66 CatalogTableViewCell header, 67 cell identifi ers, 86 cellForRowAtIndexPatch, 85–86 cellForRowAtIndexPath, 14, 51, 61 cells accessories, 60 button, 60 checkmarks, 60 contentView property, 62 creating, 63–64 custom drawn, 88 dequeuing, 63, 71 layout, hand-coding, 62 reusing, 85–86 selectionStyle, 61 CGRect, 8 char* variable, 41 checkmarks beside cells, 60 ChildNode1 node, 295 Clang static analyzer, 351–353 classes CatalogTableViewCell, 66 CLLocationManager, 311 controller classes, 7 creating, 8 data availability, 7 data model, implementing, 9–11 database access, 37–38 DBAccess, 38 InfoViewController, 105 LocationSearchViewController, 309 model classes, 6–7, 13–15 naming conventions, 222 NSArray, 40 NSBundle, 39–40 NSData, 275 NSEntityMapping, 242 NSFetchedResultController, 132 NSManagedObject, 148 NSManagedObjectContext, 126–127 NSManagedObjectModel, 126, 148 NSMappingModel, 242 NSMutableArray, 40 NSNotification, 223 NSNumber, 222 backgroundView property – classes bindex.indd 356bindex.indd 356 9/17/10 7:26:01 PM9/17/10 7:26:01 PM 357 NSPredicate, 124 NSPropertyListSerialization, 116 NSPropertyMapping, 242 NSURL, 273–275 NSURLConnection, 274 NSURLRequest, 273–275 NSValue, 222 NSXMLParser, 284 Product, 36–37, 52 RandomOperation, 252 registering as observer, 223 Result, 320–322 self, 112 superclasses, init function, 10 UIGestureRecognizer, 110–111 UILocalizedIndexedCollation, 72 UISwipeGestureRecognizer, 111–112 view classes, 7 cleanup methods, 170 clearSurvey: method, 97–98 clearSurvey method, 96 client-server architecture, 302–303 CLLocationManager class, 311 CLLocationManagerDelegate protocol, 311 closeDatabase method, 38 Cocoa framework key-value coding, 219 naming conventions, 222 String Programming Guide for Cocoa, 234 Cocoa Touch Class, 8 collection operators, 221–222 command-line interface, 24–25 ATTACH DATABASE command, 25 dot notation, 25 metacommands, 25 migrating data, 25 terminal window, 25 compare: method, 233 compatibility, models, 237 compiling, 11 properties existence, 156 warnings, 12 confi gurations, 148 configureCell method, 249–250 configureView method, 98 connectionDidFinishLoading delegate method, 287 connectionDidFinishLoading method, 319 connection:didReceiveData: delegate method, 274 Contacts application, UITableView, 6 contentSizeForViewInPopover property, 106 contentView property cells, 62 subviews, 61–65 viewWithTag function, 65 context parameter, 223 continuous gestures, 110 controller classes, 7 model classes and, 6–7 controllerDidChangeContent: method, 262 controllerDidChangeContent method, 169 controllers, 7 controllerWillChangeContent: method, 262 controls, Nav Bar, 174 coordinate method, 322 coordinate property, 322 CORBA (Common Object Request Broker Architecture), 304 Core Animation, 86–87 Core Data, 20, 123, 124 binary data, storing, 259 changes, 261–263 data store, 124, 125 types, 259 classes – Core Data bindex.indd 357bindex.indd 357 9/17/10 7:26:02 PM9/17/10 7:26:02 PM 358 Core Data (continued) description, 124 fault realization, 258 faulting, 258–259 inheritance, entities, 260 Instruments, 267–268 lightweight migration, 239–242 Managed Object Context, 124, 126–127 Managed Object Model, 124, 126 getter function, 130 performance, 257–263 Persistent Store Coordinator, 124, 125–126 existence checking, 129 relational database, 21 runtime performance, 260–261 SQLite and, 124, 127 SQLite comparison, 20–21 stack, 124–127 task manager project creating, 127–128 data model, 131–132 Event entity, 131 template code, 128–137 Tasks application, 159–161 threading, 247–248 example, 249–257 validation rules, 149–150 Core Data Cache Misses, 267–268 Core Data Faults, 267–268 Core Data Fetches, 267–268 Core Data Saves, 267–268 Core Data Versioning, 236 Core Graphics structures, 8 Core Location framework, 308, 310–313 accuracy, 311 delegate methods, 313 errors, 311 implementing, 312–313 turning off, 311–312 @count function, 221 CREATE TABLE statement (SQLite), 25 currentIndex, 112 D data default at runtime, 212–213 display delegates, 15 item count, 51 popovers, 103–110 protocols, 12, 13 migration, 236 lightweight, 239–242 normalization, 22 retrieval, 8 synchronous, 273 storage, 123 (See also Core Data API) types, 149 Transformable, 150 data-driven applications building, 3–17 templates Navigation-based Application, 4 Tab Bar Application, 5 View-based Applications, 5 data model class, 11 implementation, 9–11 creating, 8 Show Differences button, 244 data store (Core Data), 124, 125 types, 259 database access class, 37–38 getAllProducts method, 40 databases creating, 24–26 data fi les, importing, 28 designing, 22–24 joins, 30–31 migrating data, 25 Core Data – databases bindex.indd 358bindex.indd 358 9/17/10 7:26:03 PM9/17/10 7:26:03 PM . 92–93 applications communication, 304 directories, 115 model-view-controller architecture, 6–7 applicationWillTerminate method, 115 architecture client-server, 302–303 model-view-controller, 6–7 network applications,. method as follows: -( IBAction) goPressed:(id) sender { NSMutableString *theString = [[NSMutableString alloc] init]; FIGURE A - 6: Using the static analyzer APP-A.indd 352APP-A.indd 352 9/17/10. debugging in the end. The Static Analyzer ❘ 353 APP-A.indd 353APP-A.indd 353 9/17/10 7:24:14 PM9/17/10 7:24:14 PM APP-A.indd 354APP-A.indd 354 9/17/10 7:24:14 PM9/17/10 7:24:14 PM 355 INDEX ?

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