iOS UI Component API Design
-
Upload
brian-gesiak -
Category
Technology
-
view
10.586 -
download
1
Transcript of iOS UI Component API Design
![Page 1: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/1.jpg)
iOS UI Component DesignConfiguration and Callbacks Using the “Parameter Object” Pattern
Brian Gesiak
April 9th, 2014
Research Student, The University of Tokyo
@modocache
![Page 2: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/2.jpg)
Today
• Problem: How do we allow users to customize UI elements?
• Appearance, animations, and behavior should be customizable
• Composition over inheritance • Solution: Configuration objects !
• Problem: How do we define an API for callbacks? • Public delegate and block callbacks are hard to deprecate or change
• Solution: Parameter objects
![Page 3: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/3.jpg)
Customization API ExampleJVFloatLabeledTextField
![Page 4: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/4.jpg)
Customization API ExampleJVFloatLabeledTextField
![Page 5: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/5.jpg)
Customization API ExampleJVFloatLabeledTextField Appearance API
![Page 6: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/6.jpg)
Customization API ExampleJVFloatLabeledTextField Appearance API
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
![Page 7: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/7.jpg)
Customization API ExampleJVFloatLabeledTextField Appearance API
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
![Page 8: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/8.jpg)
Customization API ExampleJVFloatLabeledTextField Appearance API
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
![Page 9: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/9.jpg)
Customization API ExampleJVFloatLabeledTextField Appearance API
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
![Page 10: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/10.jpg)
But What About Categories?Favoring Composition Over Inheritance
![Page 11: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/11.jpg)
But What About Categories?
• JVFloatLabeledTextField is a subclass of UITextField
Favoring Composition Over Inheritance
![Page 12: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/12.jpg)
But What About Categories?
• JVFloatLabeledTextField is a subclass of UITextField• We need to use the class for its functionality
Favoring Composition Over Inheritance
![Page 13: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/13.jpg)
But What About Categories?
• JVFloatLabeledTextField is a subclass of UITextField• We need to use the class for its functionality • We’re forced to choose it or other useful subclasses
Favoring Composition Over Inheritance
![Page 14: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/14.jpg)
But What About Categories?
• JVFloatLabeledTextField is a subclass of UITextField• We need to use the class for its functionality • We’re forced to choose it or other useful subclasses• We need to subclass it to add functionality
Favoring Composition Over Inheritance
![Page 15: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/15.jpg)
But What About Categories?
• JVFloatLabeledTextField is a subclass of UITextField• We need to use the class for its functionality • We’re forced to choose it or other useful subclasses• We need to subclass it to add functionality• It forces itself upon our inheritance hierarchy
Favoring Composition Over Inheritance
![Page 16: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/16.jpg)
But What About Categories?
• JVFloatLabeledTextField is a subclass of UITextField• We need to use the class for its functionality • We’re forced to choose it or other useful subclasses• We need to subclass it to add functionality• It forces itself upon our inheritance hierarchy
Favoring Composition Over Inheritance
• If it were a category, we’d be able to use it with any UITextField
![Page 17: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/17.jpg)
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
But What About Categories?Favoring Composition Over Inheritance
![Page 18: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/18.jpg)
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
But What About Categories?Favoring Composition Over Inheritance
![Page 19: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/19.jpg)
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
But What About Categories?Favoring Composition Over Inheritance
![Page 20: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/20.jpg)
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
But What About Categories?Favoring Composition Over Inheritance
@interface UITextField (JVFloatLabeledTextField)
![Page 21: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/21.jpg)
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
But What About Categories?Favoring Composition Over Inheritance
@interface UITextField (JVFloatLabeledTextField)
![Page 22: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/22.jpg)
@interface JVFloatLabeledTextField : UITextField !@property (nonatomic, strong) NSNumber *floatingLabelYPadding UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIFont *floatingLabelFont UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, strong) UIColor *floatingLabelActiveTextColor UI_APPEARANCE_SELECTOR; @property (nonatomic, assign) NSInteger animateEvenIfNotFirstResponder UI_APPEARANCE_SELECTOR; !@end
But What About Categories?Favoring Composition Over Inheritance
objc_setAssociatedObject@interface UITextField (JVFloatLabeledTextField)
![Page 23: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/23.jpg)
But What About Categories?Favoring Composition Over Inheritance
![Page 24: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/24.jpg)
But What About Categories?Favoring Composition Over Inheritance
static void *JVFloatingLabelYPaddingKey = &JVFloatingLabelYPaddingKey; !- (void)setFloatingLabelYPadding:(NSNumber *)floatingLabelYPadding { objc_setAssociatedObject(self, JVFloatingLabelYPaddingKey, floatingLabelYPadding, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } !- (NSNumber *)floatingLabelYPadding { return objc_getAssociatedObject(self, JVFloatingLabelYPaddingKey); } !/// Add custom setters and getters for all properties
![Page 25: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/25.jpg)
But What About Categories?Favoring Composition Over Inheritance
static void *JVFloatingLabelYPaddingKey = &JVFloatingLabelYPaddingKey; !- (void)setFloatingLabelYPadding:(NSNumber *)floatingLabelYPadding { objc_setAssociatedObject(self, JVFloatingLabelYPaddingKey, floatingLabelYPadding, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } !- (NSNumber *)floatingLabelYPadding { return objc_getAssociatedObject(self, JVFloatingLabelYPaddingKey); } !/// Add custom setters and getters for all properties
![Page 26: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/26.jpg)
But What About Categories?Favoring Composition Over Inheritance
static void *JVFloatingLabelYPaddingKey = &JVFloatingLabelYPaddingKey; !- (void)setFloatingLabelYPadding:(NSNumber *)floatingLabelYPadding { objc_setAssociatedObject(self, JVFloatingLabelYPaddingKey, floatingLabelYPadding, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } !- (NSNumber *)floatingLabelYPadding { return objc_getAssociatedObject(self, JVFloatingLabelYPaddingKey); } !/// Add custom setters and getters for all properties
![Page 27: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/27.jpg)
But What About Categories?Favoring Composition Over Inheritance
static void *JVFloatingLabelYPaddingKey = &JVFloatingLabelYPaddingKey; !- (void)setFloatingLabelYPadding:(NSNumber *)floatingLabelYPadding { objc_setAssociatedObject(self, JVFloatingLabelYPaddingKey, floatingLabelYPadding, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } !- (NSNumber *)floatingLabelYPadding { return objc_getAssociatedObject(self, JVFloatingLabelYPaddingKey); } !/// Add custom setters and getters for all properties
![Page 28: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/28.jpg)
But What About Categories?Favoring Composition Over Inheritance
static void *JVFloatingLabelYPaddingKey = &JVFloatingLabelYPaddingKey; !- (void)setFloatingLabelYPadding:(NSNumber *)floatingLabelYPadding { objc_setAssociatedObject(self, JVFloatingLabelYPaddingKey, floatingLabelYPadding, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } !- (NSNumber *)floatingLabelYPadding { return objc_getAssociatedObject(self, JVFloatingLabelYPaddingKey); } !/// Add custom setters and getters for all properties
![Page 29: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/29.jpg)
But What About Categories?Favoring Composition Over Inheritance
static void *JVFloatingLabelYPaddingKey = &JVFloatingLabelYPaddingKey; !- (void)setFloatingLabelYPadding:(NSNumber *)floatingLabelYPadding { objc_setAssociatedObject(self, JVFloatingLabelYPaddingKey, floatingLabelYPadding, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } !- (NSNumber *)floatingLabelYPadding { return objc_getAssociatedObject(self, JVFloatingLabelYPaddingKey); } !/// Add custom setters and getters for all properties
![Page 30: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/30.jpg)
But What About Categories?Favoring Composition Over Inheritance
static void *JVFloatingLabelYPaddingKey = &JVFloatingLabelYPaddingKey; !- (void)setFloatingLabelYPadding:(NSNumber *)floatingLabelYPadding { objc_setAssociatedObject(self, JVFloatingLabelYPaddingKey, floatingLabelYPadding, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } !- (NSNumber *)floatingLabelYPadding { return objc_getAssociatedObject(self, JVFloatingLabelYPaddingKey); } !/// Add custom setters and getters for all properties
Doesn’t scale
![Page 31: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/31.jpg)
Configuration ObjectsEncapsulate Configuration
![Page 32: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/32.jpg)
Configuration ObjectsEncapsulate Configuration
![Page 33: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/33.jpg)
Configuration ObjectsEncapsulate Configuration
![Page 34: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/34.jpg)
Configuration ObjectsEncapsulate Configuration
![Page 35: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/35.jpg)
Configuration ObjectsEncapsulate Configuration
![Page 36: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/36.jpg)
Configuration Object ExampleMDCSwipeToChoose
![Page 37: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/37.jpg)
Configuration Object ExampleMDCSwipeToChoose
![Page 38: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/38.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 39: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/39.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 40: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/40.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 41: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/41.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 42: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/42.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 43: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/43.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 44: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/44.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 45: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/45.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 46: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/46.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 47: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/47.jpg)
Configuration Object ExampleMDCSwipeToChoose
MDCSwipeOptions *options = [MDCSwipeOptions new]; options.delegate = self; options.onPan = ^(MDCPanState *state){ switch (state.direction) { case MDCSwipeDirectionLeft: self.webView.alpha = 0.5f - state.thresholdRatio; break; case MDCSwipeDirectionRight: self.webView.alpha = 0.5f + state.thresholdRatio; break; case MDCSwipeDirectionNone: self.webView.alpha = 0.5f; break; } }; ![self.webView mdc_swipeToChooseSetup:options];
![Page 48: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/48.jpg)
Parameter Objects for BlocksExtensible Block Signatures
![Page 49: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/49.jpg)
options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };
Parameter Objects for BlocksExtensible Block Signatures
![Page 50: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/50.jpg)
options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };
Parameter Objects for BlocksExtensible Block Signatures
![Page 51: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/51.jpg)
options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };
Parameter Objects for BlocksExtensible Block Signatures
![Page 52: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/52.jpg)
options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };
Parameter Objects for BlocksExtensible Block Signatures
![Page 53: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/53.jpg)
options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };
Parameter Objects for BlocksExtensible Block Signatures
options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;
![Page 54: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/54.jpg)
options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };
Parameter Objects for BlocksExtensible Block Signatures
options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;
![Page 55: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/55.jpg)
Extensible Block ArgumentsUpdate the API without Breaking Old Versions
@interface MDCPanState : NSObject !@property (nonatomic, strong) UIView *view; @property (nonatomic, assign) MDCSwipeDirection direction; @property (nonatomic, assign) CGFloat thresholdRatio; !@end
![Page 56: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/56.jpg)
Extensible Block ArgumentsUpdate the API without Breaking Old Versions
@interface MDCPanState : NSObject !@property (nonatomic, strong) UIView *view; @property (nonatomic, assign) MDCSwipeDirection direction; @property (nonatomic, assign) CGFloat thresholdRatio; !@end
DEPRECATED_ATTRIBUTE;
![Page 57: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/57.jpg)
options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };
options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;
Extensible Block Arguments Slowly Phase Out Deprecated Parameters
![Page 58: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/58.jpg)
options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };
options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;
Extensible Block Arguments Slowly Phase Out Deprecated Parameters
![Page 59: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/59.jpg)
options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };
options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;
Extensible Block Arguments Slowly Phase Out Deprecated Parameters
![Page 60: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/60.jpg)
Takeaways
• Favor composition over inheritance when building UI components
• Build extensible, future-proof customization APIs using parameter objects
• Parameter objects are especially useful as block arguments
![Page 61: iOS UI Component API Design](https://reader033.fdocuments.in/reader033/viewer/2022052618/554fae90b4c905ad218b50d4/html5/thumbnails/61.jpg)
Additional Resources
• Follow me on Twitter and GitHub at @modocache • Today’s slides
• http://modocache.io/ios-ui-component-api-design • JVFloatLabeledTextField
• https://github.com/jverdi/JVFloatLabeledTextField • MDCSwipeToChoose
• https://github.com/modocache/MDCSwipeToChoose • The Parameter Object Design Pattern
• http://c2.com/cgi/wiki?ParameterObject