Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Vývoj aplikací pro iOS

2,827 views

Published on

Přednáška pokrývá úvod do mírně pokročilých oblastí vývoje pro iOS.

- vícevláknové programování
- práce s XML a JSON na iOS
- datová persistence
- MapKit a Core Location
- Systémové dialogy
- URL schémata

Published in: Technology, Business
  • Be the first to comment

  • Be the first to like this

Vývoj aplikací pro iOS

  1. 1. Vývoj aplikací pro iOS FI MUNI, 22. 4. 2011
  2. 2. Program Přednáška Coding Session 4 hodiny
  3. 3. Program
  4. 4. Program
  5. 5. Program ±4 hodiny
  6. 6. Obsah - 1. část• Vícevláknové aplikace • Asynchronní provádění operací • Bloky a GCD
  7. 7. Obsah - 2. část• Práce s daty na iOS • Zpracování XML a JSONu • Persistence dat
  8. 8. Obsah - 2. část• Polohové služby • Core Location • MapKit
  9. 9. Obsah - 3. část• Systémové dialogy a komunikace mezi aplikacemi • Získání fotografie a kontaktů • URL Schémata
  10. 10. Když zbyde čas...• Freestyle na témata • Práce s UIWebView • Lokalizace aplikací
  11. 11. Vícevláknové aplikace
  12. 12. Proč vlákna?• Pomalé operace nesmí blokovat hlavní vlákno• Operace UIKitu musí běžet na hlavním vlákně
  13. 13. Pattern• Dlouhotrvající operace - separátní vlákno• Update UI - hlavní vlákno
  14. 14. NSThread
  15. 15. NSThread• Nízkoúrovňová abstrakce nad vlákny
  16. 16. NSThread - (void) detachAsyncOperation { [NSThread detachNewThreadSelector:@selector(operation:) toTarget:self withObject:contextData]; } - (void) operation:(id)contextData { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // slow code here [self performSelectorOnMainThread:@selector(updateUI:) withObject:contextData waitUntilDone:NO]; [pool release]; }
  17. 17. NSThread NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(operation:) object:context]; [thread setThreadPriority:1.0]; // [0.0, 1.0], 1.0 = highest [thread start]; ... [thread cancel]; ... [thread release];
  18. 18. Bloky
  19. 19. Bloky^
  20. 20. Bloky^• “blok” = “kousek kódu”• široká škála použití v různých částech SDK• ~ Lambda, ~ anonymní
  21. 21. Bloky ^ BOOL (int a, int b) { /* code */ }
  22. 22. Bloky ^ BOOL (int a, int b) { /* code */ } ^ void (void) { /* code */ } ^ { /* code */ }
  23. 23. Bloky typedef (void) (^myBlock_t)(int i)
  24. 24. Bloky typedef (void) (^myBlock_t)(int i) void repeat (int times, myBlock_t block) { for (int i = 0; i < times; i++) block(i); }
  25. 25. Bloky int const = 10; myBlock_t iBlock = ^(int i) { NSLog(@”%d”, i * const); } repeat(5, iBlock);
  26. 26. UIKit Animace imageView.alpha = 0.0; [UIView animateWithDuration:1.0 animations:^{ imageView.alpha = 1.0; } completion:^(BOOL finished) { // some completion code, possibly cleanup }];
  27. 27. Bloky NSSet *iSet = [NSSet set]; // ... add objects to the set [set objectsPassingTest:^(id obj, BOOL *stop) { return [self testValue:id]; // custom comparison }];
  28. 28. GCD
  29. 29. GCD• Práce s NSThread je ubíjející• GCD (“Grand Central Dispatch”) práci zjednodušuje• jazyk C, funkce začínají na “dispatch_”
  30. 30. GCD• Dispatch Queue • fronta bloků (FIFO) • jsou reference-counted • dispatch_queue_create ➞ dispatch_release
  31. 31. GCDdispatch_async(queue, ^ { // some slow code});
  32. 32. GCDdispatch_async(network_queue, ^ { // some slow code dispatch_async(main_queue, ^{ // update UI });});
  33. 33. GCD• Dispatch Queue • dispatch_get_main_queue() • dispatch_get_global_queue(priority, 0); • dispatch_queue_create("eu.inmite.net", NULL);
  34. 34. GCD• Dispatch Semaphore • dispatch_semaphore_create • dispatch_semaphore_wait • dispatch_semaphore_signal
  35. 35. GCD• 4 Dispatch Semaphore • dispatch_semaphore_create 3 • dispatch_semaphore_wait 2 • dispatch_semaphore_signal 1
  36. 36. GCD• Dispatch Semaphore • dispatch_semaphore_create • dispatch_semaphore_wait 2 • dispatch_semaphore_signal 1
  37. 37. GCD• Dispatch Semaphore • dispatch_semaphore_create • dispatch_semaphore_wait • dispatch_semaphore_signal !
  38. 38. GCD• 4 Dispatch Semaphore • dispatch_semaphore_create 3 • dispatch_semaphore_wait 2 • dispatch_semaphore_signal 1
  39. 39. GCD• Dispatch Source • reakce na systémové události • soubory, sockety, timer, ...
  40. 40. Singleton
  41. 41. Singleton Pattern // within class Foo + (Foo*) getDefault { static Foo *inst = nil; if (!inst) { inst = [[Foo alloc] init]; // create the instance } return inst; }
  42. 42. Singleton Pattern // within class Foo + (Foo*) getDefault { static Foo *inst = nil; @synchronized (self) { if (!inst) { inst = [[Foo alloc] init]; // create the instance } } return inst; }
  43. 43. Singleton Pattern // within class Foo + (Foo*) getDefault { static Foo *inst = nil; if (!inst) { @synchronized (self) { if (!inst) { inst = [[Foo alloc] init]; // create the instance } } } return inst; }
  44. 44. Singleton Pattern // within class Foo + (Foo*) getDefault { static Foo *inst = nil; if (!inst) { @synchronized (self) { if (!inst) { inst = [[Foo alloc] init]; // create the instance ??? } } } return inst; }
  45. 45. Singleton Pattern // within class Foo + (Foo*) getDefault { static Foo volatile *inst = nil; if (!inst) { @synchronized (self) { if (!inst) { Foo *tmp = [[Foo alloc] init]; // create the instance OSMemoryBarrier(); inst = foo; } } } OSMemoryBarrier(); return inst; }
  46. 46. Singleton Pattern // within class Foo + (Foo*) getDefault { static Foo *inst = nil; if (!inst) { inst = [[Foo alloc] init]; // create the instance } return inst; }
  47. 47. Singleton Pattern // within class Foo + (Foo*) getDefault { static Foo volatile *inst = nil; if (!inst) { @synchronized (self) { if (!inst) { Foo *tmp = [[Foo alloc] init]; // create the instance OSMemoryBarrier(); inst = foo; } } } OSMemoryBarrier(); return inst; }
  48. 48. Singleton Pattern
  49. 49. Singleton Pattern
  50. 50. Singleton Pattern // within class Foo + (Foo*) getDefault { static dispatch_once_t pred; static Foo *inst; dispatch_once(&pred, ^ { inst = [[Foo alloc] init] }); return inst; }
  51. 51. Operation Queues
  52. 52. NSOperation• Abstrakce nad “operac픕 Určeno pro subclassování• KVO compliant
  53. 53. NSOperation• Informace o stavu operace • isCancelled, isFinished, isExecuting, ...• Možnost nastavení priority• Závislosti operací • [op1 addDependency:op2];
  54. 54. NSOperation• main - kód, který se má vykonat• start - spustí operaci• cancel - nastaví příznak zrušení
  55. 55. NSOperation• K dispozici podtřídy • NSInvocationOperation • NSBlockOperation
  56. 56. NSInvocationOperation• Operace vycházející ze selektoru
  57. 57. NSInvocationOperation• Operace vycházející ze selektoru [[NSInvocationOperation alloc] initWithTarget:target selector:selector object:context];
  58. 58. NSBlockOperation• Operace přijímající blok
  59. 59. NSBlockOperation• Operace přijímající blok [NSBlockOperation blockOperationWithBlock:^{ // some code... }];
  60. 60. Spuštění operace - (BOOL)performOperation:(NSOperation*)anOp { BOOL ranIt = NO; if ([anOp isReady] && ![anOp isCancelled]) { if (![anOp isConcurrent]) [anOp start]; else [NSThread detachNewThreadSelector:@selector(start) toTarget:anOp withObject:nil]; ranIt = YES; } else if ([anOp isCancelled]) { [self willChangeValueForKey:@"isFinished"]; [self willChangeValueForKey:@"isExecuting"]; executing = NO; finished = YES; [self didChangeValueForKey:@"isExecuting"]; [self didChangeValueForKey:@"isFinished"]; ranIt = YES; } return ranIt; }
  61. 61. NSOperationQueue• Snadné spouštění instancí NSOperation• Jedna NSOperationQueue instance ~ funkčnost• Možnost nastavit počet paralelních operací
  62. 62. Spuštění operace [queue addOperation:anOperation];
  63. 63. NSOperationQueue [NSOperationQueue mainQueue]; [NSOperationQueue currentQueue];
  64. 64. Úloha: Lorem Pixum• Klient služby “Lorem Pixum”• API: http://lorempixum.com/320/460/• Implementace ke stažení: http://bit.ly/fimuni_01
  65. 65. Práce s daty na iOS
  66. 66. ZpracováníXML a JSON
  67. 67. XML• SAX - NSXMLParser • součást Apple iOS SDK• DOM - TouchXML, KissXML, ... • XML ➞ Strom
  68. 68. Touch XML• Modified BSD Licence• DOM parser + XPath, XML Namespaces• https://github.com/TouchCode/TouchXML
  69. 69. Touch XML• Ukázka kódu
  70. 70. JSON•JavaScript Object Notation• JSON Framework { "id": 1, "name": "Foo", "price": 123, "tags": ["Bar","Eek"] }
  71. 71. JSON Framework• New BSD Licence• JSON parser a generator• http://stig.github.com/json-framework/
  72. 72. JSON Framework• Ukázka kódu
  73. 73. Persistence dat
  74. 74. iOS Filesystem• Aplikace jsou omezené na svůj sandbox • Nemohou číst ani psát mimo něj• Každá aplikace má svůj “Home directory”
  75. 75. iOS Filesystem• Documents • složka pro uživatelské dokumenty • zálohuje se do iTunes
  76. 76. iOS Filesystem• Caches • složka pro soubory cache • nezálohuje se do iTunes
  77. 77. iOS Filesystem• Temp • složka pro dočasné soubory • nezálohuje se do iTunes
  78. 78. iOS Filesystem
  79. 79. iOS Filesystem // temporary directory NSString *tmpDir = NSTemporaryDirectory();
  80. 80. iOS Filesystem // temporary directory NSString *tmpDir = NSTemporaryDirectory(); // documents or caches directory // NSDocuentsDirectory, NSCachesDirectory NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,YES); NSString *cacheDir = [paths objectAtIndex:0];
  81. 81. iOS Filesystem // temporary directory NSString *tmpDir = NSTemporaryDirectory(); // documents or caches directory // NSDocuentsDirectory, NSCachesDirectory NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,YES); NSString *cacheDir = [paths objectAtIndex:0]; NSString *path = [cacheDir stringByAppendingPathComponent:fileName];
  82. 82. Property list• formát pro objektovou persistenci• dvě varianty: XML a binární varianta (Apple)
  83. 83. Property list <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>title</key> <string>Blue socks</string> <key>are_new</key> <true/> <key>colors</key> <array> <string>blue</string> </array> </dict> </plist>
  84. 84. Property list• NSArray, NSDictionary • lze zapisovat a číst z plistu
  85. 85. NSCoding•Protokol pro serializaci objektu • encodeWithCoder • decodeWithCoder
  86. 86. NSCoding - (void)encodeWithCoder:(NSCoder *)encoder { // [super initWithCoder:coder]; for subclasses [encoder encodeObject:[self title] forKey:@"title"]; [encoder encodeObject:[self description] forKey:@"description"]; [encoder encodeObject:[self fullContent] forKey:@"fullcontent"]; [encoder encodeObject:[self href] forKey:@"href"]; [encoder encodeObject:[self locationStr] forKey:@"locationstr"]; [encoder encodeObject:[self imageURL] forKey:@"imageurl"]; [encoder encodeBool:[self read] forKey:@"read"]; }
  87. 87. NSCoding - (id)initWithCoder:(NSCoder *)decoder { // [super initWithDecoder:decoder]; for subclasses if (self = [super init]) { [self setTitle:[decoder decodeObjectForKey:@"title"]]; [self setDescription:[decoder decodeObjectForKey:@"description"]]; [self setFullContent:[decoder decodeObjectForKey:@"fullcontent"]]; [self setHref:[decoder decodeObjectForKey:@"href"]]; [self setLocationStr:[decoder decodeObjectForKey:@"locationstr"]]; [self setImageURL:[decoder decodeObjectForKey:@"imageurl"]]; [self setRead:[decoder decodeBoolForKey:@"read"]]; } return self; }
  88. 88. NSKeyedArchiver BOOL success = [NSKeyedArchiver archiveRootObject:self toFile:path];
  89. 89. NSKeyedUnarchiver MyModel *model = (MyModel*)[NSKeyedUnarchiver unarchiveObjectWithFile:path];
  90. 90. NSUserDefaults• Místo pro ukládání uživatelského nastavení aplikace• Pod pokličkou je PList
  91. 91. NSUserDefaults NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
  92. 92. NSUserDefaults NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setValue:@”Blue socks” forKey:@”title”]; [userDefaults setBool:YES forKey:@”are_new”]; [userDefaults synchronize];
  93. 93. NSUserDefaults NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setValue:@”Blue socks” forKey:@”title”]; [userDefaults setBool:YES forKey:@”are_new”]; [userDefaults synchronize]; NSString *title = [userDefaults valueForKey:@”title”]; BOOL are_new = [userDefaults boolForKey:@”are_new”];
  94. 94. NSUserDefaults• Možnost registrace do aplikace “Settings” • Soubor “Settings.bundle” • PSTextFieldSpecifier, PSToggleSwitchSpecifier, PSSliderSpecifier, ... • pouze “deklarativní nastavení”
  95. 95. SQLite3• Light-weight SQL implementace• Vhodná pro mobilní zařízení• Součástí Apple iOS SDK• Implementace v C, existují wrappery
  96. 96. FMDB• MIT Licence• Light-weight Objective-C wrapper nad SQLite• https://github.com/ccgus/fmdb
  97. 97. FMDB• Ukázka kódu
  98. 98. CoreData• Řešení Apple pro management modelu (object graph) a persistenci dat • podobné ORM (ale není to ORM)• Pod pokličkou SQLite• Vizuální tvorba modelu
  99. 99. CoreData
  100. 100. Polohové služby
  101. 101. MapKit Framework
  102. 102. MKMapView• Implementace online Google Map• Podpora pro různé typy map• Poměrně omezená, ale stačí
  103. 103. MKAnnotation• Protokol• Model pro “napínáčky” na mapě• anotace se přidá do mapy, vrací svou pozici a titulek
  104. 104. MKAnnotationView• View anotace na mapě (“napínáček”)• Používá concept reusable identifikátoru• MKPinAnnotationView
  105. 105. MapKit Framework• Ukázka kódu
  106. 106. CLLocationManager• Zjištění aktuální polohy zařízení• Umožňuje nastavit požadovanou přesnost• Dodává pravidelně update pozice
  107. 107. CLLocationManager• Ukázka kódu
  108. 108. Úloha: PlaceNotes• Poznámky k aktuální pozici• Poznámka má nadpis a obsah• Je spojená s GPS souřadnicí• Persistentní data
  109. 109. Systémové dialogy
  110. 110. Systémové dialogy• Aplikace v SandBoxu• Definované API pro funkce telefonu
  111. 111. Image Picker• Fotoaparát, galerie telefonu• UIImagePickerViewController
  112. 112. Person Picker• Volba kontaktů• ABPeoplePickerNavigationController
  113. 113. URL Schémata
  114. 114. URL Schémata• Způsob, jak spouštět jiné aplikace• Umožňuje předávat “malá data”
  115. 115. URL Schémata
  116. 116. URL Schémata if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url]; }
  117. 117. URL Schémata• http://www.abc.com/ - Safari • nebo Google Maps,YouTube či iTunes• mailto:mail@example.com - Mail• tel:777123456 - Phone• sms:777123456 - SMS
  118. 118. URL Schémata• Aplikace může registrovat své URL schéma• Jiná aplikace ji může spustit• Rejstřík: http://handleopenurl.com/
  119. 119. Facebook• Autentizace používá custom URL schéma• Facebook SDK for iPhone • https://github.com/facebook/facebook-ios-sdk
  120. 120. Úloha: Facebook• Nahrávání obrázků na Facebook• Možnost zvolit obrázek z fotoaparátu i telefonu• ID aplikace: 220303784651438
  121. 121. Děkuji @inmite

×