iPhone Applicaton Development

written by Martin Häcker on

Hier einige Notizen zu der iPhone API die ich spannend finde:

iPhone Development Facts

  • iPhones in 70 Ländern mit 70+ millionen iPhones (plus unbekannt viele Touches)
  • 5500 Apps gibts im App Store
  • 200 Millionen Apps wurden in 121 Tagen vergekauft
  • Wie Funktionieren iPhone Applikationen:
    • Bedienung mit dem Finger und Gesten: Pinch, Flick
    • So wenig Input wie möglich machen (Weil Input anstrengend ist)
    • Wenig Platz auf dem Bildschirm: Jede Applikation macht eine Sache und nur die
    • GPS, Accelerometer werden benutzen
    • Wenn die Applikation beendet wird wird der Zustand gesichert
  • Kriterien für Erfolgreiche Apps:
    • Delightfull (Spaß, Intuitiv)
    • Innovative (Revolutionär, Innovativ, anspruchsvolle Technik)
    • Designed
      • Great Design -> kleine Teams damit gute Ideen auch eine Chance haben
      • viele Iterationen
      • ständiger Fokus auf Design [40% der Zeit! Nicht wie sonst]
      • Attention To Detail
      • "Sollutions Not Features"
      • "Saying no to 1000 things"
      • "Chose top 5 Features and amplify them"
      • "Flatten data, to make it easily digestible"
      • 30 Second usage Scenario: Man soll nach 30 Sekunden mit der Applikation schon wieder fertig sein.
    • Integratied (Use all available technology - don't reinvent)
    • Optimized (Performance, Stability, Battery Life is important), no PORT -> neu und spezifisch fürs iPhone bauen
    • Connected: Integrate data as much as possible, Connect to a Mac-Application
    • Localized (40% des Maktes sind nicht-Englisch) Applikation UND Store lokalisieren! (Sonst weiß kein User dass die Applikation lokalisiert ist)
    • Diese Checkliste immer wieder abarbeiten. :)

Dev Tools Overview

  • Platz sparen ist das wichtigste, da sonst der watchdog das Programm killt
  • Ein iPhone Programm sollte nur etwa 20-25 MB Ram benutzen (Insbesondere nicht so viel wie direkt nach dem Start des iPhones frei ist!)
  • Code: Alles statisch gelinkt -> Code wird man nicht los
  • Bilder: png! (evtl. nochmal speziell komprimieren)
  • Named-Images: Die sind immer im Speicher da gecached -> Durch Filename laden (wird dann nicht gecached)
  • Audio: Dolby Surround ist schlecht -> mp3, mp4
  • Caching darf man gerne selber implementieren - Flasch kann man so viel nutzen wie man will
  • Applikationen im App-Store können maximal 2 Gig groß sein.

User Interface Design

Eine Applikation zu erstellen kann man grob in 4 Phasen einteilen

  • Familiarize:
    • iPhone verstehen
    • HIG lesen
    • Je schnell man mit einer Applikation fertig ist, desto besser: Starbucks, während jemand vor einem was ordert! (<30 sek)
    • Schnell starten / laden, schnell etwas rausfinden, schnell wieder beenden
    • Andere Input-Art: Finger. Weniger Input ist mehr!
      • Nach Möglichkeiten suchen Tippen zu vermeiden - weil schwer
      • Tippfehler akzeptieren / korrigieren
    • Weniger Platz am Bildschirm: Das wichtigste aussuchen, das Verstärken
      • "Reduce and Amplify!"
      • "You want to strip this app to the bone!"
  • Conceptualize
    • Fokus auf Lösungen!
    • "Refine, Refine, Refine"
    • Das Mentale Modell der User ergründen
      • Eine Frau die Kinder, Hund, Mann pflegt
      • Sie schaut auf ihre Einkaufsliste, wie viel sie auf dem Konto hat
    • Benutzer entscheiden in 20 Sekunden ob sie eine Applikation behalten. Wenn sie 15 davon zum Starten benötigt...
      • Nur Spiele die man eh länger (10-30 Minuten) spielt dürfen länger brauchen (manche Utilities auch)
    • Immer mit einer Idee anfangen:
      • "Vielleicht inneneinrichtung machen?" -> Was könnte man machen? Viel.
      • "Vielleicht FoneLink auf das iPhone bringen?" -> Macht schweine viel....
      • Was ist die Lösung die man anbietet?
    • Define your solution:
      • Application Definition statement: Worum geht's wirklich? Was und für Wen ("iPhoto ist ein Programm zum sortieren, betrachten und teilen von Photos für Home-User und Amateure.")
      • Das ist das Sieb mit dem man Features aussiebt
    • Refine Features
      • Was ist das wenigste mit dem man durchkommt?
        • Wegschmeißen! Selber belohnen wenn man etwas rauslässt! :)
        • Sieben mit dem "Application Definition Statement"
      • Was ist Neu, Am häufigsten Benutzt, Von den meisten usern (80%), Passt für unterwegs Benutzung
      • Was passiert wenn man sich ver"klickt"?
      • Was wenn die Beleuchtung schlecht ist?
      • Weniger Information zu jedem Zeitpunkt anzeigen, dafür "drill down"
    • Welches Mentale Modell haben die Benutzer? Wie sieht er die Applikation?
      • Identify: Objects, Tasks, Roles, Relationships
  • Realize
    • Welche Art Programm baut man? (Welcher Typ?)
    • Produktivität: Lang benutzung (Mail), Wenig Graphik, Viele daten (Drilldown)
    • Utility: Ein Blick auf etwas, dann fertig
    • Immersive: Games, eigene Oberfläche, viel Graphik
    • Das kann man plotten: Von oben (Serious) nach unten (Fun), von links (Entertainment) nach rechts (Tool)
      • Oben Rechts (Serious Tool) Mail: Viel Text, Hierarchien, wenig Graphik
      • Unten Rechts: (Fun Tool) Social, Twitterific: Graphisch, wenig Text, Flache Hierarchien
      • Unten Links: (Fun Entertainment) Games: Graphisch, alles eigenes Interface
      • Oben Links: (Serious Entertainment) News: Text, wenig Graphik, Hierarchien (drill down)
      • Mitte: Utilities (Rest?) Wetter, Aktienkurse, Uhrzeit / Wecker
    • Objekthierarchie in der UI wiederspiegeln (Das hat mich überrascht, da man das auf dem Desktop ja eigentlich eher nicht machen will (Weil das Mentale Modell der user, nach dem man das Interface baut, nicht unbedingt der beste Implementierungsweg ist)
    • Mit Papier Iterieren (Welcher Screen kommt wo und wann?) immer wieder...
  • Finalize
    • Verbessern mit Photos und Bildern
    • Animation für Begeisterung und Feedback!
    • Refine, Optimize, Enhance

Zusammengefasst:

  • "Application Definition Statement" erstellen
  • Iterieren "early and often" (Auf Papier?)
  • Bis zum Release wiederholen - dann wieder von vorn. :)

