Objective-C Memória kezelés Készítette: Fahmi Arman B5EXTQ 2014.03.20.
Objective–C memória kezelés Tartalom Memória kezelés Referencia számlálás Objektum tulajdonlás, szabályok Property Mi ez? Formátum Példák ARC Bemutatás Megkötések Strong, Weak pointer
Referencia számlálás Retain/Release növeli, csökenti a számláló értékét Automatikus objektum felszabadítás, ha a számláló értéke 0 lesz Problémák lehetnek. Memory leak: több retain hivás, mint release. Dangling pointer: több release, mint retain. Minden objektum ami létrehoz egy objektumot növeli az objektum referenci számlálóját, ezt a retan üzenetel teszi meg. Amikor már nincs szüksége az objektumra, akkor release-t hiv rajta, ami csökkenti a referencia számlálóját, és ha 0 lesz egy objektum referencia számlálója, akkor az felszabadul. Mivel ezt a programozók csinálják, ezért probléma lehet, ha egy objektum több retain-t kap mint release, memory leak, és forditva ha több release-t kap, akkor nagy valószinűségel crash.
„Konstruktor”, „Destruktor” Alloc/Init „konstruktor”, objektum létrehozásakor hivjuk meg, a referencia számlálót 1-re állitja NSObject *obj = [[NSObject alloc] init]; // egyéb műveletek [obj release]; Dealloc „destruktor” objektum felszabaditásakor hivódik meg „Az objektum dealloc metódusa itt kell minden retain-elt objektumra release-t hivni.
Objektum birtoklás Egy objektumnak több tulajdonosa lehet A létrehozó lesz az első tulajdonosa, más tulajdonosoknak retain-t kell hivniuk A tulajdonos felel az objektum felszabaditásáért Dealloc-t a tulajdonos se hivhat direktben Tulajdonos nélküli objektumok automatikusan felszabadulnak
Autorelease Autorelease hivás, akkor jó ha nem akarjuk megtartani az objektumot, csak ideiglenesen kell Autorelease pool Automatikusan rendelkezésre áll az apphoz, de manuálisan is létrehozható NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Code benefitting from a local autorelease pool. [pool release]; Az autorelease objektumok később kerülnek felszabaditásra. Bekerülnek egy autorelease poolba minden alkalomal amikor meghivjuk a release-t rajtuk, és a rendszer minden event loopban automatikusan csökkenti a refcountert. Egy objektum többször is bekerülhet a poolba. Manuálisan is létrehozható a pool
Autorelease példa NSString * sushiName = [_sushiTypes objectAtIndex:indexPath.row]; NSString * sushiString = [[[NSString alloc] initWithFormat:@"%d: %@", indexPath.row, sushiName] autorelease]; cell.textLabel.text = sushiString; Egy táblázat celláját állitja be ez a kód. A sushiString ref count 1 lesz a 2ik sorban, de az autorelease miatt a következo hivaskor felszabadul. A gond akkor van ha az autorelease-s objektumot kesobb is hasznalnank, mert akkor elszalhatunk.
Memória kezelés szabályai Az alloc/new/copy/mutableCopy metódusoknál retain nálunk van Más metódusok által visszaadott objektumok, csak egyszer használhatóak Factory pattern metódusok, pl: stringWithFormat, imageWithData „Autorelease pending”, azt jelenti, hogy az objektum fel lesz szabaditva automatikusan Az Init/Copy retain nálunk van-val kezdödő metódusok-at mi hozzuk létre, nekünk is kell felszabaditani. Ha többször akarjuk használni őket, akkor retain-t kell rájuk hivni.
Property Deklarált property-k, osztályváltozók eléréséhez Tömörebb kód, automatikusan generált setter/getter @interface Person : NSObject { NSString *location; } @property NSString *location; @end; @implementation Person @synthesize location; @end
Property formátuma Writeability (readonly,readwrite) Setter (assign,copy,retain) Atomicity (atomic,nonatomic) @property (writeability,setter,atomicity) type name; @synthesize name=ivarName; readonly: csak getter-t generál a fordító writeonly: csak setter-t generál a fordító assign: az értéket közvetlenül hozzárendeli, primitív típusoknál a legjobb retain: retain-t hív az átadott értékre copy: copy-t hív az átadott értékre
Property példa
Property példa 2
ARC – Automatic Reference Counting iOS5 egyik nagy újdonsága Retain, Release, és Autorelease többet nem használható vele! Forditási időben kerülnek be a retain/release hivások a kódba A nehézkes retain/release helyett a forditó megoldja ezt helyettünk nagy biztonsággal és hatékonyan. Ez nem szemétgyűjtés, hanem tényleges hivások kerülnek bele a kódba, esetleg jobban kioptimalizálva mintha mi csinálnánk.
ARC használatának megkötései Tilos használni a retain/release/autorelease hivásokat. Dealloc-t nem szabad többet hivni Property assign/retain/copy helyett, weak/strong C Sruct pointereknek vége, malloc/free se lehet NSAutoReleasePool helyett @autoreleasepool A meglévő kódjainkat sajnos át kell írni az ARC-hez, de ideiglenesen kikapcsolható az ARC. A dealloc metódus automatikusan hivodik, az ős dealloc-t sem szabad meghivnunk. A propertyknél használt memóriakezelő utasitások többet nem használhatóak, helyette weak/strongal jelezhetjük a forditónak, hogy hogyan szeretnénk használni a propertynket. A c strukturákban levő pointereket többet nem használhatjuk, helyette azt tanácsolják tegyük ezeket osztályba, ha sok ilyen fájl van, akkor szerencsére az ARC kikapcsolható fájlonként.
Strong Pointer Strong pointer Ez felel meg a retainelt objektumoknak. Tulajdonosai az objektumoknak, amig hivatkoznak az objektumra, addig nem szabadul fel az objektum. NSString *firstName = self.textField.text; ARC-vel forditott kódban ez egy retainelt változó lesz és a firstName hatókörében végig megmarad. A strong kulcsszót kell használnunk a propertykre ott ahol azt szeretnénk hogy a mi osztályunk birtokolja az objektumot. Tehát ahol eddig retain volt ott most strong lesz. A weak kulcsszót az assign lecserélésére használhatjuk, azoknál a propertyknél amelyeket nem mi szeretnénk felszabaditani. Ez egy gyenge referencia.
Weak pointer __weak NSString *weakName = self.textField.text;
Property ARC-vel Strong Weak // Nem ARC kompatibilis kód @property(retain) NSObject *obj; // ARC kompatibilis kód @property(strong) NSObject *obj; Weak // Non-ARC Compliant Declaration @property(assign) NSObject *parentObj; // ARC Compliant Declaration @property(weak) NSObject *parentObj;
ARC-vel megszűnő hibák id obj = [array objectAtIndex:0]; [array removeObjectAtIndex:0]; NSLog(@"%@", obj); __weak NSString *str = [[NSString alloc] initWithFormat:...]; NSLog(@"%@", str); // will output "(null)" Helyette: __strong NSString *firstName = self.textField.text;
Kérdések