ios复用ViewController的,uibutton不响应事件的悲剧

背景

app中有很多介绍页面,结构都差不多。于是写了一个IntroductionViewController,用来复用。 复用的时候我直接在另一个viewController中将于是写了一个IntroductionViewController初始化,然后把于是写了一个IntroductionViewController.view添加到 viewController的视图中,结果发现然后把于是写了一个IntroductionViewController设置的按钮无法响应点击事件。

IntroductionViewController设置按钮和事件代码如下

js 复制代码
- (**void**)setIntroTipBtns:(NSArray<NSString *> *)tipBtns titles: (NSArray<NSString *> *)tipTitles contents:(NSArray<NSString *> *)tipContents {

    _introView.userInteractionEnabled = **YES**;

    **for**(**int** i=0; i<tipBtns.count; i++) {

        UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];

        [btn setTitle:tipBtns[i] forState:UIControlStateNormal];

        btn.backgroundColor = [UIColor systemCyanColor];
        [_introBtns addObject:btn];
        // 使用关联参数,实现uibutton多个入参

        objc_setAssociatedObject(btn,"title",tipTitles[i],OBJC_ASSOCIATION_RETAIN_NONATOMIC);//实际上就是KVC

        objc_setAssociatedObject(btn,"content",tipContents[i],OBJC_ASSOCIATION_RETAIN_NONATOMIC);

        //这里的事件一直没办法响应
        [btn addTarget:**self** action: **@selector**(showTip:) forControlEvents:UIControlEventTouchUpInside];

        [_introView addSubview:btn];
        //省略设置btn布局的代码
    }
}


- (**void**)showTip:(UIButton *)btn{
    NSString *title = objc_getAssociatedObject(btn,"title");//取参
    NSString *content = objc_getAssociatedObject(btn, @"content");
    [TipUtil showTip:content title:title inController:**self**];
}

**@end**

有问题的代码

原本只添加了view,无法响应点击事件。 后来直接跳转到IntroductionViewController,发现能响应点击事件。 也就是下面的代码有问题。

js 复制代码
- (**void**)viewDidLoad {

    [**super** viewDidLoad];

    [**self** buildViews];

}

- (**void**)buildViews {
    IntroductionViewController *vc = [[IntroductionViewController alloc] init];
    [self.view addSubview:vc.view]; 无法响应IntroductionViewController中的点击事件
}

查阅资料

通过创建一个新的 IntroductionViewController 实例,并将其视图添加到当前的 UIViewController 中,然后设置 introTitleLabel 的文本和执行 setIntroTipBtns 方法。

但是,这种方式不会触发 IntroductionViewController 中按钮的点击事件,因为你只是将其视图添加到了当前 UIViewController 中,并没有建立起相应的视图控制器层级关系。

修正代码如下

js 复制代码
- (void)buildViews {
    IntroductionViewController *vc = [[IntroductionViewController alloc] init];
    [self addChildViewController:vc]; // 嵌入子视图控制器
    vc.view.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height); // 设置子视图控制器的大小和位置
    [self.view addSubview:vc.view];
    [vc didMoveToParentViewController:self];
    
    vc.introTitleLabel.text = @"UIAlertController介绍";
    
    [vc setIntroTipBtns:@[@"tip1", @"tip2"] titles:@[@"tip1", @"tip2"] contents:@[@"tip1", @"tip2"]];
}
相关推荐
哈里谢顿3 小时前
1000台裸金属并发创建中的重难点问题分析
面试
哈里谢顿3 小时前
20260303面试总结(全栈)
面试
over6978 小时前
从 LLM 到全栈 Agent:MCP 协议 × RAG 技术如何重构 AI 的“做事能力”
面试·llm·mcp
SuperEugene9 小时前
Vue状态管理扫盲篇:如何设计一个合理的全局状态树 | 用户、权限、字典、布局配置
前端·vue.js·面试
Sailing11 小时前
🚀 别再乱写 16px 了!CSS 单位体系已经进入“计算时代”,真正的响应式布局
前端·css·面试
SuperEugene14 小时前
Vue状态管理扫盲篇:Vuex 到 Pinia | 为什么大家都在迁移?核心用法对比
前端·vue.js·面试
Hilaku14 小时前
我会如何考核一个在简历里大谈 AI 提效的高级前端?
前端·javascript·面试
前端Hardy15 小时前
别再用 $emit 满天飞了!Vue 3 组件通信的 4 种正确姿势,第 3 种 90% 的人不知道
前端·vue.js·面试
我叫黑大帅15 小时前
前端如何利用 GitHub Actions 自动构建并发布到 GitHub Pages?
前端·面试·github
我叫黑大帅15 小时前
前端总说的防抖与节流到底是什么?
前端·javascript·面试