cocoaheads rennes #9 : gestion mémoire, du débutant à l'expert
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.TRANSCRIPT
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 ;
;
ARCpour ou contre ?