我们曾经犯过的低级错误
最后来提一个我们之前花了半个月才找出问题在哪的bug。问题出在protocol不该这么设计。我们写了一个class,这个class有两个method:begin
与stop
,按下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的实现里头,也都不该随意的调用begin
与stop
,而我在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