Upgrade to Pro — share decks privately, control downloads, hide ads and more …

10 iPhone Memory Management Tips

10 iPhone Memory Management Tips

Adrian Kosmaczewski
PRO

January 28, 2009
Tweet

More Decks by Adrian Kosmaczewski

Other Decks in Technology

Transcript

  1. 10 iPhone Memory Management Tips Adrian Kosmaczewski January 28th, 2009

    1
  2. http://kosmaczewski.net/ 2009/01/28/ 10-iphone-memory-management-tips/ 2

  3. 3

  4. Facts 4

  5. 5

  6. 128 MB RAM 6

  7. 128 MB RAM 6

  8. 128 MB RAM ~ 40 MB for you! 6

  9. Garbage Collection 7

  10. Garbage Collection 7

  11. [ alloc | copy | retain] [ release ] 8

  12. [ alloc | copy | retain] [ release ] 8

  13. 9

  14. http://cocoadevcentral.com/d/learn_objectivec/ 9

  15. Objects on the heap 10

  16. // C++ automatic object on the stack // Memory freed

    when out of scope std::string name(“Adrian”); // C++ object on the heap std::string *name = NULL; name = new std::string(“Adrian”); delete name; 11
  17. ... autorelease]; 12

  18. Virtual Memory 13

  19. Virtual Memory 13

  20. 14

  21. Tips 15

  22. 16

  23. 1) Respond to Memory Warnings 17

  24. - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } 18

  25. - (void)applicationDidReceiveMemoryWarning:(UIApplication *)app { [[ImageCache sharedImageCache] removeAllImagesInMemory]; } 19

  26. NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(whatever:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];

    20
  27. 21

  28. 2) Avoid Autoreleased Objects 22

  29. (when possible) 23

  30. // Instead of NSString *string = [NSString stringWithFormat:@"value = %d",

    var]; // use NSString *string = [[NSString alloc] initWithFormat:@"value = %d", var]; ... [string release]; 24
  31. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; for (id item in

    array) { id anotherItem = [item create]; [anotherItem doSomethingWithIt]; } [pool release]; 25
  32. 26

  33. 3) Load Lazily and Reuse 27

  34. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { Item *item = [items

    objectAtIndex:indexPath.row]; if (detailController == nil) { detailController = [[DetailController alloc] init]; } detailController.item = item; [self.navigationController pushViewController:detailController animated:YES]; } 28
  35. viewWillAppear: viewDidDisappear: 29

  36. tabBarController:didSelectViewController: 30

  37. 31

  38. 4) Avoid UIImage’s imageNamed: 32

  39. http://www.alexcurylo.com/blog/2009/01/13/ imagenamed-is-evil/ 33

  40. @implementation UIImage (AKLoadingExtension) + (UIImage *)newImageFromResource:(NSString *)filename { NSString *imageFile

    = [[NSString alloc] initWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath], filename]; UIImage *image = nil; image = [[UIImage alloc] initWithContentsOfFile:imageFile]; [imageFile release]; return image; } @end 34
  41. #import <Foundation/Foundation.h> @interface ImageCache : NSObject { @private NSMutableArray *keyArray;

    NSMutableDictionary *memoryCache; NSFileManager *fileManager; } + (ImageCache *)sharedImageCache; - (UIImage *)imageForKey:(NSString *)key; - (BOOL)hasImageWithKey:(NSString *)key; - (void)storeImage:(UIImage *)image withKey:(NSString *)key; - (BOOL)imageExistsInMemory:(NSString *)key; - (BOOL)imageExistsInDisk:(NSString *)key; - (NSUInteger)countImagesInMemory; - (NSUInteger)countImagesInDisk; - (void)removeImageWithKey:(NSString *)key; - (void)removeAllImages; - (void)removeAllImagesInMemory; - (void)removeOldImages; @end 35
  42. - (void)applicationDidReceiveMemoryWarning:(UIApplication *)app { [[ImageCache sharedImageCache] removeAllImagesInMemory]; } 36

  43. http://kosmaczewski.net/projects/iphone-image-cache/ 37

  44. 38

  45. 5) Build Custom Table Cells and Reuse Them Properly 39

  46. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { Item *item =

    [items objectAtIndex:indexPath.row]; static NSString *identifier = @"ItemCell"; ItemCell *cell = (ItemCell *)[tableView dequeueReusableCellWithIdentifier:identifier]; if (cell == nil) { cell = [[[ItemCell alloc] initWithIdentifier:identifier] autorelease]; } cell.item = item; return cell; } 40
  47. 41

  48. 6) Override Setters Properly 42

  49. @interface SomeClass { @private NSArray *items; NSString *name; id<SomeProtocol> delegate;

    } @property (nonatomic, retain) NSArray *items; @property (nonatomic, copy) NSString *name; @property (nonatomic, assign) id<SomeProtocol> delegate; @end 43
  50. - (void)setItems:(NSArray *)obj { if (obj == items) { return;

    // (merci Marco! :) } [items release]; items = nil; items = [obj retain]; if (items != nil) { // create the internal // structure of the cell // if not present, // and change the // widget values } } 44
  51. - (void)setName:(NSString *)obj { [name release]; name = nil; //

    I always copy NSStrings! name = [obj copy]; if (name != nil) { // create the internal // structure of the cell // if not present, // and change the // widget values } } 45
  52. - (void)setDelegate:(id<SomeProtocol>)obj { // do not retain! // This is

    an "assign" property delegate = obj; if (delegate != nil) { // create the internal // structure of the cell // if not present, // and change the // widget values } } 46
  53. 47

  54. 7) Beware of Delegation 48

  55. @interface SomeClass <WidgetDelegate> { @private Widget *widget; } @end 49

  56. @implementation SomeClass - (id)init { if (id = [super init])

    { widget = [[Widget alloc] init]; widget.delegate = self; } return self; } 50
  57. - (void)dealloc { // widget might be retained by someone

    else! widget.delegate = nil; [widget release]; widget = nil; } #pragma mark - #pragma mark WidgetDelegate methods - (void)widget:(Widget *)obj method:(BOOL)value { // and here something happens... } @end 51
  58. 52

  59. 8) Use Instruments 53

  60. 54

  61. 55

  62. 9) Use a Static Analysis Tool 56

  63. http://clang.llvm.org/StaticAnalysis.html 57

  64. scan-build -k -V xcodebuild -configuration Debug 58

  65. 59

  66. 60

  67. 61

  68. 62

  69. 10) Use NSZombieEnabled 63

  70. 64

  71. 65

  72. 66

  73. Thanks! 67

  74. Questions? 68