iPadiOS学习iPad 资料

iPad开发之自定义实现分屏控制器的功能

2016-05-24  本文已影响1612人  passionHan

前言

最近公司需要开发iPad版的应用程序,项目中要实现分屏控制器的功能,之前有了解到使用UISplitViewController可以实现分屏的功能,当时查了查资料,感觉挺简单的,但是随着研究的深入,发现并不是那么容易的,由于网上关于UISplitViewController的使用教程并不多,自定义实现分屏功能的教程就更少了,所以接下来我将把这几天对UISplitViewController的研究和自定义实现分屏控制器的功能的Demo分享给大家,希望能帮助到有这方面困惑的朋友。

使用系统的UISplitViewController

Demo中的第一个target是使用的UISplitViewController,通过storyboard实现,系统的UISplitViewController挺简单的,实现步骤:

  1. 在storyboard中添加一个UISplitViewController控制器,给DetailViewController包装一个导航控制器,这里在连线的时候要注意,要和splitViewController建立关系,选择detail view controller。
Paste_Image.png

2.新建一个控制器MainViewController继承自UISplitViewController,MasterTableViewController继承自UITableViewController,DetailViewController继承自UIViewController,并把相关控制器和storyboard中的相关联。

3.在MasterTableViewController中编写一个协议,主要思路就是MainViewController成为MasterTableViewController的代理,实现协议方法,从而和DetailViewController交互。

@protocol masterTableViewControllerDelegate <NSObject>

- (void)masterTableViewController:(MasterTableViewController *)masterVC didSelectedRow:(SingleModel *)singleModel;

@end

在MasterTableViewController中的tableView行点击事件中,调用代理方法,传递数据

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
    if ([self.delegate respondsToSelector:@selector(masterTableViewController:didSelectedRow:)]) {    
        GroupModel *groupModel = self.groupModel[indexPath.section];
        [self.delegate masterTableViewController:self didSelectedRow:groupModel.typeList[indexPath.row]];
    }
}

在MainViewController中,设置当前控制器为MasterTableViewController的代理,实现协议方法

- (void)viewDidLoad {
    [super viewDidLoad];

    //获取到导航控制器对象
    UINavigationController *masterNav = [self.childViewControllers firstObject];
    
    //获取到MasterTableViewController的对象
    MasterTableViewController *master = [masterNav.childViewControllers firstObject];
    
    master.delegate = self;
}
/**
 *  masterTableViewController的代理方法
 */
- (void)masterTableViewController:(MasterTableViewController *)masterVC didSelectedRow:(SingleModel *)singleModel{
    
    UINavigationController *detailNav = [self.childViewControllers lastObject];
    DetailViewController *detail = [detailNav.childViewControllers firstObject];
    
    detail.singleModel = singleModel;
    
    [detailNav popToRootViewControllerAnimated:YES];
}

重写DetailViewController的属性singleModel的setter方法就能实现和MasterTableViewController交互了

- (void)setSingleModel:(SingleModel *)singleModel{
    
    _singleModel = singleModel;
    
    self.nameView.text = singleModel.subjectName;
}

通常情况下,详情界面也会是一个tableView,在重写的singleModel中获取到上一界面传来的值,让当前控制器的tableView reloadData就可以了。

自定义实现分屏的功能

这个是今天要介绍的重点,因为有的时候系统的UISplitViewController并不能满足项目的需求,UISplitViewController只能做为程序窗口的根视图,当程序中需要使用UITabBarController或者UINavigationController来切换到分屏控制器的时候,并不能到达我们的目的。
可以看一下官网对UISplitViewController的介绍

主要的一个截图

Paste_Image.png

大体的意思就是分屏控制器不能进入导航的栈中(也就是不能通过导航控制器跳转),不推荐将分屏控制器做为某个控制器的子控制器,通常是做为程序窗口的根视图。

那如果需求是: 在主界面需要跳转到分屏控制器改怎么办呢?

这里有一种思路就是在主界面放一个按钮,在按钮的点击方法里面切换window的根视图。这个不是今天介绍的重点,就不在这里讨论了。

重点是---怎么自定义控制器具有分屏显示的功能(结合UITabBarController)

