概述
为了快速开发, 项目多出用到xib, xib的复用问题就一直存在, 最近不是很忙, 在想这个问题, 本来的加载xib的方法就是写在分类里的, 所以都是调用一个方法, 若想实现统一方法调用, 或许可以实现重写分类的方法, 但是每一个子类都要重写才能正确, 很麻烦, 就没有去实现了, 反正总体的思路就是先从自己的加载, 没有就加载父类的, 一层层往上找, 所以就有了我这篇文章
按照惯例要上demo
要解决两个问题:
- 子类没有xib 然后从父类 一直往上找
- 实例化出来的对象的实际类型并不是当前子类 改变为当前的子类
首先解决第一个问题
我是基于分类写的:
+ (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;
}
优先从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循环, 只要类不是UIResponder类 UIView的父类是UIResponder, 所以循环到UIResponder就停止
下面用了一点runtime的Api取父类, 我这里先去名字, 再从名字中获取Class, 一开始我是想用super的, 发现根本不行, 因为你调用的是父类的发放, 但是类型还是自己, 所以就我暂且想到这个方法
+ (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去实例化看看有没有, 然后发现当没有这个对应的nib文件去创建对象的时候就挂了, 总的来说这个问题解决了, 可能并不是那么的优雅
第二个问题代码中已经贴了
object_setClass(view, self);
将当前实例化出来的对象的isa指向当前类, 调用子类的自己的方法就不会奔溃了
暂时xib默认的名字类名, 为了防止有不一样的, 可以自定义, 继承之后, 重写fm_xibFileName方法即可
总结
有一点待优化的就是 不同Bundle下的文件的继承就出问题了 这里加载xib的时候 可以给个Bundle的参数 可以解决这个问题
对于xib重度使用的人而言应该有点帮助吧
如果觉得对你有一点帮助, 那就动动手指点个赞吧
我的github
不是很擅长言辞, 但是比较喜欢研究一些问题, 如果你有问题, 或者我们可以交流交流, 不能保证给你解决, 或许能提供另一种思路