zoukankan      html  css  js  c++  java
  • IOS设计模式第五篇之装饰设计模式的代理设计模式

    版权声明:原创作品,谢绝转载!否则将追究法律责任。

    代理:

    另一个装饰设计模式,代理,是一个代表或者协调另一个对象的行为机制。例如当你用一个tableView,你必须实现他里面的一个tableView:numberOfRowsInSection:.方法。你不希望tableView知道他有多少行在每个section,因此这个计算每个区有几行的任务交给了UITableView的代理。他允许tableView类是独立的数据显示。

    当你创建一个UITableView的时候下面发生的:

    Image

    这个tableView的对象的工作是用来展示tableView的,然而最终他将需要一些信息他没有的。然后转向他的代理和要求额外的信息通过发送一条信息。在Objective-c实现代理的设计模式。一个类可以定义可选或者必须的方法通过协议。

    你可能想生成一个对象的子类更容易并覆盖必须的方法,但考虑到你只能基于单个类的子类。如果你想让一个物体是两个或者两个以上的其他的对象的代表。你不能通过子类来实现这一目标。

    注意:这是一个重要的设计模式。苹果在UIKit类里面用到了很多。 UITableView,UITextView, UITextField, UIWebView, UIAlert, UIActionSheet, UICollectionView, UIPickerView,UIGestureRecognizer, UIScrollView.这里面都有

    怎么使用代理的设计模式呢?

    在Viewcontroller的实现文件里面导入头文件:

    #import "LibraryAPI.h"#import "Album+TableRepresentation.h"

    现在添加一个延展来添加私有变量:

    @interface ViewController () {

        UITableView *dataTable;

    NSArray *allAlbums;

    NSDictionary *currentAlbumData;

        int currentAlbumIndex;

    }

    @end

    然后在延展的括号后面添加协议名字:

    @interface ViewController () <UITableViewDataSource, UITableViewDelegate>

    这使你的代理符合一个协议,使你能使用协议里面的方法。在这里你表示你的ViewController符合UITableViewDataSource 和UITableViewDelegate 协议。这种方法tableView可以绝对肯定的由其委托实现他协议必须实现的方法。

    接下来在viewDidLoad写以下代码:

    - (void)viewDidLoad

    {

        [super viewDidLoad];

    // 1

        self.view.backgroundColor = [UIColor colorWithRed:0.76f green:0.81f blue:0.87f alpha:1];

        currentAlbumIndex = 0;

    //2

        allAlbums = [[LibraryAPI sharedInstance] getAlbums];

    // 3

    // the uitableview that presents the album data

        dataTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 120, self.view.frame.size.width, self.view.frame.size.height-120) style:UITableViewStyleGrouped];

        dataTable.delegate = self;

        dataTable.dataSource = self;

        dataTable.backgroundView = nil;

        [self.view addSubview:dataTable];

    }

    对上面代码的解释:

    1:改变背景颜色

    2:得到专辑的列表用API而不是直接用PersistencyManager

    3:这里创建tableView。你声明这个ViewController是是tableView的代理或者数据源,因此tableView所有的信息都将要被这个Viewcontroller提供。

    现在添加下面方法到Viewcontroller的实现文件里面

    - (void)showDataForAlbumAtIndex:(int)albumIndex

    {

    // defensive code: make sure the requested index is lower than the amount of albums

        if (albumIndex < allAlbums.count)

        {

    // fetch the album

            Album *album = allAlbums[albumIndex];

    // save the albums data to present it later in the tableview

            currentAlbumData = [album tr_tableRepresentation];

        }

        else

        {

            currentAlbumData = nil;

        }

    // we have the data we need, let's refresh our tableview

        [dataTable reloadData];

    }

    showDataForAlbumAtIndex从专辑的数组得到想要的专辑数据。当你想显示最新的数据的时候你需要调用reloadData。他是tableView想他的代理询问例如有多少section应该出现在tableVeiw上,在每个section里面有很多行,并且每行应该怎么显示。

    在ViewDidLoad最后一行添加[self showDataForAlbumAtIndex:currentAlbumIndex]

    ;

    在应用加载当前专辑。并且currentAlbumIndex 先前设置0,他在集合里面展示第一个专辑。

    编译运行项目你得到一个崩溃下面有一个异常在debug窗口:

    Image(1)

    你把Viewcontroller设置为tableView的数据源或者代理。你必须实现他里面所有的必须实现的方法包括tableView:numberOfRowsInSection:但是你没有这样做。

    在实现文件里面添加以下代码:

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    {

        return [currentAlbumData[@"titles"] count];

    }

    - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    {

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

        if (!cell)

        {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"];

        }

        cell.textLabel.text = currentAlbumData[@"titles"][indexPath.row];

        cell.detailTextLabel.text = currentAlbumData[@"values"][indexPath.row];

        return cell;

    }

    tableView:numberOfRowsInSection: 返回在tableView里面显示多少行。和在数据结构里面标题的个数匹配、

    tableView:cellForRowAtIndexPath:创建返回一个cell带有标题和值;

    编译运行项目你的应用应该这样展示:

    Image(2)

    到目前为止看起来不错。但是如果你还记得完成应用后第一次启动的画面。在屏幕的顶部有一个水平照片的滑动视图。而不是专用的水平滑动的视图为什么不使他重用呢?

    为了让他重用,所有内容的显示等都交给了另一个对象:一个代理。这个水平滑动视图应该声明协议方法让他的代理来实现。类似于tableView的代理方法是怎么工作的。我们在下一个设计模式里面讨论如何实现。

    一个适配器设计模式允许你的类和不兼容的接口一起工作。它封装在一个对象,并公开了一个标准的接口和该对象进行交互。如果你熟悉适配器设计模式,那么你会发现苹果实现了它以稍微不同的方式--苹果使用协议来做这项工作。你可能熟悉的协议像UITableViewDelegate,UScrollViewDelegate,NSCoding,和NSCopying。例如用这个NSCopying协议任何类可以提供标准的copy方法。

  • 相关阅读:
    构建Linux根文件系统(未完待续)
    Bootloader的结构和启动过程
    linux文件属性介绍
    内核中设备树的操作函数
    Redis缓存之Set使用
    cookie的三种操作方法
    毕业一年(这个总结来的比较晚)
    MongoDb 聚合报错
    Asp.Net alert 方法
    JQuery拖拽排序
  • 原文地址:https://www.cnblogs.com/qiqibo/p/3459380.html
Copyright © 2011-2022 走看看