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

前言

最近公司需要开发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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一种新的协议。它实...
    香橙柚子阅读 22,958评论 8 183
  • 最近在做团队项目,在开发中不可避免的会用到一些第三方类库,它们提供了很多实用的功能,使我们的开发变得更有效率;同时...
    豆汁儿还是豆花儿阅读 3,864评论 0 9
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 本来你们可以在一起做更多的事,而不用浪费彼此的时间和精力在要与不要之间徘徊,本来你们可以去更多的地方,一起进步。本...
    昨夜西风凋碧树阅读 254评论 0 1
  • 在现实世界中,参与者可以从合作中获益更多,但最终重新开始相互竞争的情况却更多。这种现象一般是由这样几个原...
    小小杠杆阅读 513评论 0 2