关于嵌套视图消息传递,点击嵌套视图中chidCtrl 里面的Cell ,push出另一个ctrl, 好一点的方法是?

关于嵌套视图消息传递,点击嵌套视图中chidCtrl 里面的tableCell/collectionCell ,push出另一个ctrl.
需求场景挺多的,如图:
适用场景

因为是navigation push, 所以必须是tabBar 对应的ctrl ,去调用 self.navigationController push,
childCtrl 自然是不能 调用出 navigationController。
很简单的方法是, 在childCtrl 中增加 父Ctrl属性,好Low啊,不太MVC.

我是使用通知,代码如下:

父控制器: FrontPageViewController, tabBar 对应的一级

@implementation FrontPageViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 注册 通知
    [[NSNotificationCenter defaultCenter ] addObserver: self selector: @selector(gotoDetailTheGoodsFromFrontPage:) name:kNotiGotoTheCtrlFrontPage object: nil ];}
    
    
        // 添加 子 控制器
- (void)configuratePageViewControllers {
     DressShopViewController * versaceViewCtrl = [[DressShopViewController alloc ] init ];
    versaceViewCtrl.arguDictionary = @{chSortCode : @2,
                                       chSortType: @2,
                                       chCategoryId: @8 };
    
    DressShopViewController * sloganTeeViewCtrl = [[DressShopViewController alloc ] init ];
    sloganTeeViewCtrl.arguDictionary = @{chSortCode : @2,
                                       chSortType: @2,
                                       chCategoryId: @5 };
    
    
    /** 设置内容视图 */
    self.tagChildControllers = @[
                                 [[HandPickedViewController alloc] init ],
                                 versaceViewCtrl,
                                 sloganTeeViewCtrl
                                 ];

}

HandPickedViewController, 子控制器

pragma mark - UICollection View

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *gridcell = nil;
    
    switch (indexPath.section ) {
        case 0:
            {
                SubjectCollectionViewCell * subjectCell = [collectionView dequeueReusableCellWithReuseIdentifier:kSubjectCollectionCell forIndexPath: indexPath];
                subjectCell.gridItem = _gridItems[indexPath.item];
                subjectCell.backgroundColor = [UIColor whiteColor ];
                gridcell = subjectCell;
            }
            break;
        case 1:
            {
                ImageSubjectsCollectionViewCell * imageSubjectsCell = [collectionView dequeueReusableCellWithReuseIdentifier: kImageSubjectsCollectionCell forIndexPath:indexPath];
                gridcell = imageSubjectsCell;
            }
            break;
        case 2:
            {
                NearBottomCollectionViewCell * nearBottomCell = [collectionView dequeueReusableCellWithReuseIdentifier: kNearBottomCollectionCell forIndexPath:indexPath ];
                NSMutableArray <GoodsModel *> * mutableGoodsArray = [[NSMutableArray alloc ] initWithCapacity: 60 ];
                for (TheGoodsModel * tempGoodsModel in self.frontPageModel.cashbackGoods) {
                    GoodsModel * goodsModel = [[GoodsModel alloc ] init ];
                    goodsModel.imageUrlStr = tempGoodsModel.goodsImg;
                    goodsModel.priceNum = tempGoodsModel.minPrice;
                    goodsModel.goodsId = tempGoodsModel.idTheGoodsModel;
                    [mutableGoodsArray addObject: goodsModel ];
                }
                [nearBottomCell configurateBottomCollectionView: [mutableGoodsArray copy ] ];
                gridcell = nearBottomCell ;
            }
            break;
        default:
            if (indexPath.section>2) {
                BottomMoreCollectionViewCell * bottomMoreCell = [collectionView dequeueReusableCellWithReuseIdentifier: kBottomMoreCollectionCell forIndexPath: indexPath ];
                SubjectItem * subjectModel = self.frontPageModel.subjects[indexPath.section - 3 ];
                [bottomMoreCell configurateBottomMoreCell: subjectModel.goods ];
                gridcell = bottomMoreCell ;
            }// 子控制器 render cell
            break;
    }
    return gridcell;
  
   
     }
  BottomMoreCollectionViewCell, cell 调用 通知
#pragma mark - <UICollectionViewDelegate>
  • (void)collectionView:(UICollectionView )collectionView didSelectItemAtIndexPath:(NSIndexPath )indexPath{

    GoodsItem * goodsItem = _theGoodsModels[indexPath.item ];
    [[NSNotificationCenter defaultCenter ] postNotificationName: kNotiGotoTheCtrlFrontPage object: goodsItem.idGoodsItem ];

    }

使用通知, 通知满天飞,自然不好。
多重代理,一级一级码下去,
多重block, 也是行的,麻烦了点。
按照 Objc.io 消息传递机制 的说法,
父控制器: FrontPageViewController, tabBar 对应的一级,
与 BottomMoreCollectionViewCell, cell 调用 通知,
缺乏统一的上下文,使用delegate , 就要用 胶水代码建立联系。
问下更好的方法。
CTMediator, 我还不太会。

PS: tabbar 添加 navigationController(rootController: FrontPageViewController) 还有其他三个 。
FrontPageViewController 添加 UIPageViewController,
UIPageViewController 的 viewControllers 中有一个是HandPickedViewController。
HandPickedViewController 的 View 上面 addSubView, UICollectionView

阅读 4.2k
3 个回答

chidCtrl 是这么加的:[self addChildViewController:chidCtrl];

这样 chidCtrl 自己就可以做 push/pop 操作了。

或者在view中直接通过响应链拿到naviCtrl,再去操作转场。这样就不会delegate、block、noti漫天飞了。

大概代码:

- (UIResponder *)fetchNaviWithView:(UIView *)view {
    UIResponder *target = self.nextResponder;
    do {
        target = target.nextResponder;
    } while (![target isKindOfClass:UINavigationController.self] && target != nil);
    return target;
}

获取方式 UIWindow -> UITabBarController -> UINavigationController

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    AppDelegate *appDelagate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    // 获取window中的rootViewController, 就是UITabBarController
    UITabBarController *tabVC = (UITabBarController *)appDelagate.window.rootViewController;
    // 当前导航控制器
    UINavigationController *nav = tabVC.selectedViewController;
    // 要跳转的控制器
    UIViewController *yourController = [UIViewController new];
    
    [nav pushViewController:yourController animated:YES];
}
新手上路,请多包涵

parentViewController属性不就是你的容器视图么 0 0

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题