思路是新建三个控制器,分别是主控制器、左侧显示的列表控制器和右侧显示的详情控制器,将列表控制器和详情控制器的View添加到主控制器的View上,让主控制器成为列表控制器的代理,实现相应的协议方法从而和详情控制器就行交互。大体的思路和上面提到的使用系统的UISplitViewController差不多,主要的不同就是没有使用UISplitViewController,而是自定义的UIViewController,主要看一下自定义控制器中的代码。

添加两个导航控制器的属性

@property (nonatomic, strong) UINavigationController *masterNav;
@property (nonatomic, strong) UINavigationController *detailNav;

在viewDidLoad中初始化列表控制器和详情控制器,并添加到主控制界面上。

- (void)viewDidLoad {
    [super viewDidLoad];

   // self.navigationController.navigationBarHidden = YES;
    
    HZYMasterViewController *masterVC = [HZYMasterViewController new];
    self.masterNav = [[UINavigationController alloc] initWithRootViewController:masterVC];
    [self addChildViewController:self.masterNav];
    [self.view addSubview:self.masterNav.view];
    
    HZYDetailViewController *detailVC = [HZYDetailViewController new];
    self.detailNav = [[UINavigationController alloc] initWithRootViewController:detailVC];
    [self addChildViewController:self.detailNav];
    [self.view addSubview:self.detailNav.view];
    
    masterVC.delegate = self;
}

实现协议方法

- (void)masterViewController:(HZYMasterViewController *)masterVC didSelectedRowInSection:(NSInteger)section{
    
    HZYDetailViewController *detailVC = [self.detailNav.childViewControllers firstObject];
    
    [self.detailNav popToRootViewControllerAnimated:YES];
    
    //向detailVC传递点击的Section用来区分detailVC中tableViewCell的显示样式
    [detailVC putSection:section];
}

核心的方法,当控制器的View的子视图重新布局时调用,用来布局子视图。

- (void)viewWillLayoutSubviews{
        [_masterNav.view mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(@64);
            make.left.equalTo(@70);
            make.width.equalTo(kMasterWidth);
            make.bottom.equalTo(@0);
        }];
        
        [_detailNav.view mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.top.bottom.equalTo(_masterNav.view);
            make.right.equalTo(self.view.mas_right);
            make.left.equalTo(_masterNav.view.mas_right);
        }];
}

DetailViewController在putSection方法的实现中获得index,工具类通过index获得相应模型数据,刷新tableView

- (void)putSection:(NSInteger)section{
    
    _section = section;
    
    __weak typeof (self) weakSelf = self;
    
    //获取点击Section的模型数据,为了方便这里每个Section中的行都是一个模型数据,如果获取网络数据的话要更改工具类中的方法,视情况而定!
    [Tool getDataWithSection:section successBlock:^(NSMutableArray *modelArray) {
        
        weakSelf.modelArray = modelArray;
        
        [weakSelf.tableView reloadData];
    }];
}
Demo介绍

Demo分为两个target,一个是通过系统UISplitViewController结合storyboard实现的,一个是自定义控制器纯代码实现的。

Paste_Image.png
工程中添加两个target的遇到的坑

之前并没有在一个工程中添加过两个target,这次在两个target下coding遇到最多的问题就是

Paste_Image.png

一般这种问题就是编译的问题,找不到编译的源文件,解决方法就是在工程的target->Build Phases->Compile Sources,添加报错的.m文件,重新编译就OK了!
为什么会产生这种错误呢?主要就是在新建类的时候没有选中相应的target

Paste_Image.png

还有一种解决方案,选中报错的.m文件,展开实用工具(配合IB实用的那个栏目),点击第一个(file inspector),找到下面的Target Membership,勾选上相应的target。

Paste_Image.png
结语:

第一次在简书上面发表文章,希望我这几天的研究能够帮助到有这方面困惑的朋友,谢谢大家的支持。

最近很欣赏薛之谦说的一句话:在这个时代根本就没有怀才不遇, 关键是你真的必须具备才华 所以请你一定要强大自己!对于我们iOS开发来说,市场已经进入饱和期了(甚至有人调侃为iOS烂大街),很多人抱怨工作不好找,现在的市场需要的不再是只会写写界面,只会上网复制粘贴代码的开发者,所以你一定要强大自己,等你足够强大了,好的工作自然就来了!

最后献上我的Demo

上一篇下一篇

猜你喜欢

热点阅读