我們曾經犯過的低級錯誤

最後來提一個我們之前花了半個月才找出問題在哪的 bug。問題出在 protocol 不該這麼設計。我們寫了一個 class,這個 class 有兩個 method: beginstop,按下 begin 的時候要開始做一件事情,之後想要停止,就呼叫 stop,要開始或要結束的時候,都會通知 delegate。程式大概是這樣:

@class MyClass;
@protocol MyClassDelegate <NSObject>
- (void)myClassWillBegin:(MyClass *)myClasss;
- (void)myClassDidBegin:(MyClass *)myClasss;
- (void)myClassWillStop:(MyClass *)myClasss;
- (void)myClassDidStop:(MyClass *)myClasss;
@end

@interface MyClass : NSObject
{
    id <MyClassDelegate> delegate;
}
- (void)begin;
- (void)stop;
@property (assign, nonatomic) id <MyClassDelegate> delegate;
@end

@implementation MyClass

- (void)begin
{
    [delegate myClassWillBegin:self];
    // Do something
    [delegate myClassDidBegin:self];
}
- (void)stop
{
    [delegate myClassWillStop:self];
    // Do something
    [delegate myClassDidStop:self];
}
@synthesize delegate;
@end

這個 protocol 有什麼問題呢?前面提到,在 UITableView 的 data source 的 method 裡頭不該呼叫 reloadData 一樣,這邊的幾個 delegate method 的實作裡頭,也都不該隨意的呼叫 beginstop ,而我在 myClassWillBegin:裡頭想要做一些檢查,如果在某些條件下,這件事情不該跑起來,而應該停止,所以我在myClassWillBegin: 裡頭呼叫了stop。但這麼做,並不會讓這件事情結束,因為 begin 這個 method 在對delegate 呼叫完 myClassWillBegin:之後,程式還是會繼續往下走,所以還是把 begin 整個做完了。

這個 protocol 應該這麼設計:

@class MyClass;
@protocol MyClassDelegate <NSObject>
- (BOOL)myClassShouldBegin:(MyClass *)myClasss;
- (void)myClassDidBegin:(MyClass *)myClasss;
- (BOOL)myClassShouldStop:(MyClass *)myClasss;
- (void)myClassDidStop:(MyClass *)myClasss;
@end

@interface MyClass : NSObject
{
    id <MyClassDelegate> delegate;
}
- (void)begin;
- (void)stop;
@property (assign, nonatomic) id <MyClassDelegate> delegate;
@end
@implementation MyClass

- (void)begin
{
    if (![delegate myClassShouldBegin:self]) {
        return;
    }
    // Do something
    [delegate myClassDidBegin:self];
}
- (void)stop
{
    if (![delegate myClassShouldStop:self]) {
        return;
    }
    // Do something
    [delegate myClassDidStop:self];
}
@synthesize delegate;
@end

results matching ""

    No results matching ""