一個IOS中的自定義控件,每每是一個UIView的子類,可以獨立自主的完成一個特定功能。安全
可以稱爲控件,意味着它是由多個基本控件和控制方法組合在一塊兒,咱們默認爲它的內部複雜且精密,經不起任何意外的變更。ide
把它當作是一個黑盒子,咱們只考慮它的輸入是什麼,輸出是什麼。atom
咱們來看一個最簡單的封裝例子spa
#import <UIKit/UIKit.h> @protocol MyControlViewDelegate <NSObject> @optional - (void)myButtonTouched; @end @interface MyControlView : UIView @property (nonatomic, weak) id<MyControlViewDelegate> delegate; @end #import "MyControlView.h" @interface MyControlView() @property (nonatomic, strong) UIButton *myButton; @end @implementation MyControlView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setupInterface]; } return self; } - (void)setupInterface { self.myButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.myButton.frame = CGRectMake(50, 50, 200, 50); [self.myButton setTitle:@"testButton" forState:UIControlStateNormal]; [self.myButton addTarget:self action:@selector(buttonTouched) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:self.myButton]; } - (void)buttonTouched { if ([self.delegate respondsToSelector:@selector(myButtonTouched)]) { [self.delegate myButtonTouched]; } } @end
這個例子封裝了一個View,這個View裏包含了一個按鈕,當點擊按鈕的時候,會給它的delegate對象發送一個myButtonTouched消息。 code
從封裝的角度來看,這個例子沒有輸入,只有一個delegate輸出。咱們修改需求,如今咱們須要可以定製按鈕的title。orm
有一種作法是把myButton這個屬性設置爲public屬性,而後外部程序直接修改它的title。對象
還有一種作法是不開放myButton,而是設置一個工廠方法,在工廠方法裏去定製myButton的title。接口
咱們來分析一下這兩種方法的通用性和安全性:get
安全性: it
採用第一種方法,當有多個外部類都引用了同一個例子對象,其中某個外部類將self.myButton設置爲nil,很明顯,其餘外部類會出錯。
第二種方法則不會。
通用性:
採用第一種方法,當有多個外部類使用了例子類,當例子類進行版本升級,修改了按鈕的變量名,其餘外部類會出錯,必須逐個找出調用的具體代碼行進行修改。
第二種方法不須要這樣。
上面的例子告訴咱們封裝的第一個原則:
不要讓任何外部類可以看到封裝類的內部變量或內部方法。
若是將某個內部方法開放出來做爲對外的接口,則必須在任意版本中保持方法的輸入,輸出及方法名稱不變。
剛纔例子的變化版本:
#import <UIKit/UIKit.h> @protocol MyControlViewDelegate <NSObject> @optional - (void)myButtonTouched; @end @interface MyControlView : UIView @property (nonatomic, weak) id<MyControlViewDelegate> delegate; - (id)initWithFrame:(CGRect)frame ButtonTitle:(NSString *)buttonTitle; @end #import "MyControlView.h" @interface MyControlView() @property (nonatomic, strong) NSString *buttonTitle; @property (nonatomic, strong) UIButton *myButton; @end @implementation MyControlView - (id)initWithFrame:(CGRect)frame ButtonTitle:(NSString *)buttonTitle { self = [super initWithFrame:frame]; if (self) { self.buttonTitle = buttonTitle; [self setupInterface]; } return self; } - (void)setupInterface { self.myButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.myButton.frame = CGRectMake(50, 50, 200, 50); [self.myButton setTitle:self.buttonTitle forState:UIControlStateNormal]; [self.myButton addTarget:self action:@selector(buttonTouched) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:self.myButton]; } - (void)buttonTouched { if ([self.delegate respondsToSelector:@selector(myButtonTouched)]) { [self.delegate myButtonTouched]; } } @end