一个delegate没有更新引起的bug
1、场景如下:
(1)有个mainFrameController,在这个mainFrameController点击对应彩虹tab切换分别加载另外3个子controller,分别为A-controller,B-controller,C-controller
这3个controller实例通过GroupController类进行区别并统一初始化的;
(2)A、B、C三个controller分别要实现语音播报功能,所以都要实现Sound类中的SoundDelegate中的方法;
(3)A、B、C三个界面第一次加载时,在进行初始化时,都会将自己的类实例执行赋值给Sound类中的speechDelegate指针;
Sound类中:
@property (nonatomic, weak) id<SoundDelegate> speechDelegate;
GroupController类中定义的语音实例变量:
@property (nonatomic, retain) Sound *soundButton;
GroupController类中loadView方法:
- (void)loadView
{
.....
if (mContentType_e == A)
{
.....
A *a = [[A alloc]init];
self.soundButton.speechDelegate = a;
.....
}
if (mContentType_e == B)
{
.....
B *b = [[B alloc]init];
self.soundButton.speechDelegate = b;
.....
}
if (mContentType_e == C)
{
.....
C *c = [[C alloc]init];
self.soundButton.speechDelegate = c;
.....
}
.....
}
(4)为了省去每次切换页面都要初始化,所以在mainFrameController中进行第一次初始化时,就进行持久化保存到一个字典中;
代码大致如下:
-(void) load_A
{
.....
GroupController * model = [self.modelDict objectForKey:@"A类"];
if (model == nil)
{
model = [[GroupController alloc]initWithType:A_CONTENT //在这里进行了model初始化,执行loadView
ViewRect:[GroupController getMainViewContentFrame]];
[self.modelDict setObject:model forKey:@"A类"];
}
.....
}
-(void)load_B
{
.....
GroupController * model = [self.modelDict objectForKey:@"B类"];
if (model == nil)
{
model = [[GroupController alloc]initWithType:B_CONTENT
ViewRect:[GroupController getMainViewContentFrame]];
[self.modelDict setObject:model forKey:@"B类"];
}
.....
}
-(void) load_C
{
.....
GroupController * model = [self.modelDict objectForKey:@"C类"];
if (model == nil)
{
model = [[GroupController alloc]initWithType:C_CONTENT
ViewRect:[GroupController getMainViewContentFrame]];
[self.modelDict setObject:model forKey:@"C类"];
}
.....
}
在这种场景下bug就出现了,先进入A界面进行语音播报,再第一次切换至B界面进行语音播报,再切换回A进行语音播报,发现竟还在播报B的内容;
2、原因分析:
语音播报speechDelegate只在界面第一次初始化时进行了赋值,A的第一次进入就执行了self.soundButton.speechDelegate = a;
再次B时执行了self.soundButton.speechDelegate = b;再切换回A时,由于已经进行了持久化处理,就不在进行初始化处理,就不在执行
self.soundButton.speechDelegate = a;导致speechDelegate始终是B的值;
3、参考解决方案
此问题主要是类实例的持久化保存导致speechDelegate没有更新导致,所以需要及时更新speechDelegate,让它可以调用对应的代理方法。
解决此bug采取在每次切换到某个界面时,对应的controller类中的viewWillAppear中更新speechDelegate;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
......
self.soundButton.speechDelegate = self;
......
}