父子控制器和MJ框架底层RunTime思想(二)

来源:互联网 发布:多玩数据库魔兽3.35 编辑:程序博客网 时间:2024/06/07 12:56

一 父子控制器

控制器需要了解的知识:

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 = @"热点";    //添加控制器到view中    [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{    //拿到标题view的所有的子控件数    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{    //遍历contentView中所有的子控制器(移除多余的控制器view,只保证只有一个view)    for (UIView *view in self.contentView.subviews) {        NSLog(@"%@",self.contentView.subviews);        [view removeFromSuperview];    }    //根据tag.选择指定的控制器    UIViewController *vc = self.childViewControllers[sender.tag];    //设置控制器view的背景颜色    vc.view.backgroundColor = sender.backgroundColor;    //设置控制器view的尺寸    vc.view.frame = self.contentView.bounds;    //将控制器的view加入到contentView中    [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)];        //替换(由于获取的成员变量的类型格式是@"\User\"这种类型的,需要我们将@"和\"替换掉)        type = [type stringByReplacingOccurrencesOfString:@"@\"" withString:@""];        type = [type stringByReplacingOccurrencesOfString:@"\"" withString:@""];        //将成员变量的下划线截去掉        NSString *key = [ivarName substringFromIndex:1];        //从字典中取出对应的value(根据key)        id value = dict[key];        //判断只有是字典并且是自定义的才需要二级转换        if ([value isKindOfClass:[NSDictionary class]] && ![type containsString:@"NS"]) {            //获取类型            Class className = NSClassFromString(type);            //字典转模型            value = [className modelWithDict:dict];        }        if (value) {            //用key和value给模型中的属性赋值            [obj setValue:value forKey:key];        }    }    return obj;}

三 总结

1 知道了MJ框架的底层实现,那么我们可以更加巧妙的利用MJ框架进行一些复杂的模型转换,同时我们甚至可以自己写框架,前提是有足够繁多的知识积累.

2 在开发中需要知道,当我们需要另外一种格式的控制器时,又想要和UITabBarController一样的功能的时候,我们完全可以自定义一个,同样而已达到功能的实现.

3 在开发中还有很多的不懂的地方,希望大家多多指教,谢谢!!!!

1 0
原创粉丝点击