Pitfalls bei der iOS-Entwicklung

1.364 Aufrufe

Veröffentlicht am

Die Entwicklung auf der iPhone-Platform ist alles andere als trivial. Trotzdem entstanden in den letzten zweieinhalb Jahren mehr als 250 000 iPhone-Apps. Eine Analyse der am häufigsten verwendeten Wörter bei einer negativen App-Bewertung zeigt, dass vor allem Apps schlecht abschneiden, die abstürzen oder nicht wie versprochen funktionieren. Die Ursachen vieler Fehler liegen in falsch verstandenen Konzepten zur Speicherverwaltung oder der verwendeten Frameworks. Welche Fehler häufig gemacht werden und wie man sie aufspürt und vermeidet, soll dieser Vortrag zeigen.

Veröffentlicht in: Technologie
0 Kommentare
1 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

Keine Downloads
Aufrufe
Aufrufe insgesamt
1.364
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
25
Aktionen
Geteilt
0
Downloads
0
Kommentare
0
Gefällt mir
1
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • AutoreleasePool\n\nObjectOwnership\n\nFactorymethoden\n
  • AutoreleasePool\n\nObjectOwnership\n\nFactorymethoden\n
  • AutoreleasePool\n\nObjectOwnership\n\nFactorymethoden\n
  • AutoreleasePool\n\nObjectOwnership\n\nFactorymethoden\n
  • AutoreleasePool\n\nObjectOwnership\n\nFactorymethoden\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • weitere Ursachen finden im Code\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Pitfalls bei der iOS-Entwicklung

    1. 1. Pitfalls bei der iOS-Entwicklung Dipl.-Inform. (FH) Sven Günther Agiler Senior Softwareentwickler sven.guenther@it-agile.de - @iNevs http://www.it-agile.de
    2. 2. About Softwareentwickler seit 1997 erste Programmiersprache: C Objective-C seit 2007 iOS Entwicklung seit 2009 Berater und Coach für agile Softwareentwicklung  gegründet 2005  Sitz in Hamburg und München  32 Mitarbeiter  Beratung, Schulung, Coaching in agilen Methoden  Scrum, Kanban, xTreme Programming  Develop With You  Develop 4 You Sven Günther http://www.it-agile.de 2
    3. 3. Analyse der Crash-Reports Speicherprobleme  Speicher ging aus  kein Response auf Memory-Warnings  System hat Programm abgeschossen Sven Günther http://www.it-agile.de 3
    4. 4. Analyse der Crash-Reports Speicherprobleme  Speicher ging aus  kein Response auf Memory-Warnings  System hat Programm abgeschossen Crashes  Threading-Probleme  Zugriff auf freigegebenen Speicher Sven Günther http://www.it-agile.de 3
    5. 5. Speicherverwaltung Sven Günther http://www.it-agile.de 4
    6. 6. Speicherverwaltung iPhone: 256MB RAM Sven Günther http://www.it-agile.de 4
    7. 7. Speicherverwaltung iPhone: 256MB RAM Speicher ist begrenzt und daher kostbar Sven Günther http://www.it-agile.de 4
    8. 8. Speicherverwaltung iPhone: 256MB RAM Speicher ist begrenzt und daher kostbar im Gegensatz zum Mac / PC kann kein virtueller Speicher genutzt werden Sven Günther http://www.it-agile.de 4
    9. 9. Speicherverwaltung iPhone: 256MB RAM Speicher ist begrenzt und daher kostbar im Gegensatz zum Mac / PC kann kein virtueller Speicher genutzt werden Sven Günther http://www.it-agile.de 4
    10. 10. Speicherverwaltung iPhone: 256MB RAM Speicher ist begrenzt und daher kostbar im Gegensatz zum Mac / PC kann kein virtueller Speicher genutzt werden Wie kann Speicher ausgehen? Sven Günther http://www.it-agile.de 4
    11. 11. Speicherverwaltung iPhone: 256MB RAM Speicher ist begrenzt und daher kostbar im Gegensatz zum Mac / PC kann kein virtueller Speicher genutzt werden Wie kann Speicher ausgehen? Leaks  Speicher auf den keine Referenz mehr besteht Sven Günther http://www.it-agile.de 4
    12. 12. Speicherverwaltung iPhone: 256MB RAM Speicher ist begrenzt und daher kostbar im Gegensatz zum Mac / PC kann kein virtueller Speicher genutzt werden Wie kann Speicher ausgehen? Leaks  Speicher auf den keine Referenz mehr besteht Verlassener Speicher  Speicher der unnötig referenziert aber nicht mehr benutzt wird Sven Günther http://www.it-agile.de 4
    13. 13. LeaksWas sind Leaks? MemoryMyClass *foo = [[MyClass alloc] init]; foo 0x0 Sven Günther http://www.it-agile.de 5
    14. 14. LeaksWas sind Leaks? MemoryMyClass *foo = [[MyClass alloc] init]; foofoo = nil; // ==> Memory Leak 0x0 Sven Günther http://www.it-agile.de 5
    15. 15. Leaks finden Sven Günther http://www.it-agile.de 6
    16. 16. iOS Reference Counting in iOS keine Garbage Collection aber alle Objekte haben einen Referenzzähler (retainCount) wenn der retainCount 0 erreicht so wird der Speicher freigegeben Sven Günther http://www.it-agile.de 7
    17. 17. iOS Reference Counting in iOS keine Garbage Collection aber alle Objekte haben einen Referenzzähler (retainCount) wenn der retainCount 0 erreicht so wird der Speicher freigegeben //->retainCount+1 alloc new retain copy Sven Günther http://www.it-agile.de 7
    18. 18. iOS Reference Counting in iOS keine Garbage Collection aber alle Objekte haben einen Referenzzähler (retainCount) wenn der retainCount 0 erreicht so wird der Speicher freigegeben //->retainCount+1 //->retainCount-1 alloc release * new autorelease retain copy Sven Günther http://www.it-agile.de 7
    19. 19. iOS Reference Counting in iOS keine Garbage Collection aber alle Objekte haben einen Referenzzähler (retainCount) wenn der retainCount 0 erreicht so wird der Speicher freigegeben //->retainCount+1 //->retainCount-1 alloc release * new autorelease retain immer paarweise copy Sven Günther http://www.it-agile.de 7
    20. 20. AutoreleasepoolNSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Memory pool Sven Günther http://www.it-agile.de 8
    21. 21. AutoreleasepoolNSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; MemoryMyClass *foo = [[MyClass alloc] init]; foo pool Sven Günther http://www.it-agile.de 8
    22. 22. AutoreleasepoolNSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; MemoryMyClass *foo = [[MyClass alloc] init]; foo[foo autorelease]; pool foo Sven Günther http://www.it-agile.de 8
    23. 23. AutoreleasepoolNSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; MemoryMyClass *foo = [[MyClass alloc] init]; foo[foo autorelease];[pool release]; ([foo release];) pool Sven Günther http://www.it-agile.de 8
    24. 24. Object-OwnershipWer ist verantwortlich dafür Objekte zu releasen? Object-Owner Sven Günther http://www.it-agile.de 9
    25. 25. Object-OwnershipWer ist verantwortlich dafür Objekte zu releasen? Object-OwnerWie wird man Object-Owner? Bei Aufruf einer Methode, die den retainCount erhöht. Sven Günther http://www.it-agile.de 9
    26. 26. Object-OwnershipWer ist verantwortlich dafür Objekte zu releasen? Object-OwnerWie wird man Object-Owner? Bei Aufruf einer Methode, die den retainCount erhöht.Regel: Wer retained muss releasen! Sven Günther http://www.it-agile.de 9
    27. 27. Factory-MethodenWie implementiere ich eine Factory-Methode? Sven Günther http://www.it-agile.de 10
    28. 28. Factory-MethodenWie implementiere ich eine Factory-Methode? +(Foo*) fooWithName:(NSString*) name { Foo* [foo = [Foo alloc] init]; return [foo autorelease]; } Sven Günther http://www.it-agile.de 10
    29. 29. Vorsicht bei Zuweisungen Foo *foo = [[Foo alloc] init]; Memory Foo *bar = [[Foo alloc] init]; foo 1 bar 1 Sven Günther http://www.it-agile.de 11
    30. 30. Vorsicht bei Zuweisungen Foo *foo = [[Foo alloc] init]; Memory Foo *bar = [[Foo alloc] init]; foo 1 foo = bar; bar 1 Sven Günther http://www.it-agile.de 11
    31. 31. Vorsicht bei Zuweisungen Foo *foo = [[Foo alloc] init]; Memory Foo *bar = [[Foo alloc] init]; foo 1 foo = bar; bar 0 … [foo release]; Sven Günther http://www.it-agile.de 11
    32. 32. Vorsicht bei Zuweisungen Foo *foo = [[Foo alloc] init]; Memory Foo *bar = [[Foo alloc] init]; foo 1 foo = bar; bar 0 … [foo release]; [bar release]; crash! Sven Günther http://www.it-agile.de 11
    33. 33. So ist es richtig Foo *foo = [[Foo alloc] init]; Memory Foo *bar = [[Foo alloc] init]; foo 1 bar 1 Sven Günther http://www.it-agile.de 12
    34. 34. So ist es richtig Foo *foo = [[Foo alloc] init]; Memory Foo *bar = [[Foo alloc] init]; foo 0 [foo release]; foo = [bar retain]; bar 2 1 Sven Günther http://www.it-agile.de 12
    35. 35. So ist es richtig Foo *foo = [[Foo alloc] init]; Memory Foo *bar = [[Foo alloc] init]; foo 0 [foo release]; foo = [bar retain]; bar 1 [foo release]; Sven Günther http://www.it-agile.de 12
    36. 36. So ist es richtig Foo *foo = [[Foo alloc] init]; Memory Foo *bar = [[Foo alloc] init]; foo 0 [foo release]; foo = [bar retain]; bar 0 [foo release]; [bar release]; Sven Günther http://www.it-agile.de 12
    37. 37. Implementierung von setter// ivar Foo* foo;-(void) setFoo:(Foo*) aFoo { foo = aFoo;} Sven Günther http://www.it-agile.de 13
    38. 38. Implementierung von setter// ivar Foo* foo;-(void) setFoo:(Foo*) aFoo { foo = aFoo; Leak foo} Sven Günther http://www.it-agile.de 13
    39. 39. Implementierung von setter// ivar Foo* foo;-(void) setFoo:(Foo*) aFoo { foo = aFoo; Leak foo} aFoo nicht retained Sven Günther http://www.it-agile.de 13
    40. 40. Implementierung von setter// ivar Foo* foo;-(void) setFoo:(Foo*) aFoo { [foo release]; foo = [aFoo retain];} Sven Günther http://www.it-agile.de 14
    41. 41. Implementierung von setter// ivar Foo* foo;-(void) setFoo:(Foo*) aFoo { [foo release]; Was ist wenn foo = [aFoo retain]; aFoo == foo?} Sven Günther http://www.it-agile.de 14
    42. 42. Implementierung von setter // ivar Foo* foo;-(void) setFoo:(Foo*) aFoo { if (foo != aFoo) { [aFoo retain]; Regel: [foo release]; foo = aFoo; erst retain dann release }} Sven Günther http://www.it-agile.de 15
    43. 43. Objective-C 2.0 Properties // @property (retain) Foo *foo; self.foo = aFooObject; Sven Günther http://www.it-agile.de 16
    44. 44. Objective-C 2.0 Properties // @property (retain) Foo *foo; self.foo = aFooObject; retainCount +1 Sven Günther http://www.it-agile.de 16
    45. 45. Objective-C 2.0 Properties // @property (retain) Foo *foo; self.foo = aFooObject; retainCount +1 self.foo = nil; Sven Günther http://www.it-agile.de 16
    46. 46. Objective-C 2.0 Properties // @property (retain) Foo *foo; self.foo = aFooObject; retainCount +1 retainCount -1 self.foo = nil; Sven Günther http://www.it-agile.de 16
    47. 47. Achtung: Properties & alloc// @property (retain) Foo *foo;self.foo = [[Foo alloc] init]; Sven Günther http://www.it-agile.de 17
    48. 48. Achtung: Properties & alloc// @property (retain) Foo *foo; alloc --> retainCount = 1 retain --> retainCount = 2self.foo = [[Foo alloc] init]; Sven Günther http://www.it-agile.de 17
    49. 49. Achtung: Properties & alloc// @property (retain) Foo *foo; alloc --> retainCount = 1 retain --> retainCount = 2self.foo = [[Foo alloc] init];-(void) dealloc { release --> retainCount = 1 [foo release]; [super dealloc];} Leak! Sven Günther http://www.it-agile.de 17
    50. 50. Achtung: Properties & alloc// @property (retain) Foo *foo; alloc --> retainCount = 1 retain --> retainCount = 2self.foo = [[Foo alloc] init];-(void) dealloc { release --> retainCount = 1 [foo release]; [super dealloc];} Leak! gleiches gilt für self.foo = [f copy]; self.foo = [f retain]; Sven Günther http://www.it-agile.de 17
    51. 51. Achtung: Properties & alloc // @property (retain) Foo *foo; alloc --> retainCount = 1 retain --> retainCount = 2 Foo* f = [[Foo alloc] init]; release --> retainCount = 1 self.foo = f; [f release]; … -(void) dealloc { [foo release]; release --> retainCount = 0 [super dealloc]; Sven Günther http://www.it-agile.de 18
    52. 52. Verlassener Speicher (abandoned memory) Sven Günther http://www.it-agile.de 19
    53. 53. Instruments allocations Sven Günther http://www.it-agile.de 20
    54. 54. Ursachen für abandoned memory Tabellenzellen nicht wiederverwendet Caches Retain-Cycles Sven Günther http://www.it-agile.de 21
    55. 55. RetainCycles Foo Bar *bar; Foo *foo; .. bar.foo = [foo retain]; foo.bar = [bar retain]; Bar // bar dealloc -(void) dealloc { [foo release]; } Sven Günther http://www.it-agile.de 22
    56. 56. RetainCycles Foo kein retain Bar Sven Günther http://www.it-agile.de 23
    57. 57. Master-Detail-Beziehungen Übliches Pattern in iOS: Master - Detail  z.B. Ergebnisliste --> Detailansicht in Kontakten Sven Günther http://www.it-agile.de 24
    58. 58. Master-Detail-Beziehungen Übliches Pattern in iOS: Master - Detail  z.B. Ergebnisliste --> Detailansicht in Kontakten Sven Günther http://www.it-agile.de 24
    59. 59. Master-Detail-Beziehungen Übliches Pattern in iOS: Master - Detail  z.B. Ergebnisliste --> Detailansicht in Kontakten Verantwortlichkeiten für Daten Sven Günther http://www.it-agile.de 24
    60. 60. Master-Detail-Beziehungen Übliches Pattern in iOS: Master - Detail  z.B. Ergebnisliste --> Detailansicht in Kontakten Verantwortlichkeiten für Daten  MasterViewController erzeugt Daten für DetailViewController Sven Günther http://www.it-agile.de 24
    61. 61. Master-Detail-Beziehungen Übliches Pattern in iOS: Master - Detail  z.B. Ergebnisliste --> Detailansicht in Kontakten Verantwortlichkeiten für Daten  MasterViewController erzeugt Daten für DetailViewController  MasterViewController initialisiert DetailViewController mit den Daten Sven Günther http://www.it-agile.de 24
    62. 62. Master-Detail-Beziehungen Übliches Pattern in iOS: Master - Detail  z.B. Ergebnisliste --> Detailansicht in Kontakten Verantwortlichkeiten für Daten  MasterViewController erzeugt Daten für DetailViewController  MasterViewController initialisiert DetailViewController mit den Daten  DetailViewController zeigt Daten an Sven Günther http://www.it-agile.de 24
    63. 63. Master-Detail-Beziehungen Übliches Pattern in iOS: Master - Detail  z.B. Ergebnisliste --> Detailansicht in Kontakten Verantwortlichkeiten für Daten  MasterViewController erzeugt Daten für DetailViewController  MasterViewController initialisiert DetailViewController mit den Daten  DetailViewController zeigt Daten an  Wenn DetailViewController releast wird, wird Speicher für DetailDaten freigegeben Sven Günther http://www.it-agile.de 24
    64. 64. Globale Objekte Objekte die von allen anderen Objekten benutzt werden  z.B. AppDelegate Sven Günther http://www.it-agile.de 25
    65. 65. Globale Objekte Objekte die von allen anderen Objekten benutzt werden  z.B. AppDelegate nicht als Datencontainer missbrauchen! Sven Günther http://www.it-agile.de 25
    66. 66. Crashes Zugriff auf bereits freigegebenen Speicher Threading mit UIKit / CoreData Enumeration über mutable Collections Sven Günther http://www.it-agile.de 26
    67. 67. Crashes bei Delegates Foo *foo; delegates werden i.d.R. nicht retained foo.delegate = bar; Sven Günther http://www.it-agile.de 27
    68. 68. Crashes bei Delegates Foo *foo; delegates werden i.d.R. nicht retained foo.delegate = bar; [foo release] Vorsicht beim release des delegate [bar release]; foo kann noch retained sein Sven Günther http://www.it-agile.de 27
    69. 69. Crashes bei Delegates Foo *foo; delegates werden i.d.R. nicht retained foo.delegate = bar; [foo release] Vorsicht beim release des delegate [bar release]; foo kann noch retained sein … // Foo: [delegate doSomething]; crash! Sven Günther http://www.it-agile.de 27
    70. 70. Crashes bei Delegates Foo *foo; delegates werden i.d.R. nicht retained foo.delegate = bar; foo.delegate = nil; [foo release] Vorsicht beim release des delegate [bar release]; foo kann noch retained sein … // Foo: [delegate doSomething]; Sven Günther http://www.it-agile.de 27
    71. 71. Threading Nicht alle Frameworks sind threadsafe UIKit Coredata Sven Günther http://www.it-agile.de 28
    72. 72. UIKit Änderungen an der UI immer nur im MainThread  [tableView reloadData] (nachdem Daten in Backgroundthread geladen wurden) Sven Günther http://www.it-agile.de 29
    73. 73. UIKit Änderungen an der UI immer nur im MainThread  [tableView reloadData] (nachdem Daten in Backgroundthread geladen wurden) -(void) updateUI { if (![NSThread isMainThread]) { [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO]; return; } [tableView reloadData]; } Sven Günther http://www.it-agile.de 29
    74. 74. CoreData Änderungen an ManagedObjects nur im selben Thread durchführen, der das Objekt erzeugt hat  insert in ManagedObjectContext  fetch from perstistent store Sven Günther http://www.it-agile.de 30
    75. 75. Mutable Collections NSMutableArray *strings; ... for (NSString *s in strings) { ... } Sven Günther http://www.it-agile.de 31
    76. 76. Mutable Collections NSMutableArray *strings; ... NSArray *stringsCopy = [strings copy]; vor Enumeration Copy machen for (NSString *s in stringsCopy) { ... } [stringsCopy release]; Sven Günther http://www.it-agile.de 31
    77. 77. Simulator == Device? Sven Günther http://www.it-agile.de 32
    78. 78. Simulator == Device? Speicher  Device 256MB (512MB iPad2)  Simulator unbegrenzt Sven Günther http://www.it-agile.de 32
    79. 79. Simulator == Device? Speicher  Device 256MB (512MB iPad2)  Simulator unbegrenzt CPU-Power  Simulator nutzt die volle Power des Host-Rechners  auf dem Device wird dann später die Performance nicht erreicht Sven Günther http://www.it-agile.de 32
    80. 80. Simulator == Device? Speicher  Device 256MB (512MB iPad2)  Simulator unbegrenzt CPU-Power  Simulator nutzt die volle Power des Host-Rechners  auf dem Device wird dann später die Performance nicht erreicht Unterschiedliche Implementierungen der SDK‘s  zB [UIImage imageNamed:nil] (z.B. im iOS SDK 4.1)  ==> Simulator: gibt nil zurück  ==> Device: Crash Sven Günther http://www.it-agile.de 32
    81. 81. Simulator == Device? Speicher  Device 256MB (512MB iPad2)  Simulator unbegrenzt CPU-Power  Simulator nutzt die volle Power des Host-Rechners  auf dem Device wird dann später die Performance nicht erreicht Unterschiedliche Implementierungen der SDK‘s  zB [UIImage imageNamed:nil] (z.B. im iOS SDK 4.1)  ==> Simulator: gibt nil zurück  ==> Device: Crash Leak-Detection  ==> Simulator: keine Leaks gefunden  ==> Device: Instruments findet Leaks Sven Günther http://www.it-agile.de 32

    ×