CocoaHeads Toulouse - Patrice Trognon / Delta Studio - ARC

3,424 views
3,393 views

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,424
On SlideShare
0
From Embeds
0
Number of Embeds
2,612
Actions
Shares
0
Downloads
13
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

CocoaHeads Toulouse - Patrice Trognon / Delta Studio - ARC

  1. 1. Tutorial ARC Développement de Logiciels & Technologies Avancées http://www.DLTA-Studio.com ARC Tutorial Patrice Trognon patrice.trognon@dlta-studio.com Version 1.1 08/03/2012 Copyright (c) 2012 DLTA Studio Tous Droits Réservés Reproduction InterditeARC! 1/10
  2. 2. Tutorial ARC Table des Matières Au début était la gestion tout à la main.! 3 Ensuite nous avons les propriétés! 4 Place à ARC !! 5 Deux nouveaux keywords! 7 ARC et Interface Builder! 8 ARC ne traite que l’objective-C! 9 Désactiver ARC pour la compilation d’un source! 10ARC! 2/10
  3. 3. Tutorial ARCAu début était la gestion tout à la main.// Compte.h@class Client ;@interface Compte : NSObject { Client * titulaire ;}-(Client*)titulaire ;-(void)setTitulaire:(Client*)titulaire_;@end// Compte.m@implementation Compte-(Client*)titulaire { return titulaire ;}-(void)setTitulaire:(Client*)titulaire_ { [titulaire release]; titulaire = titulaire_; [titulaire retain];}-(void)dealloc { [titulaire release]; [super dealloc];}@end// testClient *clientMarcel ; Client *clientPaul; Compte *compte;clientMarcel = [[Client alloc]init]; // clientMarcel [1], clientPaul [0], compte[0]clientPaul = [[Client alloc]init]; // clientMarcel [1], clientPaul [1], compte[1]compte = [[Compte alloc]init]; // clientMarcel [1], clientPaul [1], compte[1][compte setTitulaire:clientMarcel]; // clientMarcel [2], clientPaul [1], compte[1][compte setTitulaire:clientPaul]; // clientMarcel [1], clientPaul [2], compte[1][clientMarcel release]; // clientMarcel [0], clientPaul [2], compte[1][clientPaul release]; // clientMarcel [0], clientPaul [1], compte[1][compte release]; // clientMarcel [0], clientPaul [0], compte[0]Toute la gestion de la mémoire s’effectue alors à la main dans la méthode de set etdans la méthode dealloc, tout est à la charge du développeur, si il oublie une desinstructions il y aura un soucis dans cette gestion (memory-leak).ARC! 3/10
  4. 4. Tutorial ARCEnsuite nous avons les propriétés// Compte.h@class Client ;@interface Compte : NSObject@property(nonatomic,retain) Client* titulaire;@end// Compte.m@implementation Compte@synthesize titulaire;-(void)dealloc { [titulaire release]; [super dealloc];}@end// testClient *clientMarcel ; Client *clientPaul; Compte *compte;clientMarcel = [[Client alloc]init]; // clientMarcel [1], clientPaul [0], compte[0]clientPaul = [[Client alloc]init]; // clientMarcel [1], clientPaul [1], compte[1]compte = [[Compte alloc]init]; // clientMarcel [1], clientPaul [1], compte[1][compte setTitulaire:clientMarcel]; // clientMarcel [2], clientPaul [1], compte[1][compte setTitulaire:clientPaul]; // clientMarcel [1], clientPaul [2], compte[1][clientMarcel release]; // clientMarcel [0], clientPaul [2], compte[1][clientPaul release]; // clientMarcel [0], clientPaul [1], compte[1][compte release]; // clientMarcel [0], clientPaul [0], compte[0]La gestion de la mémoire est prise en charge en partie par la propriété, plus besoinde coder un setter ou un getter ils seront générés par le @synthesize. Attention ledealloc est toujours présent et à la charge du développeur, si il est oublié il y atoujours fuite mémoire.ARC! 4/10
  5. 5. Tutorial ARCPlace à ARC !ARC (Automatic Reference Counting), est la pour aider le développeur afin qu’il n’ait plusde gestion de mémoire à faire dans son code, du moins afin qu’il en ait beaucoup moins.Il faut activer ARC à la création du projet.ARC! 5/10
  6. 6. Tutorial ARC// Compte.h@class Client ;@interface Compte : NSObject@property(nonatomic,strong) Client* titulaire;@end// Compte.m@implementation Compte@synthesize titulaire;@end// testClient *clientMarcel ; Client *clientPaul; Compte *compte;clientMarcel = [[Client alloc]init]; // clientMarcel [1], clientPaul [0], compte[0]clientPaul = [[Client alloc]init]; // clientMarcel [1], clientPaul [1], compte[1]compte = [[Compte alloc]init]; // clientMarcel [1], clientPaul [1], compte[1][compte setTitulaire:clientMarcel]; // clientMarcel [2], clientPaul [1], compte[1][compte setTitulaire:clientPaul]; // clientMarcel [1], clientPaul [2], compte[1]Il n’y a plus une seule ligne de code pour la gestion de la mémoire, ARC va faire letravail effectué avant par le développeur en générant le code adéquat, le setter etle getter sont générés par le @synthesize de la propriété comme avant, ARC vagénérer le dealloc ainsi que les release quand c’est nécessaire.Plus de risque de fuite mémoire, gestion plus efficace par ARC car il ne va générerque ce qu’il faut la ou il faut.Attention ARC N’EST PAS UN GARBAGE COLLECTOR.ARC! 6/10
  7. 7. Tutorial ARCDeux nouveaux keywords// Compte.h@class Client ;@interface Compte : NSObject@property(nonatomic,strong) Client* titulaire;@endstrong ‘remplace’ retain .// Case.h@interface Case : NSObject@property(nonatomic,weak) Case* suivante;@endDans le cas des références circulaires il faut utiliser weak.Attention si vous vous passez des propriétés pour utiliser des attributs ils serontstrong par défaut, par exemple ce code va fuir car les références circulaires seront strong :// Case.h@interface Case : NSObject {! Case* suivante;}@endConclusion1/ Il faut utiliser les propriétés2/ utiliser weak pour les références circulairesARC! 7/10
  8. 8. Tutorial ARCARC et Interface BuilderIl faut distinguer ici deux cas, les projets qui ciblent uniquement iOS 5, et ceux qui ciblentiOS 5 et iOS 4.Dans le cas d’iOS 5 les IBOutlet(s) doivent être déclarées en weak.@property(nonatomic,weak) IBOutlet UILabel * label ;Dans le cas d’iOS 4 weak n’étant pas supporté il faut les déclarer strong.@property(nonatomic,strong) IBOutlet UILabel * label ;ARC! 8/10
  9. 9. Tutorial ARCARC ne traite que l’objective-CAttention lors de l’utilisation d’API C, typiquement toutes les API Core, il faut utiliser lesopérateur de cast spécifiques à ARC.Par exemple sans arc on avait ce code :+ (NSString*) createUUID { NSString *udid; CFUUIDRef uuidRef = CFUUIDCreate(0); CFStringRef uuidStringRef = CFUUIDCreateString(NULL,uuidRef); udid = [NSString stringWithString:(NSString*)uuidStringRef]; CFRelease(uuidStringRef); CFRelease(uuidRef); return udid ;}Avec ARC il devient :+ (NSString*) createUUID { NSString *udid; CFUUIDRef uuidRef = CFUUIDCreate(0); CFStringRef uuidStringRef = CFUUIDCreateString(NULL,uuidRef); udid = [NSString stringWithString:(__bridge NSString*)uuidStringRef]; CFRelease(uuidStringRef); CFRelease(uuidRef); return udid ;}Ici ARC ne devient pas responsable de uuidStringRef, qui est libéré par le CFRelease,donc tout va bien.ou :+ (NSString*) createUUID { NSString *udid; CFUUIDRef uuidRef = CFUUIDCreate(0); CFStringRef uuidStringRef = CFUUIDCreateString(NULL,uuidRef); udid = [NSString stringWithString:(__bridge_transfer NSString*)uuidStringRef]; CFRelease(uuidStringRef); CFRelease(uuidRef); return udid ;}Dans ce second cas ARC devient responsable de uuidStringRef.Attention, il est donc libéré deux fois puisque le CFRelease le fait aussi, donc crash !On remarque que ARC ne s’occupant pas de toute ce qui est alloué parCore on a toujours les CFRelease !La bonne pratique consiste a laisser ARC traiter tout le code Objective-C, et traiter son code C comme d’habitude, c’est à dire avec lesCFRelease nécessaires, chacun son boulot !La première approche qui consiste à utiliser un cast (__bridgeNSString*) est donc préférable, en oubliant pas le CFRelease après biensur !ARC! 9/10
  10. 10. Tutorial ARCDésactiver ARC pour la compilation d’un sourceIl est possible de désactiver ARC, cela va se faire dans les préférences du projet, sur laTarget dans l’onglet Build Phases, pour le source sur lequel on ne souhaite pas utiliserARC il suffit d’ajouter le flag de compilation -fno-objc-arc Patrice Trognon <patrice.trognon@dlta-studio.com>ARC! 10/10

×