一 父子控制器
控制器需要了解的知识:
1 谁modal,谁dismiss
—-> dismiss的原理:判断当前的通知其是否是modal出来的控制器,如果是那么就dismiss;判断父控制器是否是modal出来的控制器,如果是,那么就dismiss,如果不是,那么就逐级的往上找,一直判断,直到没有父控制器.
2 拿到导航控制器的条件
—–> // 只要是导航控制器的子控制器就能拿到导航控制器
—–> // 判断下当前控制器是否是导航控制器的子控制,判断下自己的父控制器是否是导航控制器的子控制器,继续寻找有没有父控制器
3 addSubView的原理:只要添加一个viewA,先判断viewA有没有父控件,如果有父控件,先将父控件移除,在重新添加到对应的view
4 一个通过运用父子控制器实现的案例
4.1 功能图:(类似于UITabBarController功能)
—–> 原理:通过运用父子控制器的原理,我们始终只保证控制器的view只有一个.同时达到了控制器的切换,还有能监听选中后控制器的点击事件.
—–> 思路:
——-> 1上面部分的类似导航条的功能部分,采用一个view作为三个按钮的父控件.
——-> 2 创建三个控制器,我们都将控制器通过addChildViewController方法加入到父控制器中
——-> 3 当点击不同的按钮的时候,我们不是将控制器加入 ,而是将控制器的view加入到父控件的view中
——-> 4 如何保证程序运行中只有一个view呢?用一个普通的view来装容器,类似于UITabBarController一样装控件的view
代码块一:设置控制器
#pragma mark - 设置子控制器
- (void)setWithChildCode
{
XFJHotViewController *hvc = [[XFJHotViewController alloc] init];
hvc.title = @"热点";
[self addChildViewController:hvc];
XFJSocietyViewController *svc = [[XFJSocietyViewController alloc] init];
svc.title = @"社会";
[self addChildViewController:svc];
XFJTopLineViewController *lvc = [[XFJTopLineViewController alloc] init];
lvc.title = @"头条";
[self addChildViewController:lvc];
}
代码块二:设置按钮
#pragma mark - 设置按钮
- (void)setWithBtn
{
NSInteger count = self.titleView.subviews.count;
for (int i = 0; i < count; i++) {
UIButton *btn = self.titleView.subviews[i];
UIViewController *vc = self.childViewControllers[i];
[btn setTitle:vc.title forState:UIControlStateNormal];
}
}
代码块三:处理点击按钮的业务逻辑(采用直接拖线的方法)
#pragma mark - 按钮的业务逻辑
- (IBAction)titleBtnClick:(UIButton *)sender
{
for (UIView *view in self.contentView.subviews) {
NSLog(@"%@",self.contentView.subviews);
[view removeFromSuperview];
}
UIViewController *vc = self.childViewControllers[sender.tag];
vc.view.backgroundColor = sender.backgroundColor;
vc.view.frame = self.contentView.bounds;
[self.contentView addSubview:vc.view];
}
代码块四:设置一个view,用来装子控件的view(占位思想精华部分)
/**
* 用来接收控制器的view
*/
@property (weak, nonatomic) IBOutlet UIView *contentView;
5 其实上面的思想是用到了占位的思想,就是先用一个view将父控件的view占住一个位置,然后通过占据的位置来处理业务,通常是在开发中常用的一种思想.
二 MJ框架底层RunTime思想(二级模型转换)
条件:当模型中嵌套了一个模型的时候,也就是说字典中又含有字典的时候,需要我们做二级转换.
步骤:
—-> 1 遍历模型中的属性
—-> 2 判断属性的类型是否是字典的类型,满足条件才可以二级转换
—-> 3 如果是,字典的类型,那么就调用自己实现一级模型转换
—-> 4 根据key和value给模型属性赋值
底层的代码部分:
+ (instancetype)modelWithDict:(NSDictionary *)dict
{
id obj = [[self alloc] init];
NSInteger count = 0;
Ivar *ivarList = class_copyIvarList(self, &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivarList[i];
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
type = [type stringByReplacingOccurrencesOfString:@"@\"" withString:@""];
type = [type stringByReplacingOccurrencesOfString:@"\"" withString:@""];
NSString *key = [ivarName substringFromIndex:1];
id value = dict[key];
if ([value isKindOfClass:[NSDictionary class]] && ![type containsString:@"NS"]) {
Class className = NSClassFromString(type);
value = [className modelWithDict:dict];
}
if (value) {
[obj setValue:value forKey:key];
}
}
return obj;
}
三 总结
1 知道了MJ框架的底层实现,那么我们可以更加巧妙的利用MJ框架进行一些复杂的模型转换,同时我们甚至可以自己写框架,前提是有足够繁多的知识积累.
2 在开发中需要知道,当我们需要另外一种格式的控制器时,又想要和UITabBarController一样的功能的时候,我们完全可以自定义一个,同样而已达到功能的实现.
3 在开发中还有很多的不懂的地方,希望大家多多指教,谢谢!!!!