CocoaHeads Rennes #9 : Gestion mémoire, du débutant à l'expert

Preview:

DESCRIPTION

La session rennaise des CocoaHeads du mois d'avril 2012 fût l'occasion de revenir sur un des grands sujets d'iOS: la gestion mémoire. Thomas Dupont nous a présenté le sujet en partant des considérations les plus simples en allant vers les cas les plus complexes. Sa présentation est assurément un bon moyen pour se lancer dans le sujet, pour faire un rappel des basiques ou pour aller plus loin ... Une large partie de sa présentation était consacrée à ARC.

Citation preview

Gestion Mémoire

Thomas DupontCocoaHeads Rennes #912 avril 2012

du débutant à l’expert

Sommaire

• Gestion mémoire

• Compteur de références

• Properties

• Blocks

• ARC

•Gestion mémoire

stack

sp

0

1

2

3

4

5

6

7

co if (b) {int y = 3;

}

•Gestion mémoire

stack

sp

0

1

2

3

4

5

6

7

co if (b) {int y = 3;

}

adresse de retour : 4

variable y

heap

•Gestion mémoire

malloc

free

0

Compteur de références

retain

release

NSObject

12

chien

Compteur de références

métaphore du chien

A B

C

0123

‣ Vous êtes responsable des objets que vous créez

‣ Vous pouvez devenir responsable d’un objet avec retain

‣ Vous devez relâcher un objet dont vous êtes responsable

+ (id)alloc- (id)init+ (id)new- (id)copy- (id)mutableCopy

Conventions de nommage

Compteur de références

+ (MyObject*)fetchMyObject;

MyObject* obj = [MyObject fetchMyObject];

obj

Compteur de références

autorelease

autoreleasepoolrun loop

obj01

Properties

assignretain

readonlynonatomicsetter=

@synthesize myObj;

copy

getter=

NSObject* myObj;@property (attributes)

readwrite

Blocks

dispatch_block_t myBlock

[UIView animateWithDuration:0.5 animations:

^{ myView.alpha = 0; }

];

= ;

myBlock

int a = 3;__block

Blocks

void (^incrementA)(void) = ^{ a++; };

incrementA();

Blocks

NSObject* myObj;__block

void (^foo)(void) = ^{ [myObj foo]; };

foo();

Blocks

void (^foo)(void) = ^{myIvar++;[myObj foo];

};foo();

MyObject* myObj;int myIvar;

MyClass.h

MyClass.m

myObj = [[MyObject alloc] initWithBlock:^{NSLog(@"%i",

}];

MyObject* myObj;int myIvar;

myIvar);

MyClass.h

MyClass.m

myObj

blockself

Blocks

myObj = [[MyObject alloc] initWithBlock:^{NSLog(@"%i",

}];

MyObject* myObj;int myIvar;

MyClass* weakSelf = self;

weakSelf-> myIvar);

MyClass.h

MyClass.m__block

myObj

blockself

Blocks

dispatch_block_t block;

if ( ... ) { if ( ... ) {

} else {

}

} else {

}

block();

int* pInt;

int a = 1;pInt = &a;

int b = 1;pInt = &b;

// utilisation de pInt

;^{ ... }block =

Blocks

;^{ ... }block =

dispatch_block_t block;

if ( ... ) {

} else {

}

block();

copy] ;^{ ... }[[ autorelease]block =

Blocks

copy] ;^{ ... }[[ autorelease]block =

ARC

@implementation Stack { NSMutableArray *array; }

@end

- (id) init {if (self = [super init])

array = return self;

}- (void) push: (id) x {

[array addObject: x];}- (id) pop {

id x = [array removeLastObject];return

}

;[[NSMutableArray array]

[array lastObject][ ;

;[

ARC

@implementation Stack { NSMutableArray *array; }

- (void) dealloc { [array release]; [super dealloc]; }@end

- (id) init {if (self = [super init])

array = return self;

}- (void) push: (id) x {

[array addObject: x];}- (id) pop {

id x = [array removeLastObject];return

}

retain] ;[ [NSMutableArray array]

[array lastObject][ retain] ;

autorelease] ;[ x

ARC

It just works !

Oublier la notion de retain et releasePenser au graphe d’objets

Insertion automatique de retain, release et autorelease

__strong objc_retain (

objc_autorelease (

- (id) pop { [array removeLastObject] ;return

}

result =

ARC

__strong

[array lastObject] ;

; result

)

)

valeur par défaut

devient responsable

id

ARC

__unsafe_unretained

ne devient pas responsable

- (void) dealloc {[myTableView setDelegate:nil];[myTableView setDataSource:nil];

}

utilisé pour éviter les deadlocks

ARC

__weak

ne devient pas responsable

utilisé pour éviter les deadlocks

remis à nil dès que l’objet est détruit

! disponible que depuis iOS 5.0 et OS X 10.7

- (void) testWeak {id newObject = [NSObject new];__weak id value = newObject;newObject = nil;assert(value == nil);

}

ARC

@property (strong) id x; // __strong , a.k.a retain

@property (unsafe_unretained) id y; // __unsafe_unretained , a.k.a assign

@property (weak) id z; // __weak

ARC

blocks

^{ ... }

ARC

dispatch_block_t block;

if ( ... ) {

} else {

}

block();

;block =

^{ ... } ;block =

ARC

myObj = [[MyObject alloc] initWithBlock:^{

MyObject* myObj;int myIvar;

MyClass* weakSelf = self;

weakSelf->myIvar);

MyClass.h

MyClass.m__block __unsafe_unretained

}];NSLog(@"%i",

__weak

MyObject* strongSelf = weakSelfif (strongSelf)

ARC

myObj = [[MyObject alloc] initWithBlock:^{

MyObject* myObj;int myIvar;

MyClass* weakSelf = self;

myIvar);

MyClass.h

MyClass.m

}];NSLog(@"%i", strongSelf->

ARC

Core Foundation

CFArrayRef) [[NSArray alloc] init];

NSDictionary*) CFDictionaryCreate(...);

NSString*) myCFString;

ARC

NSDictionary* dict = (

NSString* myNSString = ( __bridge

__bridge_transfer

__bridge_retainedCFArrayRef aray = (

ARC

Project configuration

ARC

ARC

-fno-objc-arc-fobjc-arc

ARC

- (NSString*) copyRightLicense {return license;

}

objc_release ( l );

- (void) checkLicense {NSString* l = [license copyRightLicense];...

}

Non-ARC compiled

ARC compiled

- (void) checkLicense {

...License* l = [License createLicense]

ARC

+ (License*) createLicense {return [[self alloc] init];

}

objc_release ( l );}

Non-ARC compiled

ARC compiled__strong objc_retain ( ;)

ARC

+ (License*) createLicense

- (NSString*) copyRightLicense

NS_RETURNS_RETAINED

NS_RETURNS_NOT_RETAINED ;

;

julien@cocoaheads.frthomas.dupont@cocoaheads.fr

CocoaHeads Rennes #912 avril 2012

Merci

ARCpour ou contre ?

Recommended