UIKit Development

  • View Controllers stehen immer im Zentrum: "The C in MVC" :)
    • Einer für jeden Bildschirm / Screen in der App
    • Zwei Sorten: Custom Subclasses (Typischerweise 1 Screen), Apples Subklassen (machen mehrere Screens!)
    • "view" property zum ablegen des UIViews
    • wichtige delegate methoden: loadView: viewDidLoad: viewWillAppear: viewDidAppear:
    • initWithNibName:bundle: -> Designated initializer
    • Releasen wenn man fertig ist mit anzeigen -> Speicher sparen
    • Navigation controller: "Drill Down" interfaces
      • Managt andere ViewController!
      • wichtige Delegate Methoden: pushViewController:animated: popViewController:animated:
      • Wechselt Controller, Show/Hide NavigationController (für die Rückwärtsnavigation und wenige Aktionen)
    • UITabBarController: Verschiedene Ansichten auf die gleichen Daten (iTunes)
      • Managt NSViewControllers
      • More und Konfiguration (fast wie NSToolbar!)
      • Icons schwarz-weiß Outlines mit Alpha!
    • Toolbars: Tools und Aktionen (nur ein Icon)
      • Kein UIViewController!
      • OK: Modales-Sheet als Aktion bringen (Slide up from the bottom!)
      • Slide up meint: Etwas worauf man reagieren muss (Slide across meint navigating)
      • Nie im Tab-Switcher aktionen auslösen!
      • Bookmarks: Sheet dass den ganzen Bildschirm abdeckt
    • UITableViewController: Tabellen...
      • Plain (Adressbuch), Grouped (Prefs)
      • Header, Footer, Sektionen (wieder mit Header & Footer)
      • Jede menge delegate calls um es zu befüllen
      • UITableCells:
        • Kann: Bild, Text, Disclosure / Accessory (evtl. auch checkbox?)
        • Kann einfach Subviews hinzufügen (Yay, nie mehr SubviewTableViewController)
          • Speicher sparen: (Speziell beim scrollen wichtig, damit es flüssig ist) "Cellen" mit gleicher Klasse / Struktur sollten gleiche ID haben, dann kann man mit [tableView dequeReusableCellWithIdentifier:someID] die die oben rausgescrollt sind wieder verwenden statt jedesmal eine Neue zu machen
    • View Controller Tips
      • Immer festlegen ob man das View drehen kann oder nicht (Telefon verkehrt herum macht keinen Sinn - Spiele könnten aber auch in beiden Landscapes prima funktionieren)
      • Bildschirmgröße kann unterschiedlich sein: Beim Telefonieren ist die Statusbar doppelt so hoch!
      • Memory
        • Jeder UIViewController kriegt Memory-Warnings
        • applicationDidFinishLaunching -> leicht halten (für schnellen Startup)
        • Jedes UIKit View ist / hat einen core-animation Layer -> Macht spaß
        • Während der Animation (asynchron) die Applikation blockieren. Wenn der User irgendwo klickt und einen view-wechsel auslöst, der die Animation sinnlos macht...
  • Text Display:
    • UILabel, UIWebView (html, pdf, word)
    • NSString (UIStringDrawing)
    • UITextField (so wenig wie möglich, immer defaults anbieten!)
    • Keyboard Code: (UITextInputTraits) oder IB
      • shown in becomesFirstResponder hidden in resignFirstResponder
      • Cancel bedenken!
  • UITouch (ein Finger!)
    • multiTouch muss man per view einschalten!
    • Gesten muss man selber erkennen
    • touchesBegan:withEvent: touchesMoved:withEvent: touchesended:withEvent:
  • Accelerometer: Reichtung
    • deviceOrientationChanged: delegate
    • Oder direkt -[UIAccelerometer sharedAccelerometer]
      • möglichst wenig (baterie) grob: 10/sec, spiel: 30/sec
      • filtern! low pass (konstante bewegungen)-> Bubble-Level Sample, high-pass für plötzliche bewegungen
      • Kriegt keine konstante Bewegung oder Richtung mit
  • MediaPlayer: Full screen movies
  • Wichtig man kann zu jedem Zeitpunkt unterbrochen werden. Telefon, SMS, Termin (Telefonieren ist aber das wichtigste!)
    • Dann: Adio anhalten, Animation weg, Pausen-Funktion
    • Bei einem Telefonanruf: Erst wird eine Pause ausgelöst, und eine Dialogbox die dem User erlaubt das Telefonat anzunehmen oder abzuweisen, Wenn er annimmt, wird die Applikation terminiert, sonst "resumed"
  • CoreLocation
    • Filter setzen damit weniger callbacks notwendig sind: distanceFilter = xxx; desiredAccuracy = kConstant;
    • setzt man die filter "niedrig" genug wird möglicherweise GPS gar nicht angeworfen -> weniger Strom, schneller
    • Authorization Dialog: durch startUpdatingLocation -> lehnt der User ab muss man das behandeln (Muss man das jedes mal authorisieren?)

