layout: true class: middle .center[ # Histoire d’IBOutlets ] .footnote.center[[bou.io/talks/iboutlets.html](http://bou.io/talks/iboutlets.html)] --- --- .center[ ``` #ifndef IBOutlet #define IBOutlet #endif ``` ] --- layout:false # Old-style Cocoa .footnote[ * Objective-C « 1.0 », * Plus vieux que le Key-Value Coding. * alloc/initWithCoder, puis assignation à un ivar. ] ``` @interface MyController : NSObject{ IBOutlet NSView * _anOutlet; } @end ``` ``` @implementation MyController - (void) dealloc { [anOutlet release]; anOutlet = nil; [super dealloc]; } @end ``` --- # Objective-C 2.0 Declared Properties .footnote[ * Le *NibLoading* utilise la méthode `set
` si elle existe. * Guidelines Apple: utiliser `retain` pour les vues racines, `assign` pour les autres. * Mais il faut les mettre à nil quand même. ] ``` @interface MyController : NSObject @property (nonatomic,retain) IBOutlet NSView * anOutlet; @end ``` ``` @implementation MyController @synthesize anOutlet=_anOutlet; - (void) dealloc { [anOutlet release]; anOutlet = nil; [super dealloc]; } @end ``` --- # Declared Properties, simplifiées .footnote[ * Le locking (`atomic`) est inutile, mais en général, il n'y a pas de problème de performance. * Autant supprimer du code. ] ``` @interface MyController : NSObject @property (retain) IBOutlet NSView * anOutlet; @end ``` ``` @implementation MyController @synthesize anOutlet=_anOutlet; - (void) dealloc { [anOutlet release]; anOutlet = nil; [super dealloc]; } @end ``` --- # Private Class Extension .footnote[ * Les outlets ne sont pas une API du ViewController * Ils sont à leur place dans le `.m`. ] ``` @interface MyController : NSObject @end ``` ``` @interface MyController() @property (retain) IBOutlet NSView * anOutlet; @end @implementation MyController @synthesize anOutlet=_anOutlet; - (void) dealloc { [anOutlet release]; anOutlet = nil; [super dealloc]; } @end ``` --- # iPhone OS : UIViewController .footnote[ * Le *NibLoading* utilise le Key-Value Coding sur iOS. ] ``` @interface MyController : UIViewController @end ``` ``` @interface MyController() @property (retain) IBOutlet UIView * anOutlet; @end @implementation MyController @synthesize anOutlet=_anOutlet; - (void) dealloc { [anOutlet release]; anOutlet = nil; [super dealloc]; } @end ``` --- # iPhone OS : UIViewController .footnote[ * La `view` du ViewController peut-être libérée! ] ``` @interface MyController : UIViewController @end ``` ``` @interface MyController() @property (retain) IBOutlet UIView * anOutlet; @end @implementation MyController @synthesize anOutlet=_anOutlet; - (void) viewDidUnload { self.anOutlet = nil; [super viewDidUnload]; } - (void) dealloc { [anOutlet release]; anOutlet = nil; [super dealloc]; } @end ``` --- # ARC .footnote[ * On se débarasse de `dealloc`. * Les Mots-clés `strong` et `weak` remplacent `retain` et `assign`. * `@synthesize` est simplifié ] ``` @interface MyController : UIViewController @end ``` ``` @interface MyController() @property (strong) IBOutlet UIView * anOutlet; @end @implementation MyController @synthesize anOutlet; - (void) viewDidUnload { self.anOutlet = nil; [super viewDidUnload]; } @end ``` --- # ARC + Weak .footnote[ * Les outlets `weak` sont mis à `nil` automatiquement. ] ``` @interface MyController : UIViewController @end ``` ``` @interface MyController() @property (weak) IBOutlet UIView * anOutlet; @end @implementation MyController @synthesize anOutlet; - (void) viewDidUnload { [super viewDidUnload]; } @end ``` --- # Properties `strong` par default .footnote[ * On peut retirer l’attribut. ] ``` @interface MyController : UIViewController @end ``` ``` @interface MyController() @property IBOutlet UIView * anOutlet; @end @implementation MyController @synthesize anOutlet; - (void) viewDidUnload { self.anOutlet = nil; [super viewDidUnload]; } @end ``` --- # Autosynthesize .footnote[ * On peut retirer le `@synthesize`. ] ``` @interface MyController : UIViewController @end ``` ``` @interface MyController() @property IBOutlet UIView * anOutlet; @end @implementation MyController - (void) viewDidUnload { self.anOutlet = nil; [super viewDidUnload]; } @end ``` --- # `viewDidUnload` deprecated .footnote[ * Les outlets ne sont jamais libérés avant le ViewController. * On peut toujours utiliser `strong`. * (C’est-à-dire, ne pas spécifier d’attribut.) ] ``` @interface MyController : UIViewController @end ``` ``` @interface MyController() @property IBOutlet UIView * anOutlet; @end @implementation MyController @end ``` --- # Private iVar .footnote[ * Les iVar sont strong par défaut. * Le KVO n'a que très peu d’intérêt pour des outlets. ] ``` @interface MyController : UIViewController @end ``` ``` @interface MyController() { IBOutlet UIView * _anOutlet; } @end @implementation MyController @end ``` --- # Private iVar .footnote[ * Autant le déclarer directement dans le bloc @implementation. ] ``` @interface MyController : UIViewController @end ``` ``` @implementation MyController{ IBOutlet UIView * _anOutlet; } @end ``` --- # ``` @interface MyController : UIViewController @end ``` ``` @implementation MyController{ IBOutlet UIView * _anOutlet; } @end ``` .center[ # Done ] -- .center[Resource Programming Guide : [Nib Files](https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html)] .footnote.right[Nicolas Bouilleaud — 2013
[@_nb](http://twitter.com/_nb)
[bou.io/talks/iboutlets.html](http://bou.io/talks/iboutlets.html)]