ios ui component api design

60
UI コンポーネント API デザイン 「パラメータ・オブジェクト」パターン Brian Gesiak 201449Research Student, The University of Tokyo @modocache #potatotips

Upload: brian-gesiak

Post on 11-May-2015

12.503 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: iOS UI Component API Design

UIコンポーネントAPIデザイン「パラメータ・オブジェクト」パターン

Brian Gesiak

2014年4月9日

Research Student, The University of Tokyo

@modocache #potatotips

Page 2: iOS UI Component API Design

内容•課題:カスタマイズ用のAPIをどう提供するか

•細かいところまでカスタマイズしたい •継承より組み立てを好む

•解決策:設定オブジェクト •設定オブジェクト

!

•課題:コールバックのAPI

•ブロックやdelegateメソッドのパラメータが確定してしまうとなかなか変えられない

•解決策:パラメータ・オブジェクト

Page 3: iOS UI Component API Design

カスタマイズ用のAPIの一例JVFloatLabeledTextField

Page 4: iOS UI Component API Design

カスタマイズ用のAPIの一例JVFloatLabeledTextField

Page 5: iOS UI Component API Design

カスタマイズ用のAPIの一例JVFloatLabeledTextField

Page 6: iOS UI Component API Design

カスタマイズ用のAPIの一例JVFloatLabeledTextField

@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

カスタマイズ用のAPIの一例JVFloatLabeledTextField

@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

カスタマイズ用のAPIの一例JVFloatLabeledTextField

@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

カスタマイズ用のAPIの一例JVFloatLabeledTextField

@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

継承するのか?継承より組み立てを好む

Page 11: iOS UI Component API Design

継承するのか?

• JVFloatLabeledTextFieldはUITextFieldのサブクラス

継承より組み立てを好む

Page 12: iOS UI Component API Design

継承するのか?

• JVFloatLabeledTextFieldはUITextFieldのサブクラス•機能がほしければこのクラスを使うしかない

継承より組み立てを好む

Page 13: iOS UI Component API Design

継承するのか?

• JVFloatLabeledTextFieldはUITextFieldのサブクラス•機能がほしければこのクラスを使うしかない•機能を追加したければサブクラスを新たに定義するしかない

継承より組み立てを好む

Page 14: iOS UI Component API Design

継承するのか?

• JVFloatLabeledTextFieldはUITextFieldのサブクラス•機能がほしければこのクラスを使うしかない•機能を追加したければサブクラスを新たに定義するしかない

• JVFloatLabeledTextFieldは継承ヒエラルキーに自分をねじ込んでいる

継承より組み立てを好む

Page 15: iOS UI Component API Design

継承するのか?

• JVFloatLabeledTextFieldはUITextFieldのサブクラス•機能がほしければこのクラスを使うしかない•機能を追加したければサブクラスを新たに定義するしかない

• JVFloatLabeledTextFieldは継承ヒエラルキーに自分をねじ込んでいる

継承より組み立てを好む

•カテゴリーだったら、どのUITextFieldでも使える

Page 16: iOS UI Component API Design

@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 17: iOS UI Component API Design

@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 18: iOS UI Component API Design

@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 19: iOS UI Component API Design

@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

継承するのか?継承より組み立てを好む

@interface UITextField (JVFloatLabeledTextField)

Page 20: iOS UI Component API Design

@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

継承するのか?継承より組み立てを好む

@interface UITextField (JVFloatLabeledTextField)

Page 21: iOS UI Component API Design

@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

継承するのか?継承より組み立てを好む

objc_setAssociatedObject@interface UITextField (JVFloatLabeledTextField)

Page 22: iOS UI Component API Design

継承するのか?継承より組み立てを好む

Page 23: iOS UI Component API Design

継承するのか?継承より組み立てを好む

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 24: iOS UI Component API Design

継承するのか?継承より組み立てを好む

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

継承するのか?継承より組み立てを好む

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

継承するのか?継承より組み立てを好む

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

継承するのか?継承より組み立てを好む

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

継承するのか?継承より組み立てを好む

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

継承するのか?継承より組み立てを好む

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

設定オブジェクトカスタマイズ用のパラメータを束ねる

Page 31: iOS UI Component API Design

設定オブジェクトカスタマイズ用のパラメータを束ねる

Page 32: iOS UI Component API Design

