A包含B,如何实现A和B互相调用更新数据。
添加通知了不是立即生效的,需要系统调度。而block是立即生效的。
不要用通知来回发送通知,通知有很多弊端,特别是多线程环境下,当一个控件刚添加了通知还没有正式生效,另一个线程发送了对应通知,就有概率闪退 。
所以尽量少用或不用通知,尽量用block来代替。
理论上因为A包含B,A可以知道B的数据,但是无法知道B的私有数据,当然若A只是创建B,但是没有持有B的指针也无法知道B的数据。通过两者来回发送通知当然能实现,只是通知是一对多,有概率闪退的问题,尽量别用。那么可以在创建B时给它传递一个bock,对A特别关注的数据B更新该数据时同步给A。
现在是一个A页面通过蘑菇街架构创建了一个B页面并把一个block给B页面,A页面没有持有B页面的指针,当B页面更新了数据后,通过block的回掉更新了A页面的数据和刷新了列表。
A页面创建B页面:
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
void(^selectEntityBlock)(FHFollowListUnitEntity *followListUnitEntity, BOOL isFollow) = ^(FHFollowListUnitEntity *followListUnitEntity, BOOL isFollow) {
@strongify(self);
[self freshTabWithFollowListUnitEntity:followListUnitEntity isFollow:isFollow];
};
[userInfo setSafeObject:entity forKey:@"followListUnitEntity"];
[userInfo setSafeObject:selectEntityBlock forKey:@"block"];
[userInfo setSafeObject:@(entity.dynamic_id) forKey:@"dynamic_id"];
[BITRouter openURL:@"gb://FHImageTextDetailViewController" withUserInfo:userInfo completion:nil];
A页面通过B页面的回调数据更新数据并刷新表格处理:
-(void)freshTabWithFollowListUnitEntity:(FHFollowListUnitEntity *)followListUnitEntity isFollow:(BOOL)isFollow
{
if(!followListUnitEntity || ![followListUnitEntity isKindOfClass:[FHFollowListUnitEntity class]] || isCommonUnitEmptyArray(self.models))
{
return;
}
if(!isFollow)
{
for(NSInteger i = 0; i < self.models.count; i++)
{
FHFollowListUnitEntity *entity = self.models[i];
if(entity && [entity isKindOfClass:[FHFollowListUnitEntity class]] && followListUnitEntity.dynamic_id > 0 && (entity.dynamic_id == followListUnitEntity.dynamic_id))
{
entity.is_collect = followListUnitEntity.is_collect;
entity.collect = followListUnitEntity.collect;
entity.is_praise = followListUnitEntity.is_praise;
entity.praise = followListUnitEntity.praise;
entity.is_evaluate = followListUnitEntity.is_evaluate;
entity.evaluate = followListUnitEntity.evaluate;
// [self.collectionView reloadData];
if(self.selectEntityBlock)
{
self.selectEntityBlock(followListUnitEntity, NO);
}
BOOL animationsEnabled = [UIView areAnimationsEnabled];
[UIView setAnimationsEnabled:NO];
NSIndexPath *indexPath=[NSIndexPath indexPathForRow:i inSection:0];
[self.collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil]];
[UIView setAnimationsEnabled:animationsEnabled];
return;
}
}
}
else
{
if(isCommonUnitEmptyString(followListUnitEntity.user_id))
{
return;
}
BOOL flag = NO;
NSMutableArray *indexPaths = [NSMutableArray array];
for(NSInteger i = 0; i < self.models.count; i++)
{
FHFollowListUnitEntity *entity = self.models[i];
if(entity && [entity isKindOfClass:[FHFollowListUnitEntity class]] && followListUnitEntity.dynamic_id > 0 && ([entity.user_id isEqualToString:followListUnitEntity.user_id]))
{
flag = YES;
entity.is_follow = followListUnitEntity.is_follow;
entity.follow_sum = followListUnitEntity.follow_sum;
[indexPaths addSafeObject:[NSIndexPath indexPathForRow:i inSection:0]];
// NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:i];
// //为了避免重新加载时出现不需要的动画(又名“闪烁”)
// BOOL animationsEnabled = [UIView areAnimationsEnabled];
// [UIView setAnimationsEnabled:NO];
// [self.collectionView reloadSections:indexSet];
// [UIView setAnimationsEnabled:animationsEnabled];
// return;
}
}
if(flag)
{
BOOL animationsEnabled = [UIView areAnimationsEnabled];
[UIView setAnimationsEnabled:NO];
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
[UIView setAnimationsEnabled:animationsEnabled];
// [self.collectionView reloadData];
if(self.selectEntityBlock)
{
self.selectEntityBlock(followListUnitEntity, YES);
}
}
}
}
B页面通过block回调A页面注册的block传递数据:
B页的子控件更新了数据,回调给B页面,然后回调A页面的block:
self.writeEvaluateMessageCollectPraiseView.selectBlock = ^{
@strongify(self);
CHECK_JUMP_LOGIN;
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
void(^freshBlock)(NSInteger dynamic_id, BOOL is_evaluate, NSInteger evaluate) = ^(NSInteger dynamic_id, BOOL is_evaluate, NSInteger evaluate){
@strongify(self);
if(dynamic_id > 0 && self.followListUnitEntity && (self.followListUnitEntity.dynamic_id == dynamic_id))
{
self.model.detailEntity.is_evaluate = is_evaluate;
self.model.detailEntity.evaluate = evaluate;
self.writeEvaluateMessageCollectPraiseView.model = self.model;
self.followListUnitEntity.is_evaluate = self.model.detailEntity.is_evaluate;
self.followListUnitEntity.evaluate = self.model.detailEntity.evaluate;
self.selectEntityBlock(self.followListUnitEntity, NO);
}
// [self loadListDataWithIsFresh:YES];
};
[userInfo setSafeObject:freshBlock forKey:@"block"];
[userInfo setSafeObject:@(self.model.dynamic_id) forKey:@"dynamic_id"];
[BITRouter openURL:@"gb://FHEvaluateListViewController" withUserInfo:userInfo completion:nil];
};
B页通过请求数据更新了数据,回调A页面的block:
-(void)loadListDataWithIsFresh:(BOOL)isFresh
{
@weakify(self);
self.isFresh = isFresh;
[NetWorkManager postWithPath:@"Dynamic/getDynamic" param:@{@"typeid":@(1),@"dynamic_id":@(self.model.dynamic_id)} dataClass:[FHDetailEntity class] isArray:NO].complete = ^(DYNetModel * _Nullable net, FHDetailEntity *data) {
@strongify(self);
if (net.errcode == DYNetModelStateSuccess) {
self.isFresh = NO;
if(data && [data isKindOfClass:[FHDetailEntity class]])
{
if(isFresh)
{
if(self.selectEntityBlock && self.selectEntityBlock && [self.followListUnitEntity isKindOfClass:[FHFollowListUnitEntity class]])
{
self.model.detailEntity.is_follow = data.is_follow;
self.model.detailEntity.is_collect = data.is_collect;
self.model.detailEntity.collect = data.collect;
self.model.detailEntity.is_praise = data.is_praise;
self.model.detailEntity.praise = data.praise;
self.model.detailEntity.is_evaluate = data.is_evaluate;
self.model.detailEntity.evaluate = data.evaluate;
[self freshBlock];
self.writeEvaluateMessageCollectPraiseView.model = self.model;
}
return;
}
self.model.detailEntity = data;
[self.collectionView reloadData];
self.selectBtn.isSelectContent = self.model.detailEntity.is_collect;
self.writeEvaluateMessageCollectPraiseView.model = self.model;
}
else
{
[self displayNoData];
}
}
else
{
[self loadFail];
}
};
}
理论上因为是B是被包含的关系,无法直接访问A的数据,而A的数据可能被C直接更新的,也可能是A自己更新的数据,情况比较复杂,若A的数据变更时,忘记传递给B,就会造成B拿到的不是A的最新数据。若B只在部分处理时需要使用A的数据。正确的做法是A创建B注册一个B的block,B需要时,调用block通知A更新最新的B关注数据给B或单例。然后再使用数据。block是实时传递,不像通知在发出通知到收到通知需要时间差。
A页面创建B页面注册一个B页面的block:
- (UIViewController<ZJScrollPageViewChildVcDelegate> *)childViewController:(UIViewController<ZJScrollPageViewChildVcDelegate> *)reuseViewController forIndex:(NSInteger)index {
@weakify(self);
if(self.currentCell && self.player){
self.currentCell.isPause = YES;
[self.player clearPlayer];
//返回关注的列表,暂停之前的播放
[self.player stopPlay];
}
self.currentIndex = index;
UIViewController<ZJScrollPageViewChildVcDelegate> *childVc = reuseViewController;
if (!childVc) {
if (index == 0) {
self.attentionBtn.isSelected = YES;
self.recommentBtn.isSelected = NO;
QRHomeController *vc = [[QRHomeController alloc] init];
self.attentionPage = vc;
vc.type = @"2";
// vc.isFirstLoad = YES;
vc.isFreshTable = YES;
// self.isLoadCurrencyStartup = NO;
[self synchroData];
self.attentionPage.synchroDataBlock = ^{
@strongify(self);
[self synchroData];
};
self.attentionPage.switchSelectPageBlock = ^(NSInteger selectPageIndex) {
@strongify(self);
[self synchroData];
[self.scrollPageView setSelectedIndex:1 animated:YES];
};
self.attentionPage.storeDataBlock = ^{
@strongify(self);
[self storeWithPage:self.attentionPage sno:0];
};
self.attentionPage.freshPageBlock = ^(NSInteger freshPageIndex) {
@strongify(self);
if(0 == freshPageIndex)
{
[self.attentionPage headerRefresh];
}
else
{
[self.recommentPage headerRefresh];
}
};
[self.attentionPage headerRefresh];
childVc = vc;
}
else
{
self.attentionBtn.isSelected = NO;
self.recommentBtn.isSelected = YES;
QRHomeController *vc = [[QRHomeController alloc] init];
self.recommentPage = vc;
self.recommentPage.synchroDataBlock = ^{
@strongify(self);
[self synchroData];
};
self.recommentPage.switchSelectPageBlock = ^(NSInteger selectPage) {
@strongify(self);
[self synchroData];
[self.scrollPageView setSelectedIndex:0 animated:YES];
};
self.recommentPage.storeDataBlock = ^{
@strongify(self);
[self storeWithPage:self.recommentPage sno:1];
};
self.recommentPage.freshPageBlock = ^(NSInteger freshPageIndex) {
@strongify(self);
if(0 == freshPageIndex)
{
[self.attentionPage headerRefresh];
}
else
{
[self.recommentPage headerRefresh];
}
};
vc.type = @"1";
vc.isFreshTable = YES;
vc.isNotFirstPlay = NO;
childVc = vc;
[self synchroData];
}
}
else
{
}
return childVc;
}
A页面同步数据给B页面的处理函数:
-(void)synchroData
{
[self updateHomeControllerWithPage:self.attentionPage sno:0];
[self updateHomeControllerWithPage:self.recommentPage sno:1];
}
-(void)updateHomeControllerWithPage:(QRHomeController *)page sno:(NSInteger)sno
{
if(page && [page isKindOfClass:[QRHomeController class]])
{
page.district_id = self.district_id;
page.longStr = self.longStr;
page.latiStr = self.latiStr;
page.isNotFirstPlay = self.isNotFirstPlay;
page.player = self.player;
page.currentIndex = self.currentIndex;
}
}
B页面需要时,调用block通知A页面更新最新的B关注数据给B或单例。然后再使用数据:
- (void)configurationCell:(QRHomeVideoCell *)cell indexPath:(NSIndexPath *)indexPath {
@weakify(self);
NSMutableArray *arr1 = self.models;
if (arr1.count>indexPath.row) {
cell.latiStr = self.latiStr;
cell.logStr = self.longStr;
LCStoreModel *model = [arr1 objectAtSafeIndex:indexPath.row];
[cell setModel:model];
[cell setZanBlock:^(NSInteger ifZan) {
@strongify(self);
model.user_love = (ifZan == 0) ? NO : YES;
}];
[cell setChangeNoBlock:^(NSInteger count) {
@strongify(self);
[self.currentCell.commentBtn.titleL setText:[NSString stringWithFormat:@"%ld", count]];
}];
[cell setHitAttentionBlock:^(LCStoreModel * _Nonnull model) {
@strongify(self);
if(model && [model isKindOfClass:[LCStoreModel class]] && !isCommonUnitEmptyArray(self.models) && model.suppliers_id > 0)
{
BOOL flag = NO;
NSMutableArray *arr =[NSMutableArray array];
for(NSInteger n = 0; n < self.models.count; n++)
{
LCStoreModel *entity = self.models[n];
if(entity && [entity isKindOfClass:[LCStoreModel class]] && (entity.suppliers_id > 0) && (model.suppliers_id == entity.suppliers_id) && (entity.goods_id != model.goods_id))
{
entity.user_focus = model.user_focus;
NSIndexPath *indexPath1 =[NSIndexPath indexPathForRow:n inSection:0];
[arr addObject:indexPath1];
flag = YES;
}
}
if(!isCommonUnitEmptyArray(arr))
{
//为了避免重新加载时出现不需要的动画(又名“闪烁”)
BOOL animationsEnabled = [UIView areAnimationsEnabled];
[UIView setAnimationsEnabled:NO];
[self.tableView reloadRowsAtIndexPaths:arr withRowAnimation:UITableViewRowAnimationNone];
[UIView setAnimationsEnabled:animationsEnabled];
}
}
if(self.type.intValue == 2){
if(self.synchroDataBlock)
{
self.synchroDataBlock();
}
self.isFreshTable = YES;
if(self.currentCell && self.player){
self.currentCell.isPause = YES;
[self.player clearPlayer];
//返回关注的列表,暂停之前的播放
[self.player stopPlay];
}
[self headerRefresh];
if(self.freshPageBlock)
{
self.freshPageBlock(1);
}
}
else
{
//刷新推荐列表
if(self.freshPageBlock)
{
self.freshPageBlock(0);
}
}
[self loginIMaccount];
}];
cell.changePlayBlock = ^(BOOL isPause) {
@strongify(self);
if(isPause)
{
[self.player pause];
}
else
{
[self repeatPlayWithIsPause:YES];
}
};
cell.endEditingBlock = ^{
@strongify(self);
[self.view endEditing:YES];
};
}
}