zoukankan      html  css  js  c++  java
  • SplitViewController的简单使用

    最终效果图:

    主控制器 BeyondViewController 

    继承自UISplitViewController<喎�"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="java;">// // BeyondViewController.h // 27_SplitViewCtroller // // Created by beyond on 14-8-31. // Copyright (c) 2014年 com.beyond. All rights reserved. // 主控制器,继承自UISplitViewController,左边master控制器是:FoodTypeListCtrl,右边的从控制器是FoodListCtrl #import @interface BeyondViewController : UISplitViewController @end 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    //
    //  BeyondViewController.m
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  主控制器,继承自UISplitViewController,左边master控制器是:FoodTypeListCtrl,右边的从控制器是FoodListCtrl
     
    #import "BeyondViewController.h"
    // 菜系 列表 控制器
    #import "FoodTypeListController.h"
    // 菜列表 控制器
    #import "FoodListController.h"
     
    // 菜系 列表 控制器 定义的协议,目的是:点击了菜系 列表 中的某一行时,告诉代理(即菜列表控制器) 要展示哪一种菜系下面的所有菜
    #import "FoodTypeListCtrlDelegate.h"
     
    @interface BeyondViewController () <foodtypelistctrldelegate>
     
     
    @end
     
    @implementation BeyondViewController
    // 重要~~~主控制器充当中间人,先得到FoodTypeListController,并且成为它的代理,得到菜系 列表 的某一行被点击时 对应的菜系对象
    //  然后再在FoodTypeListController的代理方法中,得到FoodListController,并将菜系 进一步传递给FoodListController
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 1.先得到Master控制器,即导航控制器,再从导航控制器中得到  FoodTypeListController,并且成为它的代理
        UINavigationController *foodTypeListNav = [self.childViewControllers firstObject];
        FoodTypeListController *foodTypeListCtrl = [foodTypeListNav.childViewControllers firstObject];
        foodTypeListCtrl.delegate = self;
         
         
         
        // 让foodListCtrl成为主控制器的代理,仅仅是监听Master控制器的出现和隐藏,并在foodListCtrl的左按钮上显示相应的提示文字(点击该文字可以展开被隐藏的Master控制器)
        UINavigationController *foodListNav = [self.childViewControllers lastObject];
        FoodListController<uisplitviewcontrollerdelegate> *foodListCtrl = [foodListNav.childViewControllers firstObject];
        self.delegate = foodListCtrl;
    }
    // 2. 然后再在FoodTypeListController的代理方法中,得到FoodListController,并将菜系 进一步传递给FoodListController
    - (void)foodTypeListController:(FoodTypeListController *)foodTypesVc didSelectedFoodType:(FoodType *)type
    {
        UINavigationController *foodListNavi = [self.childViewControllers lastObject];
        FoodListController *foodListCtrl = [foodListNavi.childViewControllers firstObject];
        foodListCtrl.foodType = type;
         
        [foodListNavi popToRootViewControllerAnimated:YES];
    }
     
    @end
    </uisplitviewcontrollerdelegate></foodtypelistctrldelegate>



     

    SplitViewCtrl的Master主控制器,

    继承自表格控制器 

    FoodTypeListController 【菜系列表】及其代理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //
    //  FoodTypeListController.h
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  SplitViewCtrl的Master主控制器,继承自表格控制器 【菜系列表】
     
    #import <uikit uikit.h="">
    @protocol FoodTypeListCtrlDelegate;
    @interface FoodTypeListController : UITableViewController
     
     
    // 成员:代理,当点击了某一行时,告诉代理 即点击了哪一种菜系,从而,右边的控制器展示相应的菜名列表
    @property (weak, nonatomic) id<foodtypelistctrldelegate> delegate;
     
     
    @end
    </foodtypelistctrldelegate></uikit>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    //
    //  FoodTypeListController.m
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //
     
    #import "FoodTypeListController.h"
     
    #import "FoodType.h"
     
    #import "FoodTypeListCtrlDelegate.h"
    @interface FoodTypeListController ()
    // 成员:数组,保存着从plist中加载的所有的从字典一一转成对象的FoodType
    @property (strong, nonatomic) NSArray *foodTypesArr;
    @end
     
    @implementation FoodTypeListController
    // getter访问时才加载,懒加载
    - (NSArray *)foodTypesArr
    {
        if (_foodTypesArr == nil) {
            // 经典,一句话将参数所对应的Plist文件中的字典数组,转成 该类的对象数组
            _foodTypesArr = [FoodType objArrFromPlistName:@"food_types.plist"];
        }
        return _foodTypesArr;
    }
     
    - (void)viewDidLoad
    {
        [super viewDidLoad];
         
        self.title = @"菜系";
        // 默认选择第0行,调用自己的方法,给其传递数据模型
        [self.tableView selectRowAtIndexPath:kIndexPathZero animated:YES scrollPosition:UITableViewScrollPositionTop];
        // 让第0行,显示选中状态,需配合覆盖掉系统默认的方法:viewWillAppear
        [self tableView:self.tableView didSelectRowAtIndexPath:kIndexPathZero];
    }
    // 取消系统默认的一些 事件,让第0行,显示选中状态
    - (void)viewWillAppear:(BOOL)animated
    {
     // do nothing...
    }
     
    #pragma mark - 数据源方法
    // 多少行
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return self.foodTypesArr.count;
    }
    // 每行显示的cell
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *ID = @"FoodType";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
        }
        // 模型数组中取出对应行的模型
        FoodType *type = self.foodTypesArr[indexPath.row];
        // 设置独一无二的内容
        cell.textLabel.text = type.name;
        // 返回cell
        return cell;
    }
    #pragma mark - 代理方法
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // 如果 代理(就是右边的从控制器)需要,才告知 当前选择了哪一个菜系
        if ([self.delegate respondsToSelector:@selector(foodTypeListController:didSelectedFoodType:)]) {
            FoodType *type = self.foodTypesArr[indexPath.row];
            [self.delegate foodTypeListController:self didSelectedFoodType:type];
        }
    }
     
     
    @end


    定义好的协议

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    //
    //  FoodTypeListCtrlDelegate.h
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //
     
    #import <foundation foundation.h="">
    @class FoodType;
    @protocol FoodTypeListCtrlDelegate <nsobject>
     
     
    @optional
    // 当点击了某一行时,告诉代理 即点击了哪一种菜系,从而,右边的控制器展示相应的菜名列表
    - (void)foodTypeListController:(FoodTypeListController *)ctrl didSelectedFoodType:(FoodType *)foodType;
     
     
    @end
    </nsobject></foundation>



    FoodListController

     

    SplitViewCtrl的从控制器,继承自表格控制器 

    展示的是某一菜系下所有的菜【菜的列表】

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //
    //  FoodListController.h
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  SplitViewCtrl的从控制器,继承自表格控制器  某一菜系下所有的【菜的列表】
    //  点击左边菜系列表控制器中的某一行时,本控制器将展示该菜系下的所有菜
     
    #import <uikit uikit.h="">
    @class FoodType;
    @interface FoodListController : UITableViewController
     
    // 数据源,根据传入的菜系,通过它的idstr,拼凑出新的plist名称,加载,转成Food模型对象数组
    @property (strong, nonatomic) FoodType *foodType;
    @end
    </uikit>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    //
    //  FoodListController.m
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //
     
    #import "FoodListController.h"
     
    #import "FoodDetailController.h"
    #import "Food.h"
    #import "FoodCell.h"
    #import "FoodType.h"
     
    // 成为UISplitViewControllerDelegate的代理,目的是监听其显示和隐藏方法,从而控制leftBarButtonItem的显示和隐藏
    @interface FoodListController ()<uisplitviewcontrollerdelegate>
    @property (strong, nonatomic) NSArray *foodsArr;
    @end
     
    @implementation FoodListController
     
    - (void)viewDidLoad
    {
        [super viewDidLoad];
         
    }
     
    // 重要~~~拦截setterFoodType方法,设置标题,从对应的Plist加载数据,并转成对象数组,刷新表格
    - (void)setFoodType:(FoodType *)foodType
    {
        _foodType = foodType;
         
        NSString *filename = [NSString stringWithFormat:@"type_%@_foods.plist", foodType.idstr];
        // 经典,一句话将参数所对应的Plist文件中的字典数组,转成 该类的对象数组
        self.foodsArr = [Food objArrFromPlistName:filename];
        self.title = foodType.name;
        if (self.isViewLoaded) {
            // 默认让tableView 滚动到第 0 行
            [self.tableView scrollToRowAtIndexPath:kIndexPathZero atScrollPosition:UITableViewScrollPositionTop animated:YES];
            // 刷新表格
            [self.tableView reloadData];
        }
    }
    #pragma mark - SplitViewCtrl的代理方法
    // 即将显示 Master主控制器
    - (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
    {
        self.navigationItem.leftBarButtonItem = nil;
    }
    // 即将隐藏 Master主控制器
    - (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc
    {
        barButtonItem.title = @"菜系";
        self.navigationItem.leftBarButtonItem = barButtonItem;
    }
     
     
    #pragma mark - 数据源方法
    // 多少行
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return self.foodsArr.count;
    }
    // 高度封装了FoodCell,控制器知道得很少
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        FoodCell *cell = [FoodCell cellWithTableView:tableView];
         
        cell.food = self.foodsArr[indexPath.row];
         
        return cell;
    }
    #pragma mark - 代理方法
    // cell 行高
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return 100;
    }
    // 选中某一行
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // 点击那行  对应的模型
        Food *food = self.foodsArr[indexPath.row];
        FoodDetailController *detailVc = [[FoodDetailController alloc] init];
        // 传递数据模型,内部会拦截
        detailVc.food = food;
        [self.navigationController pushViewController:detailVc animated:YES];
    }
     
    @end
    </uisplitviewcontrollerdelegate>



    WebView展示某一道 菜 的详情

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //
    //  FoodDetailController.h
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击菜列表控制中的某一行,来到这,显示该道菜的详细信息,直接用webView展示
     
    #import <uikit uikit.h="">
    @class Food;
    @interface FoodDetailController : UIViewController
     
    // 数据源,要显示哪道菜
    @property (strong, nonatomic) Food *food;
    @end
    </uikit>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    //
    //  FoodDetailController.m
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  点击一行,来到这,显示该道菜的详细信息,直接用webView展示
     
    #import "FoodDetailController.h"
    #import "Food.h"
     
    @interface FoodDetailController ()
    @property (weak, nonatomic) UIWebView *webView;
    @end
     
    @implementation FoodDetailController
    // 让weibView就是控制器的view
    - (void)loadView
    {
        UIWebView *webView = [[UIWebView alloc] init];
        // bounds就是屏幕的全部区域,applicationFrame就是app显示的区域,不包含状态栏
        webView.frame = [UIScreen mainScreen].applicationFrame;
        // 随着屏幕的旋转,宽高自动伸缩
        webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        self.view = webView;
        // 成员变量,记住,目的是 避免强转
        self.webView = webView;
    }
     
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 导航栏标题
        self.title = self.food.name;
        // 重点~~~拼接本地url,注意:如果在沙盒创建真实的文件夹,那么加载文件时,要加上文件夹名
        NSString *fileName = [NSString stringWithFormat:@"Html/food/%@.html", self.food.idstr];
        NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:fileName  withExtension:nil]];
        [self.webView loadRequest:request];
    }
    @end



    模型Model

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    //
    //  Food.h
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  模型:一种菜肴 Food 对应plist文件里面的一个字典
     
    #import <foundation foundation.h="">
     
    @interface Food : NSObject
     
    // 必须与plist文件中 字典的key 一模一样
    // id
    @property (copy, nonatomic) NSString *idstr;
    // 菜名
    @property (copy, nonatomic) NSString *name;
    // 小图标url
    @property (copy, nonatomic) NSString *imageUrl;
    // 网页的url
    @property (copy, nonatomic) NSString *url;
    // 本道菜预计耗时多长
    @property (copy, nonatomic) NSString *time;
    // 制作难度多大
    @property (copy, nonatomic) NSString *diff;
     
    @end
    </foundation>



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //
    //  FoodType.h
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  模型:一种菜系 FoodType 对应plist文件里面的一个字典
     
    #import <foundation foundation.h="">
     
    @interface FoodType : NSObject
    // ID
    @property (copy, nonatomic) NSString *idstr;
    // 菜系 名称:如粤菜 川菜 家常菜
    @property (copy, nonatomic) NSString *name;
     
    @end
    </foundation>



    封装的一个Cell View

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //
    //  FoodCell.h
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  自定义cell,一个cell 展示一个food模型里面的数据,传入tableView实例化cell的目的是封装得最彻底,让控制器作最少的事,知道得最少
     
    #import <uikit uikit.h="">
    @class Food;
    @interface FoodCell : UITableViewCell
     
    // 数据源模型,提供数据给内部的子控件们显示,内部会拦截setter方法
    @property (strong, nonatomic) Food *food;
    // 传入tableView实例化cell的目的是封装得最彻底,让控制器作最少的事,知道得最少
    + (instancetype)cellWithTableView:(UITableView *)tableView;
     
    @end
    </uikit>



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    //
    //  FoodCell.m
    //  27_SplitViewCtroller
    //
    //  Created by beyond on 14-8-31.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //
     
    #import "FoodCell.h"
     
    #import "Food.h"
    #import "UIImageView+WebCache.h"
     
    @interface FoodCell()
    @property (weak, nonatomic) IBOutlet UIImageView *iconView;
    @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    @property (weak, nonatomic) IBOutlet UILabel *descLabel;
    @end
     
     
     
    @implementation FoodCell
     
    // 传入tableView实例化cell的目的是封装得最彻底,让控制器作最少的事,知道得最少
    + (instancetype)cellWithTableView:(UITableView *)tableView
    {
        // cellID必须和xib中的一模一样
        static NSString *cellID = @"FoodCell";
        FoodCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
        if (cell == nil) {
            // 从xib创建
            cell = [[[NSBundle mainBundle] loadNibNamed:cellID owner:nil options:nil] lastObject];
            // 右边是箭头
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        }
        return cell;
    }
    // 数据源模型,提供数据给内部的子控件们显示,内部会拦截setter方法
    - (void)setFood:(Food *)food
    {
        _food = food;
         
        // 小图标
        [self.iconView setImageWithURL:[NSURL URLWithString:food.imageUrl] placeholderImage:[UIImage imageNamed:@"timeline_image_placeholder"]];
        // 菜名
        self.nameLabel.text = food.name;
        // 子标题
        self.descLabel.text = [NSString stringWithFormat:@"难度:%@  时长:%@", food.diff, food.time];
         
         
    }
    @end


    XIB

  • 相关阅读:
    非循环单链表节点的操作
    链表每一个节点的数据类型该如何表示
    链表的定义、确定一个链表需要几个参数?
    typedef的用法
    连续存储数组的算法(包含数组倒置、冒泡排序……)
    跨函数使用内存案例
    malloc()动态分配内存概述
    结构体
    指针和数组
    C#基础知识之dnSpy反编译
  • 原文地址:https://www.cnblogs.com/YH-Coding/p/5331788.html
Copyright © 2011-2022 走看看