Data Source 与Delegate 的差别?

我们现在可以来看看UITableViewUITableViewController是怎么运作的。UITableViewControllerloadView中建立了一个UITableView的instance,指定成是自己的view,同时将这个view的delegate与data source设定成自己。一个class可以根据需要,将delegate拆成好几个,以UITableView来说,跟表格中有什么资料有关的,就放在data source中,其余的method放在delegate中。

我们在Mac OS X会用到的最庞大的UI元件,莫过于WebView,虽然在iOS上UIWebView被阉割到只剩下四个delegate method,但是Mac OS X上足足有五大类delegate method,网页页框的载入进度、个别图片档案的载入进度、下载档案的UI呈现、该不该开新视窗或是新分页、没有安装Java或是Flash要怎么呈现、用JavaScript跳出alert该怎么呈现…都是一堆delegate method。

假如先不管UITableView怎么重复使用UITableViewCell的机制(这个机制还顶复杂),我们要更新UITableView的资料时,先指定data source物件后,要呼叫一次reloadDatareloadData可能是这样写的:

- (void)reloadData
{
    NSInteger sections = 1;
    if ([dataSource respondsToSelector:
        @selector(numberOfSectionsInTableView:)]) {
        sections = [dataSource numberOfSectionsInTableView:self];
    }
    for (NSInteger section = 0; section < sections; section++) {
        NSInteger rows = [dataSource tableView:self
                         numberOfRowsInSection:section];
        for (NSInteger row = 0; row < rows; row++) {
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row
                                                        inSection:section];
            UITableViewCell *cell = [dataSource tableView:self
                                    cellForRowAtIndexPath:indexPath];
            // Do something with the cell...
        }
    }
}

我们注意到几件事情:首先,因为numberOfSectionsInTableView:被定义成是optional的delegate method,delegate不见得要实现,所以我们会用respondsToSelector:检查是否有实现。我们可以在protocol的宣告中,指定某个delegate method是required或是optional,如果不特别指定的话,预设都是required。我们简单看一下UITableViewDataSource就知道如何定义required与optional的delegate method。

@protocol UITableViewDataSource<NSObject>
@required
- (NSInteger)tableView:(UITableView *)tableView
  numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView
  cellForRowAtIndexPath:(NSIndexPath *)indexPath;
@optional
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
// ....
@end

另外,就是定义在data source的method,是在reloadData中被呼叫,因此我们可以知道UITableView的data source与delegate的最大差别:我们绝对不可以在data source定义的method中呼叫reloadData,不然就会进入死循环!

results matching ""

    No results matching ""