注意事项

在上面的范例中,我们看到了设计delegate 与protocol 应该注意的地方:

Delegate 不应该指定Class

我们将delegate物件定义成id <MyButtonDelegate> delegate,意思就是不需要管这个实例属于哪个class,只要是个Objective-C实例即可,但是这个实例必须遵守MyButtonDelegateprotocol。

我们其实可以将delegate实例是那个class写死,例如把MyButton的delegate的class指定成MyController,但这样做非常不好,如此一来,就只有MyController可以使用MyButton,其他controller都无法使用,就大大减少了重复使用MyButton的弹性。

Delegate 这种设计方式,也方便我们在同时开发Mac OS X 与iOS跨平台项目时共用代码,我们在撰写某个model 实例的时候,只使用Foundation 或是其他两个平台都有的framework,至于与平台相依的部份,就放进delegate 中,然后在Mac OS X 与iOS 上各自作现delegate 方法。

总之,在实现delegate的时候,delegate属于哪个class并不重要,重要的是delegate有没有实现我们想要调用的method。

Delegate 属性应该要用Weak,而非Strong

在使用property 语法的时候,如果这个property 是Objective-C实例,我们照理说应该要设定成strong 或retain,但是遇到的是delegate,我们应该设成weak 或assign。

原因是:需要设计delegate的这个实例,往往是其delegate实例的成员变量。在我们的例子中,MyButton的instance是myButton,是MyController的成员变量,自己可能已经被MyControllerretain了一份。如果MyButton又retain了一次MyController,就会出现循环retain的问题—我已经被别人retain,我又把别人retain一次。

如此,会造成我们会无法释放MyController:在该释放MyController的时候,MyController还是被自己的成员变量retain,MyController得要走到dealloc才会释放myButton,但是自己却因为被myButton给retain起来,而始终走不到dealloc

Delegate Method 的命名方式

Delegate method的命名有个鲜明的特色,就是这个method至少会传入一个参数,就是把到底是谁呼叫了这个delegate method传递进来。同时,这个method也往往以传入的class名称开头,让我们可以辨识这是属于哪个class的delegate method。以UITableViewDelegate为例,假如我们在iOS的表格中,选择了某一列,就会调用

- (void)tableView:(UITableView *)tableView
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath

Method 的名称就以「tableView」开头,让我们知道这是属于Table View 的delegate method,然后第一个参数把这个Table View 的instance传入,接下来才传入到底是哪一列被选起来的信息。

至少把是谁调用了这个delegate method传入的理由很简单。以我们的MyController为例,这个controller可能有好几个MyButton,而这些MyButton全都把delegate指到同一个controller上,那么,controller就需要知道到底是被哪个button呼叫。判断方式只要简单比对指标就好了:

- (void)myButtonDidBecomeQuadrupleClicked:(MyButton *)button
{
    if (button == myButton1) {
    }
    else if (button == myButton2) {
    }
}

results matching ""

    No results matching ""