概述
為了快速開發(fā), 項目多出用到xib, xib的復(fù)用問題就一直存在, 最近不是很忙, 在想這個問題, 本來的加載xib的方法就是寫在分類里的, 所以都是調(diào)用一個方法, 若想實現(xiàn)統(tǒng)一方法調(diào)用, 或許可以實現(xiàn)重寫分類的方法, 但是每一個子類都要重寫才能正確, 很麻煩, 就沒有去實現(xiàn)了, 反正總體的思路就是先從自己的加載, 沒有就加載父類的, 一層層往上找, 所以就有了我這篇文章
按照慣例要上demo
要解決兩個問題:
- 子類沒有xib 然后從父類 一直往上找
- 實例化出來的對象的實際類型并不是當前子類 改變?yōu)楫斍暗淖宇?/li>
首先解決第一個問題
我是基于分類寫的:
+ (instancetype)fm_viewFromXib{
UIView *view = nil;
NSArray *views = nil;
views = [self fm_loadFromNib];
if (views == nil) {
return [[self alloc] init];
}
view = views.lastObject;
if (view == nil) {
return [[self alloc] init];
}
object_setClass(view, self);
return view;
}
優(yōu)先從xib加載, 沒有的從代碼實例化一個返回出去
具體來再看看fm_loadFromNib這個方法
+ (NSArray *)fm_loadFromNib{
if ([self fm_loadNibFromName:NSStringFromClass(self)]) {
return [self fm_loadNibFromName:NSStringFromClass(self)];
} else {
NSArray *arrM = nil;
NSString *name = NSStringFromClass([super class]);
while (![name isEqualToString:NSStringFromClass([UIResponder class])]) {
name = [self fm_xibFileName];
if ([self fm_loadNibFromName:name]) {
arrM = [self fm_loadNibFromName:name];
break;
} else {
Class superClass = NSClassFromString(name);
superClass = class_getSuperclass(superClass);
name = NSStringFromClass(superClass);
}
}
return arrM;
}
}
if判斷如果當前的類名的xib是可以加載出來的, 就直接返回房錢自己加載的 如果沒有就從父類, 父類不知道有多少級, 所以就有一個while循環(huán), 只要類不是UIResponder類 UIView的父類是UIResponder, 所以循環(huán)到UIResponder就停止
下面用了一點runtime的Api取父類, 我這里先去名字, 再從名字中獲取Class, 一開始我是想用super的, 發(fā)現(xiàn)根本不行, 因為你調(diào)用的是父類的發(fā)放, 但是類型還是自己, 所以就我暫且想到這個方法
+ (NSArray *)fm_loadNibFromName:(NSString *)name{
if ([self fm_isExsitNibWithName:name]) {
return [[NSBundle mainBundle] loadNibNamed:name owner:nil options:nil];
}
return nil;
}
+ (BOOL)fm_isExsitNibWithName:(NSString *)name{
return [[NSBundle mainBundle] pathForResource:name ofType:@"nib"] != nil;
}
以上兩個方法, 判斷Bundle有沒有nib這個文件, 這里也踩過一個坑, 想到用UINib去實例化看看有沒有, 然后發(fā)現(xiàn)當沒有這個對應(yīng)的nib文件去創(chuàng)建對象的時候就掛了, 總的來說這個問題解決了, 可能并不是那么的優(yōu)雅
第二個問題代碼中已經(jīng)貼了
object_setClass(view, self);
將當前實例化出來的對象的isa指向當前類, 調(diào)用子類的自己的方法就不會奔潰了
暫時xib默認的名字類名, 為了防止有不一樣的, 可以自定義, 繼承之后, 重寫fm_xibFileName方法即可
總結(jié)
有一點待優(yōu)化的就是 不同Bundle下的文件的繼承就出問題了 這里加載xib的時候 可以給個Bundle的參數(shù) 可以解決這個問題
對于xib重度使用的人而言應(yīng)該有點幫助吧
如果覺得對你有一點幫助, 那就動動手指點個贊吧
我的github
不是很擅長言辭, 但是比較喜歡研究一些問題, 如果你有問題, 或者我們可以交流交流, 不能保證給你解決, 或許能提供另一種思路