Optimization with Instruments

  • Wenig über Instruments und Shark. Mehr allgemeines Zeug
  • Man muss sich klarmachen was man wo an informationen kriegen kann:
    • Simulator: Mac: 2 ghz, 2 gig ram, 500 gb platte, 2mb l2 cache, ethernet, wifi
    • iPhone: 400mhz, 128 mb ram, 8-32 gb flash, kein cache, wifi, 3g, edge
  • Was messen: Speicher, Malen und Scrollen, Startzeit, Dateizugriff, Stromverbrauch
  • VM gibt's, aber kein swap, read only pages (memmap) werden aber geschossen und neu geladen
  • Keine Garbage Collector (man könnte sich aber mal an dem Boehm versuchen :)

Tips:

  • Static Memory minimieren
    • Code Size
    • Compiler flags (schon standardmäßig): -mthumb -> benutzt nur ein 16 Bit Subset und macht kleineren -> Floating point Code wird aber wesentlich größer -> Abwägen
    • "Dead Code Stripping" -> hilft aber nur bei C/C++ Code
    • Möglichst abschalten was man nicht braucht (C++ RTTI, Exceptions)
    • PNGs statt BMP/TIFF
    • Plists als binary Variante (macht Xcode automatisch beim Resourcen Kopieren)
  • Dynamic Memory
    • NSAutoreleasePools eher vermeiden sonst so nutzen wie mans machen soll -> computation intensive schleife -> alle 100/1000 mal einen neuen nehmen
    • "nonatomic" properties sind bis zu 10 mal schneller
    • leaks vermeiden....
  • Memory warnings
    • Unbedingt reagieren -> sonst wird die Applikation abgeschossen
    • Werden u.a. via den UIViewControllern geliefert
    • Dem Benutzer sagen dass die App gleich crashen könnte ist KEINE Lösung
  • Custom Drawing:
    • Views undurchsichtig (opaque) machen -> schneller
    • optimiert Zeichnen: -setNeedsDisplayInRect:, dann nur das in -drawRect: malen
    • Cachen was sich nicht verändert
    • Möglichst views nicht beim Scrollen allokieren -> langsam
      • "reusable cells" machen mehr sinn (siehe dequeue...)
    • Cell layer hierarchies zusammenfallen lassen? (Unklar was das genau sein soll
    • "Design for fast launch, short use"
    • "Optimize startup, Optimize quit"
    • Rest per lazy initializing
  • Große Datensets:
    • -[NSData initWithContentsOfMappedFile:]
    • SQLite für random access in großen Datensets
  • So wenig wie möglich schreiben
  • Sich schnell / langsam ändernde Daten trennen
  • Möglichst wenig Batterie verbrauchen
  • Möglichst wenig Netzwerktraffic
    • wenn doch: Viel auf einmal, wenig "chatty protokolls"
  • Location:
    • Holen, dann callbacks ausschalten
    • Genauigkeit nur so weit einschränken wie man es tatsächlich braucht