Date post: | 08-Jun-2015 |
Category: |
Technology |
Upload: | petr-dvorak |
View: | 2,460 times |
Download: | 2 times |
V!voj aplikací pro iOSFI MUNI, 22. 4. 2011
Obsah - 1. část
• Vícevláknové aplikace
• Asynchronní provádění operací
• Bloky a GCD
Obsah - 2. část
• Práce s daty na iOS
• Zpracování XML a JSONu
• Persistence dat
Obsah - 2. část
• Polohové slu#by
• Core Location
• MapKit
Obsah - 3. část
• Systémové dialogy a komunikace mezi aplikacemi
• Získání fotografie a kontaktů• URL Schémata
Kdy# zbyde čas...
• Freestyle na témata
• Práce s UIWebView
• Lokalizace aplikací
Vícevláknové aplikace
Proč vlákna?
• Pomalé operace nesmí blokovat hlavní vlákno
• Operace UIKitu musí bě#et na hlavním vlákně
Pattern
• Dlouhotrvající operace - separátní vlákno
• Update UI - hlavní vlákno
NSThread
NSThread
• Nízkoúrovňová abstrakce nad vlákny
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];}
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];
Bloky
Bloky
• “blok” = “kousek kódu”
• "iroká "kála pou#ití v různ!ch částech SDK
• ~ Lambda, ~ anonymní
^
Bloky
^ BOOL (int a, int b) { /* code */ }
^ void (void) { /* code */ }^ { /* code */ }
Bloky
typedef (void) (^myBlock_t)(int i)
void repeat (int times, myBlock_t block) { for (int i = 0; i < times; i++) block(i);}
Bloky
int const = 10;
myBlock_t iBlock = ^(int i) {
NSLog(@”%d”, i * const);
}
repeat(5, iBlock);
UIKit Animace
imageView.alpha = 0.0;[UIView animateWithDuration:1.0 animations:^{ imageView.alpha = 1.0;} completion:^(BOOL finished) { // some completion code, possibly cleanup}];
Bloky
NSSet *iSet = [NSSet set];// ... add objects to the set
[set objectsPassingTest:^(id obj, BOOL *stop) { return [self testValue:id]; // custom comparison}];
GCD
GCD
• Práce s NSThread je ubíjející
• GCD (“Grand Central Dispatch”) práci zjednodu"uje
• jazyk C, funkce začínají na “dispatch_”
GCD
• Dispatch Queue
• fronta bloků (FIFO)
• jsou reference-counted
• dispatch_queue_create ! dispatch_release
GCD
dispatch_async(queue, ^ { // some slow code});
GCD
dispatch_async(network_queue, ^ { // some slow code dispatch_async(main_queue, ^{ // update UI });});
GCD
• Dispatch Queue
• dispatch_get_main_queue()
• dispatch_get_global_queue(priority, 0);
• dispatch_queue_create("eu.inmite.net", NULL);
GCD
• Dispatch Semaphore
• dispatch_semaphore_create
• dispatch_semaphore_wait
• dispatch_semaphore_signal
GCD
• Dispatch Semaphore
• dispatch_semaphore_create
• dispatch_semaphore_wait
• dispatch_semaphore_signal
4
3
2
1
GCD
• Dispatch Semaphore
• dispatch_semaphore_create
• dispatch_semaphore_wait
• dispatch_semaphore_signal
2
1
GCD
• Dispatch Semaphore
• dispatch_semaphore_create
• dispatch_semaphore_wait
• dispatch_semaphore_signal!
GCD
• Dispatch Semaphore
• dispatch_semaphore_create
• dispatch_semaphore_wait
• dispatch_semaphore_signal
4
3
2
1
GCD
• Dispatch Source
• reakce na systémové události
• soubory, sockety, timer, ...
Singleton
Singleton Pattern
// within class Foo+ (Foo*) getDefault { static Foo *inst = nil; if (!inst) { inst = [[Foo alloc] init]; // create the instance } return inst;}
Singleton Pattern
// within class Foo+ (Foo*) getDefault { static Foo *inst = nil; @synchronized (self) { if (!inst) { inst = [[Foo alloc] init]; // create the instance } } return inst;}
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;} ???
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;}
Singleton Pattern
// within class Foo+ (Foo*) getDefault { static dispatch_once_t pred; static Foo *inst; dispatch_once(&pred, ^ { inst = [[Foo alloc] init] }); return inst;}
Operation Queues
NSOperation
• Abstrakce nad “operací”
• Určeno pro subclassování
• KVO compliant
NSOperation
• Informace o stavu operace
• isCancelled, isFinished, isExecuting, ...
• Mo#nost nastavení priority
• Závislosti operací
• [op1 addDependency:op2];
NSOperation
• main - kód, kter! se má vykonat
• start - spustí operaci
• cancel - nastaví příznak zru"ení
NSOperation
• K dispozici podtřídy
• NSInvocationOperation
• NSBlockOperation
NSInvocationOperation
• Operace vycházející ze selektoru
[[NSInvocationOperation alloc] initWithTarget:target selector:selector object:context];
NSBlockOperation
• Operace přijímající blok
[NSBlockOperation blockOperationWithBlock:^{ // some code...}];
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;}
NSOperationQueue
• Snadné spou"tění instancí NSOperation
• Jedna NSOperationQueue instance ~ funkčnost
• Mo#nost nastavit počet paralelních operací
Spu"tění operace
[queue addOperation:anOperation];
NSOperationQueue
[NSOperationQueue mainQueue];
[NSOperationQueue currentQueue];
Práce s daty na iOS
ZpracováníXML a JSON
XML
• SAX - NSXMLParser
• součást Apple iOS SDK
• DOM - TouchXML, KissXML, ...
• XML ! Strom
Touch XML
• Modified BSD Licence
• DOM parser + XPath, XML Namespaces
• https://github.com/TouchCode/TouchXML
JSON
• JavaScript Object Notation
• JSON Framework
{ "id": 1, "name": "Foo", "price": 123, "tags": ["Bar","Eek"]}
JSON Framework
• New BSD Licence
• JSON parser a generator
• http://stig.github.com/json-framework/
Persistence dat
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”
iOS Filesystem
• Documents
• slo#ka pro u#ivatelské dokumenty
• zálohuje se do iTunes
iOS Filesystem
• Caches
• slo#ka pro soubory cache
• nezálohuje se do iTunes
iOS Filesystem
• Temp
• slo#ka pro dočasné soubory
• nezálohuje se do iTunes
iOS Filesystem
// temporary directoryNSString *tmpDir = NSTemporaryDirectory();
// documents or caches directory// NSDocuentsDirectory, NSCachesDirectoryNSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);NSString *cacheDir = [paths objectAtIndex:0];
NSString *path = [cacheDir stringByAppendingPathComponent:fileName];
Property list
• formát pro objektovou persistenci
• dvě varianty: XML a binární varianta (Apple)
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>
Property list
• NSArray, NSDictionary
• lze zapisovat a číst z plistu
NSCoding
• Protokol pro serializaci objektu
• encodeWithCoder
• decodeWithCoder
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"];}
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;}
NSKeyedArchiver
BOOL success = [NSKeyedArchiver archiveRootObject:self toFile:path];
NSKeyedUnarchiver
MyModel *model = (MyModel*)[NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSUserDefaults
• Místo pro ukládání u#ivatelského nastavení aplikace
• Pod pokličkou je PList
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”];
NSUserDefaults
• Mo#nost registrace do aplikace “Settings”
• Soubor “Settings.bundle”
• PSTextFieldSpecifier, PSToggleSwitchSpecifier, PSSliderSpecifier, ...
• pouze “deklarativní nastavení”
SQLite3
• Light-weight SQL implementace
• Vhodná pro mobilní zařízení
• Součástí Apple iOS SDK
• Implementace v C, existují wrappery
FMDB
• MIT Licence
• Light-weight Objective-C wrapper nad SQLite
• https://github.com/ccgus/fmdb
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
CoreData
Polohové slu#by
MapKit Framework
MKMapView
• Implementace online Google Map
• Podpora pro různé typy map
• Poměrně omezená, ale stačí
MKAnnotation
• Protokol
• Model pro “napínáčky” na mapě• anotace se přidá do mapy, vrací svou pozici a
titulek
MKAnnotationView
• View anotace na mapě (“napínáček”)
• Pou#ívá concept reusable identifikátoru
• MKPinAnnotationView
CLLocationManager
• Zji"tění aktuální polohy zařízení
• Umo#ňuje nastavit po#adovanou přesnost
• Dodává pravidelně update pozice
Systémové dialogy
Systémové dialogy
• Aplikace v SandBoxu
• Definované API pro funkce telefonu
Image Picker
• Fotoaparát, galerie telefonu
• UIImagePickerViewController
Person Picker
• Volba kontaktů• ABPeoplePickerNavigationController
URL Schémata
URL Schémata
• Způsob, jak spou"tět jiné aplikace
• Umo#ňuje předávat “malá data”
URL Schémata
if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url];}
URL Schémata
• http://www.abc.com/ - Safari
• nebo Google Maps, YouTube či iTunes
• mailto:[email protected] - Mail
• tel:777123456 - Phone
• sms:777123456 - SMS
URL Schémata
• Aplikace mů#e registrovat své URL schéma
• Jiná aplikace ji mů#e spustit
• Rejstřík: http://handleopenurl.com/
• Autentizace pou#ívá custom URL schéma
• Facebook SDK for iPhone
• https://github.com/facebook/facebook-ios-sdk
Děkuji@inmite