用xib做公共組件

現(xiàn)狀

1揽碘、用代碼寫的公共view次屠,用起來比較簡單,不論是代碼方式還是IB方式雳刺,都很簡單劫灶;
2、用xib寫的組件掖桦,需要調用者來加載本昏,用代碼方式加入到原有的視圖體系中;如果調用者是用IB畫界面的枪汪,那么就要用代碼設限制或者定frame涌穆,不是很方便

改進點

將加載代碼從調用者移到公共組件內(nèi)部,讓IB開發(fā)界面的調用者只要拉一個IBOutlet就可以訪問了料饥,不需要own這個公共組件對象,和系統(tǒng)組件一樣方便使用朱监。

xib加載過程

函數(shù)調用情況

  • 不會自動調用的函數(shù)
  - (instancetype)init {
    self = [super init];
    
    if (self) {
        [self loadViewFromXib];
    }
    
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    
    if (self) {
        [self loadViewFromXib];
    }
    
    return self;
}
  • 自動調用的函數(shù)
- (void)awakeFromNib {
    [self loadViewFromXib];
}

- initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder: aDecoder];
    
    if (self) {
        [self loadViewFromXib];
    }
    
    return self;
}

選擇的加載函數(shù)

- (void)awakeFromNib {
    [self loadViewFromXib];
}

自動加載岸啡,通過IBOutlet的方式訪問對象,調用者不需要own這個組件

加載的代碼

- (void)loadViewFromXib {
    NSArray *views = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil];
    UIView *view = [views firstObject];
    
    if (nil != view) {
        UIView *superview = self;
        
        [superview addSubview:view];
        
        UIEdgeInsets padding = UIEdgeInsetsMake(0, 0, 0, 0);
        
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(superview).with.insets(padding);
        }];
    }
}
  1. 需要將xib的File's Owner 設置為自定義的組件類
  2. xib中頂級的view就是load函數(shù)加載等到的view赫编,只是個容器
  3. 將容器view以addSubview的方式添加到自定義的組件類(self)
  4. 代碼加限制巡蘸,將容器view和自定義的組件類(self)完全重合奋隶,使self成了最底層的容器

加載完后執(zhí)行的函數(shù)

// View在加載完成之后,會自動調用這個函數(shù)悦荒,這里可以更新約束
- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    
    // 其它代碼

    // 變換約束之后唯欣,重新布局,以便取到正確的frame
    [self layoutIfNeeded]; 

    // 這個函數(shù)執(zhí)行完搬味,一般要加這句境氢,更新View
    [self setNeedsDisplay];
}

自動函數(shù)加載順序

場景:ViewController作為調度者。用xib做一個自定義的view名字叫ChartView碰纬,供外部調用萍聊。xib中用代碼做一個自定義的view,叫PlotView悦析,用來畫圖表寿桨。經(jīng)過斷點實驗,加載順序如下

  1. ChartView: - (void)awakeFromNib
  2. ViewController: - (void)viewDidLoad
  3. ViewController: - (void)viewWillAppear:(BOOL)animated
  4. ViewController: - (void)viewWillLayoutSubviews
  5. ViewController: - (void)viewDidLayoutSubviews
  6. ChartView: - (void)drawRect:(CGRect)rect
  7. PlotView: - (void)drawRect:(CGRect)rect
  8. ViewController: - (void)viewDidAppear:(BOOL)animated

這個調用關系就是導致有些函數(shù)放在- (void)viewDidLoad- (IBAction)buttonTouched:(UIButton *)sender中有不同表現(xiàn)的原因

難點

  1. 一般xib的File's Owner是ViewController强戴,所以Xcode默認讓xib對應一個ViewController
  2. tableViewCell的File's Owner是空的(NSObject)亭螟,最頂層的view容器設置為自定義的Cell類,所以需要對應的ViewController來加載這個cell骑歹,調用者ViewController擁有own這個cell(strong引用)
  3. 一般的xib公共組件预烙,F(xiàn)ile's Owner是空的(NSObject),所以需要調用者加載陵刹,調用這own這個組件默伍。做法就是將最頂層view設置為自定義的組件類。這個跟tableViewCell的用法很像衰琐。
  4. 將xib的File's Owner設置為自定義的類之后也糊,頂層的view容器的own是自定義的類自身self,所以這個view的引用是strong羡宙,雖然是IBOutlet狸剃,跟其它的不一樣
    @property (strong, nonatomic) IBOutlet UIView *containerView;
  5. 自定義類的owner是調用者的xib文件,所以自定義類本身(self)在調用者類中可以是弱引用狗热,weak钞馁,像普通的IBOutlet一樣
    @property (weak, nonatomic) IBOutlet PAButtonWithBadgeView *buttonWithBadgeView;

注意點

