A包含B,用block实现A和B互相调用更新数据

简介: A包含B,用block实现A和B互相调用更新数据

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];
        };
    }
}
目录
相关文章
|
7月前
|
关系型数据库 MySQL 测试技术
当update修改数据与原数据相同时会再次执行吗
当update修改数据与原数据相同时会再次执行吗
52 1
|
7月前
合并对象的几种方法
合并对象的几种方法
67 5
|
消息中间件 缓存 数据库
A和B接口同时修改table字段,无法确认调用顺序
在互联网应用开发中,经常会碰到多个接口同时需要修改数据库表字段的情况。然而,由于无法确认接口调用的顺序,可能会导致数据冲突和一致性问题。本文将介绍一种解决这一问题的方法,通过合理的设计和技术手段,确保同时修改table字段的操作能够顺利进行,数据一致性得到保障。
160 0
A和B接口同时修改table字段,无法确认调用顺序
element close事件关闭表单,数据替换掉原始列表的数据bug解决
element close事件关闭表单,数据替换掉原始列表的数据bug解决
80 0
|
数据处理
两个接口数据合并
数据处理
240 0
mode:类型非常多 r:只读 从头部开始读 io.UnsupportedOperation: not writable w:写入 每次都是从头部开始写 原有的内容
mode:类型非常多 r:只读 从头部开始读 io.UnsupportedOperation: not writable w:写入 每次都是从头部开始写 原有的内容
|
NoSQL
随笔:sending data状态包含了使用内部临时表
这是一个我的随笔记录,这些过程非常有用,也非常明显。 欢迎关注我的《深入理解MySQL主从原理 32讲 》,如下: 语句如下: mysql> desc select id,count(*) from t110 group by id; +----+-------------+-------+...
905 0