如何在Interface Builder布局下优雅切换嵌入式视图?
解决Activity切换与嵌入式View复用的IB优化方案
嘿,我完全懂你现在的处境——为了实现Activity A和Activity B互相切换、各自加载对应嵌入式View的逻辑,你在Interface Builder里硬生生建了双倍的活动场景,比如Activity A分支下搞了两个并行副本,一个嵌View A,另一个嵌View B,这种做法不仅让IB的结构变得臃肿,后期改需求时也得重复改两套场景,太麻烦了!
其实咱完全可以通过复用同一个Activity场景来实现需求,不用搞重复的场景副本,下面是具体的优化步骤:
- 第一步:先清理冗余场景
删掉重复的Activity A/B场景,只保留一套基础的Activity A和Activity B场景。比如只留一个Activity A,默认先嵌入View A;Activity B默认嵌入View B。 - 第二步:给每个Activity配置两个嵌入Segue
给Activity A分别添加指向View A和View B的embed segue,然后给这两个Segue设置清晰的标识符,比如EmbedViewA和EmbedViewB;Activity B同理,配置指向View B和View A的Segue,标识符对应EmbedViewB和EmbedViewA。 - 第三步:在Activity代码里实现切换逻辑
首先在Activity类里加个变量记录当前显示的嵌入式控制器:
然后写个切换方法,比如:var currentEmbeddedVC: UIViewController?
最后在func switchToView(_ viewIdentifier: String) { // 先移除当前的嵌入式View currentEmbeddedVC?.willMove(toParent: nil) currentEmbeddedVC?.view.removeFromSuperview() currentEmbeddedVC?.removeFromParent() // 加载新的嵌入式View performSegue(withIdentifier: viewIdentifier, sender: nil) }prepare(for segue:)方法里更新当前控制器:override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "EmbedViewA" || segue.identifier == "EmbedViewB" { currentEmbeddedVC = segue.destination addChild(currentEmbeddedVC!) currentEmbeddedVC?.view.frame = yourContainerView.bounds // 替换成你的容器View的frame yourContainerView.addSubview(currentEmbeddedVC!.view) currentEmbeddedVC?.didMove(toParent: self) } } - 第四步:处理反向切换
比如在Activity A里显示View B时,要切回View A,只需要调用switchToView("EmbedViewA")就行;Activity B里的切换逻辑同理。
另外给你个小提示:
如果需要保留View的状态(比如用户在View B里输入的内容切换回来还能看到),可以把View控制器的实例提前缓存起来,不用每次通过Segue重新创建,这样体验会更好。
内容的提问来源于stack exchange,提问作者Optimalist
相关产品推荐
相关产品推荐

