Az iPhone fejlesztés alapjai I. előadás
A ponte.hu Kft.
• 2001 óta a piacon • Web iPhone, Android, Nokia és Windows mobile fejlesztések • Újszerű megoldások és technológiák keresése
A kurzus menete Elméleti órák • 3x45+2x45 perc • Elméleti háttér és programozási alapok
Teszt • 1x45 perc • Az elméleti anyagból, a verseny a laborhelyekért megy
Gyakorlat • 4x3x45 perc, és egy kiegészítő bemutató előadás • Közösen fogunk programozni, több témakört átívelve
A kurzus felépítése Gyakorlat
Elmélet Nyelvi elemek
Szemlélet
Eszközök
API
A mai előadás témái • I. Áttekintés • Az iPhone története • Az iPhone fejlesztés eszközei és menete
• II. Az Objective-C nyelv alapjai • Objektum orientáltság • III. Memória kezelés • IV. Nézzünk meg egy példát
I. Áttekintés
Az iPhone története • 2007. Első iPhone kiadása
Nagyon korlátozott: 2G, nincs alkalmazás telepítés, nincs GPS, nincs multitask, de forradalmian új felhasználói felület.
• 2008. iPhone 3G
Nagyon sok fájó pontot javít, megjelenik az AppStore
• 2009. iPhone 3GS
Ráncfelvarrás, nagyobb processzor teljesítmény, digitális iránytű (Augmented Reality), később multitask
• 2010. iPad, mad iPhone 4
Nagy felbontású kijelző, giroszkóp
Miért forradalmi? Korlátolt multitask
Nincs külső telepítés
Szeparált fájlrendszer
Ellenőrzés
Korlátozott funkciók
AppStore
Felhasználói élmény
Minimális testreszabás
Multitouch
Minimális fragmentáció
Egyetlen gomb
Megfelelő teljesítmény
Animált felületek
Kötött készülékek
Egyszerű kezelés
Az iPhone számokban • Több mint 120 millió eladott iOS készülék • Több mint 250 000 alkalmazás • Több mint 10 000 000 000 letöltés • Tulajdonosok 50%-a már vásárolt alkalmazást
Miért az Apple a minta? Profit megoszlás 2010 I. félév
Mobile készülékek 2010 I. félév
Others 29%
Nokia, Samsung, LG 66% Nokia, Samsung, LG 32% Apple 3%
Others 31%
Apple 39%
Forrás: Fortune
Az iOS platform • Támogatott eszközök: • iPhone 2G, 3G, 3GS, 4 • iPod touch 1.-4. generáció • iPad • Minimális fragmentáció • iPhone SDK a fejlesztői környezet (csak Mac)
• Natív alkalmazások Objective-C nyelven
A fejlesztés eszközei
Xcode IDE
• A központ • Debugger és
Profiler alkalmazások
Interface Builder
• Felületek építése
• Nem kötelező, de hasznos
iPhone Simulator
• Nem emulátor • Jó teljesítmény • Nem teljes
A fejlesztés menete Koncepció
Fejlesztés
Tesztelés
Specifikáció
Kódolás
Szimulátor
Arculat
Felület építés
Készülék
II. Objective-C
A nyelv kialakulása • 1980-as évek elején a Stepstone cég alakította ki a Smalltalk alapján
• 1988-ban a NeXT licencelte a technológiát a
NeXTstep rendszere alapjaként, amely később a Mac OS X alapja lett
• A C nyelv objektum orientált kiegészítéseként született, de nem azt az irányt követi, mint a C++ (Simula)
• C++: obj->method(argument); • Objective-C: [obj method: argument];
Osztályok Classname.h @interface classname : superclassname { // instance variables } +classMethod1; +(return_type)classMethod2; +(return_type)classMethod3:(param1_type)param1_varName; -(return_type)instanceMethod1:(param1_type)param1_varName :(param2_type) param2_varName; -(return_type)instanceMethod2WithParameter:(param1_type)param1_varName andOtherParameter:(param2_type)param2_varName; @end
Classname.m @implementation classname +classMethod { // implementation } -instanceMethod { // implementation } @end
Mezők elérése @interface MyFirstClass : NSObject { @public int publicNumber; @protected // Protected is the default char protectedLetter; @private bool privateBool; } @end
@implementation MyFirstClass -‐ myMethod { publicNumber = 3; protectedLetter = 'Q'; privateBool = NO; } @end
@implementation OtherClass -‐ (id)myMethod2 { MySecondClass *other; other = [[MyFirstClass alloc] init]; other-‐>publicNumber = 42; } @end
Metódusok elérése A metódus hívások üzenet küldésekként vannak kezelve, csak futási idejű a hozzárendelés, ezért nincs igazi privát metódus @interface MyClass { // My Instance Variables }
@interface MyClass()
-‐ (void)myPublicMethod;
@end
@end
@implementation MyClass
-‐ (void)myPrivateMethod;
-‐ (void)myPublicMethod { // Implementation goes here } -‐ (void)myPrivateMethod { // Implementation goes here } @end
Konstruktorok Az objektumokat mindig mutatókkal érjük el MyObject *o = [[MyObject alloc] init];
Alap konstruktor felül definiálása -(id) init { if ( self = [super init] ) { // perform initialization of object here } return self; }
Konstruktor paraméterekkel -(id) initWithX: (int)xCord y:(int)yCord { if ( self = [super init] ) { width=xCord; height=yCord; } return self; }
Öröklődés Egyszeres öröklődés @interface Car : Vehicle { } @end
Többszörös öröklődés helyett protokollok @protocol Motoros -(int)getUrtartalom; @end
Protokoll megvalósítás @interface Car : Vehicle <Motoros>{ } @end
III. Memóriakezelés
Nincs Garbage Collection
GC
Kézi kezelés
•
Nem kell foglalkozni a memória felszabadítással
•
Hibalehetőségek: Memory leak és Bad Access
•
De gyakorlatilag nem is lehet
•
•
Kevesebb hibalehetőség, de kevésbé hatékony
Kiszámítható teljesítmény, de munkás
•
Statikus és dinamikus elemző eszközök
Retain...Release -(void)doSomething{ ! SomeObj* someObject=[[SomeObj alloc] init]; ! . ! . ! do something with the object ! . ! . ! [someObject release]; }
retain refainCount++
alloc refainCount=1
doSomething
release refainCount--
-(void)useSomething:(NSString*)someObject{ ! [someObject retain]; ! myObject=someObject; }
retainCount==0 ? Yes
-(void)dontNeedAnyMore{ ! [myObject release]; ! myObject=nil; }
dealloc
Property Hogy néz ki egy egyszerű setter? -(void) setText:(NSString *)textValue { if (textValue != text) { [textValue retain]; [text release]; text = textValue; } }
Mindezeket megcsináltathatjuk a fordítóval is! SomeObject.h
SomeObject.m
#import
#import "SomeObject.h"
@interface SomeObject : NSObject { ! NSString* text; } @property (nonatomic,retain) NSString* text; @end
@implementation SomeObject @synthesize text; @end
No
Property Hogyan használjuk más osztályokban? ! SomeObject* someObject=[[SomeObject alloc] init]; ! someObject.text=@"hello"; ! NSString* localText=someObject.text;
További lehetőségek @property (nonatomic,retain) NSString* text;
• nincs nonatomic: alaptípus (pl: int) • readonly: csak getter készül • assign: nincs retain/release, szimpla értékadás • copy: új példány készítése
Autorelease Pool • Az eddigi modell jól működik tagváltozók esetében. • Viszont lokálisan felhasznált változók, vagy főleg API hívások lokálisan használt eredményei esetén ez nagyon macerás megoldás (mindenre release)
Megoldás: Autorelease Pool
• Az autoreleaselt objektumoknál nem kell foglalkozni a felszabadítással, de csak egy cikluson belül érvényes ! NSString* test=@"test"; NSLog(test); test=[NSString stringWithFormat:@"test: %d",2]; NSLog(test); ! SomeObject* someObject=[[SomeObject alloc] init]; ! [someObject autorelease];
Autorelease Pool működése Start
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Do Something
[pool drain];
End
Memória kezelési szabályok Főszabály
• Azokat az objektumokat kell release, vagy autoreleaseelni, amelyek a birtokunkban vannak
• Egy objektum akkor kerülhet a birtokunkba, ha a
metódus neve, amivel létrehoztuk tartalmazza az alloc, new vagy copy szavakat (pl. alloc, newObject, mutableCopy.), vagy retain-t hívtunk az objektumra.
• Az objektumot tulajdonjogát, akkor engedjük el, ha release, vagy autorelease-t (releaseld valamikor a jövőben) hívunk rajta.
Build and Analyze •
•
Bár a fenti szabályok nem követhetetlenek, nagyon könnyen idézhetünk elő nehezen megtalálható hibákat.
•
Ha kimaradt egy release, akkor memory leaket okoztunk, aminek nincs közvetlen hatása, csak egyszer elfogy a memória.
•
Ha egyel több release van, vagy utána akarunk hozzáférni, akkor kapunk egy BAD_ACCESS hibaüzenetet, amit szintén nehéz megtalálni, mert ki tudja miért volt már a téves felszabadítás.
Statikus analizátor: Xcode Build/Build and Analyze
C típusú memóriakezelés •
Az Objective-C a C kiterjesztése, minden, ami működik C-ben, az működik itt is.
•
Ez sokszor nem a legjobb megoldás, mert nem objektum orientált és még könnyebb hibázni, könnyen okozhatunk buffer overflow-t.
•
Viszont adott esetben nagyon gyors és helytakarékos ! ! ! ! ! !
typedef struct{ ! int x; ! int y; } Point; Point* points;
! points=malloc(100*sizeof(Point)); ! ! ! !
points[0].x=0; points[0].y=0; points[99].x=0; points[99].y=0;
! free(points);
III. Gyakorlat
Mit fogunk csinálni? • Egyszerű OOP feladat • Van egy ős protokoll (Shape), amelynek az a specialitása, hogy lekérdezhető a területe
• Ezt megvalósítja két osztály Square, Circle, amelyeket oldalhosszukkal és sugarukkal inicializálunk
• Van egy Calculator osztály, amely egy statikus
metódusban készít egy Circle-t és egy Square-t, majd a területüket összeadja
Az Xcode megnyitása
Új projekt létrehozása
Az Xcode képernyője
Új fájl hozzáadása
Adjunk fájlokat a grouphoz
Shape.h
#import @protocol Shape -(double)getArea; @end
Square.h #import #import "Shape.h" @interface Square : NSObject <Shape>{ ! double sideLength; } -(id)initWithSide:(double)length; @end
Square.m #import "Square.h" @implementation Square -(id)initWithSide:(double)length{ ! self = [super init]; if ( self ) { ! ! sideLength=length; } ! return self; } -(double)getArea{ ! return sideLength*sideLength; } @end
Circle.h #import #import "Shape.h" @interface Circle : NSObject <Shape>{ ! double circleRadius; } -(id)initWithRadius:(double)radius; @end
Circle.m #import "Circle.h" @implementation Circle -(id)initWithRadius:(double)radius{ ! self = [super init]; if ( self ) { ! ! circleRadius=radius; } ! return self; } -(double)getArea{ ! return circleRadius*circleRadius*M_PI; } @end
Calculator.h
#import @interface Calculator : NSObject { } +(double)calculate; @end
Calculator.m #import "Calculator.h" #import "Circle.h" #import "Square.h" @implementation Calculator +(double)calculate{ ! ! ! ! ! ! ! ! !
Circle* circle=[[Circle alloc] initWithRadius:2.0]; Square* square=[[Square alloc] initWithSide:2.0]; id<Shape> shapes[2]={circle,square}; double sum=0; for (int i=0;i<2;i++){ ! sum+=[shapes[i] getArea]; ! NSLog(@"i: %d %f",i,[shapes[i] getArea]); }
! [circle release]; ! [square release]; ! return sum; } @end
AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch.
! double result=[Calculator calculate]; ! NSString* resultString=[NSString stringWithFormat:@"result: %f",result]; ! UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:resultString ! ! ! ! ! ! delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; ! [alert show]; ! [alert release]; ! [window makeKeyAndVisible]; return YES; }
Az eredmény
Köszönöm a figyelmet!
Sallai Péter [email protected]