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 ?