設定オブジェクトカスタマイズ用のパラメータを束ねる

Page 33: iOS UI Component API Design

設定オブジェクトカスタマイズ用のパラメータを束ねる

Page 34: iOS UI Component API Design

設定オブジェクトカスタマイズ用のパラメータを束ねる

Page 35: iOS UI Component API Design

設定オブジェクトの一例MDCSwipeToChoose

Page 36: iOS UI Component API Design

設定オブジェクトの一例MDCSwipeToChoose

Page 37: iOS UI Component API Design

設定オブジェクトの一例MDCSwipeToChoose

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 38: iOS UI Component API Design

設定オブジェクトの一例MDCSwipeToChoose

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

設定オブジェクトの一例MDCSwipeToChoose

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

設定オブジェクトの一例MDCSwipeToChoose

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

設定オブジェクトの一例MDCSwipeToChoose

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

設定オブジェクトの一例MDCSwipeToChoose

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

設定オブジェクトの一例MDCSwipeToChoose

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

設定オブジェクトの一例MDCSwipeToChoose

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

設定オブジェクトの一例MDCSwipeToChoose

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

設定オブジェクトの一例MDCSwipeToChoose

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

パラメータ・オブジェクトブロックのシグネチャの変化を回避する

Page 48: iOS UI Component API Design

options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };

パラメータ・オブジェクトブロックのシグネチャの変化を回避する

Page 49: iOS UI Component API Design

options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };

パラメータ・オブジェクトブロックのシグネチャの変化を回避する

Page 50: iOS UI Component API Design

options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };

パラメータ・オブジェクトブロックのシグネチャの変化を回避する

Page 51: iOS UI Component API Design

options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };

パラメータ・オブジェクトブロックのシグネチャの変化を回避する

Page 52: iOS UI Component API Design

options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };

パラメータ・オブジェクトブロックのシグネチャの変化を回避する

options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;

Page 53: iOS UI Component API Design

options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };

パラメータ・オブジェクトブロックのシグネチャの変化を回避する

options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;

Page 54: iOS UI Component API Design

パラメータ・オブジェクトAPIの微調整、バージョニングが可能

@interface MDCPanState : NSObject !@property (nonatomic, strong) UIView *view; @property (nonatomic, assign) MDCSwipeDirection direction; @property (nonatomic, assign) CGFloat thresholdRatio; !@end

Page 55: iOS UI Component API Design

パラメータ・オブジェクトAPIの微調整、バージョニングが可能

@interface MDCPanState : NSObject !@property (nonatomic, strong) UIView *view; @property (nonatomic, assign) MDCSwipeDirection direction; @property (nonatomic, assign) CGFloat thresholdRatio; !@end

DEPRECATED_ATTRIBUTE;

Page 56: iOS UI Component API Design

options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };

options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;

パラメータ・オブジェクトサポートしないパラメータを少しずつ排除

Page 57: iOS UI Component API Design

options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };

options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;

パラメータ・オブジェクトサポートしないパラメータを少しずつ排除

Page 58: iOS UI Component API Design

options.onPan = ^(UIView *view, MDCSwipeDirection direction, CGFloat thresholdRatio){ if (direction == MDCSwipeDirectionLeft) { NSLog(@"Panning to the left..."); } };

options.onPan = ^(MDCPanState *state){ MDCSwipeDirection direction = state.direction;

パラメータ・オブジェクトサポートしないパラメータを少しずつ排除

Page 59: iOS UI Component API Design

要約

•継承に頼らないUIコンポーネントを好む •設定オブジェクトで、クリーンなカスタマイズ用のAPIを提供できる

•パラメータ・オブジェクトというデザイン・パターンは、シグネチャの変化を未然に防ぐ

•特にブロックのパラメータに有用

Page 60: iOS UI Component API Design

ご参考までに•本日のスライド

• http://modocache.io/ios-ui-component-api-design •ぜひフォローして下さい

• Twitter: @modocache • GitHub: https://github.com/modocache

• JVFloatLabeledTextField • https://github.com/jverdi/JVFloatLabeledTextField

• MDCSwipeToChoose(おいらに☆を!) • https://github.com/modocache/MDCSwipeToChoose

•「パラメータ・オブジェクト」デザイン・パターン(英語) • http://c2.com/cgi/wiki?ParameterObject