由于自定義類本身是最底層的view容器,而xib中的View容器完全覆蓋在上面匿刮,所有擋住了僧凰,這個導致設置自定義的背景色不起作用。解決的方法是重寫基類的設置函數(shù)

// self是最底層容器熟丸,會被self.containerView擋住训措,導致看起來代碼設背景色不起作用,所以覆蓋基類的函數(shù)
- (void)setBackgroundColor:(UIColor *)backgroundColor {
    if (nil != backgroundColor) {
        self.backgroundColor = backgroundColor;
        [self setContainerColor:backgroundColor];
    }
}

- (void)setContainerColor:(UIColor *)color {
    if (nil != color) {
        self.containerView.backgroundColor = color;
    }
} ```
> 遺留問題:
這樣做,代碼設背景色绩鸣,看上去是變了怀大;但是,直接在調用者xib中設置自定義組件的背景色呀闻,還是不起作用的

# 備選方案
在自定義組件的xib中化借,頂層view容器的背景色設置為clearColor。這樣自定義組件的背景色完全由自定義組件自身來決定捡多。調用者在xib和代碼設置背景色都能成功蓖康。但是這樣會導致如下不完美之處:

* 在自定義組件設計的xib中,背景色就是一片空白局服,失去了所見即所得的優(yōu)勢钓瞭。
* 在實際使用過程中,自定義組件都是用view拉一個占位符淫奔,其它的具體內(nèi)容還是要切換到自定義組件的xib中去看具體內(nèi)容山涡。背景色在這里,更有意義唆迁。

**正是為了發(fā)揮xib更直觀的優(yōu)勢鸭丛,所以采用了上面那種不完美的方案√圃穑基于一個假設:在總的xib上的占位符上用IB設背景色鳞溉,沒有什么意義。將背景色和自定義組件的xib具體內(nèi)容結合起來看更有意義鼠哥。**

# 實例代碼

[zhangxusong888/PAButtonWithBadgeViewTest](https://github.com/zhangxusong888/PAButtonWithBadgeViewTest)

作為對比熟菲,下面這個例子是純代碼寫的控件

[zhangxusong888/PAProcessBarTest](https://github.com/zhangxusong888/PAProcessBarTest)
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市朴恳,隨后出現(xiàn)的幾起案子抄罕,更是在濱河造成了極大的恐慌,老刑警劉巖于颖,帶你破解...
    沈念sama閱讀 223,207評論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呆贿,死亡現(xiàn)場離奇詭異,居然都是意外死亡森渐,警方通過查閱死者的電腦和手機做入,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評論 3 400
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來同衣,“玉大人竟块,你說我怎么就攤上這事∧推耄” “怎么了浪秘?”我有些...
    開封第一講書人閱讀 170,031評論 0 366
  • 文/不壞的土叔 我叫張陵前弯,是天一觀的道長。 經(jīng)常有香客問我秫逝,道長,這世上最難降的妖魔是什么询枚? 我笑而不...
    開封第一講書人閱讀 60,334評論 1 300
  • 正文 為了忘掉前任违帆,我火速辦了婚禮,結果婚禮上金蜀,老公的妹妹穿的比我還像新娘刷后。我一直安慰自己,他們只是感情好渊抄,可當我...
    茶點故事閱讀 69,322評論 6 398
  • 文/花漫 我一把揭開白布尝胆。 她就那樣靜靜地躺著,像睡著了一般护桦。 火紅的嫁衣襯著肌膚如雪含衔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,895評論 1 314
  • 那天二庵,我揣著相機與錄音贪染,去河邊找鬼。 笑死催享,一個胖子當著我的面吹牛杭隙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播因妙,決...
    沈念sama閱讀 41,300評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼痰憎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了攀涵?” 一聲冷哼從身側響起铣耘,我...
    開封第一講書人閱讀 40,264評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎汁果,沒想到半個月后涡拘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,784評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡据德,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,870評論 3 343
  • 正文 我和宋清朗相戀三年鳄乏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棘利。...
    茶點故事閱讀 40,989評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡橱野,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出善玫,到底是詐尸還是另有隱情水援,我是刑警寧澤密强,帶...
    沈念sama閱讀 36,649評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站蜗元,受9級特大地震影響或渤,放射性物質發(fā)生泄漏。R本人自食惡果不足惜奕扣,卻給世界環(huán)境...
    茶點故事閱讀 42,331評論 3 336
  • 文/蒙蒙 一薪鹦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惯豆,春花似錦池磁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至芯杀,卻和暖如春端考,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背揭厚。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評論 1 275
  • 我被黑心中介騙來泰國打工跛梗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棋弥。 一個月前我還...
    沈念sama閱讀 49,452評論 3 379
  • 正文 我出身青樓核偿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親顽染。 傳聞我的和親對象是個殘疾皇子漾岳,可洞房花燭夜當晚...
    茶點故事閱讀 45,995評論 2 361

推薦閱讀更多精彩內(nèi)容