UIViewController setView nil 自动从 superview 中移除

Posted

技术标签:

【中文标题】UIViewController setView nil 自动从 superview 中移除【英文标题】:UIViewController setView nil automatically removes from superview 【发布时间】:2015-05-24 22:45:48 【问题描述】:

在 UIViewController 上调用 setView 会自动从其父视图中删除当前视图。我找不到这个记录。在我的情况下,我想动态地将 UIViewController 对象交换为另一个对象,同时保持我的视图结构。我正计划将视图重新链接到新控制器,但可惜,这不起作用。

一般来说,自动从其父视图中删除视图似乎是一个明智的决定。文档应该反映这一点。

(对于任何认为以这种方式交换视图控制器对象是一个非常糟糕的主意的人,让我补充一下,我正在交换的控制器是现有控制器的子类。这种方法非常适合添加功能到一个视图是另一个视图的扩展。)

【问题讨论】:

【参考方案1】:

我就是这样解决的:

UIView *viewToKeep = self.viewController.view;
UIView *superview = viewToKeep.superview;
self.viewController.view = nil;  // removes the view from its superview

UIViewController *swapInViewController = [[UIViewController alloc] init];
swapInViewController.view = viewToKeep;
[superview addSubview: viewToKeep];
[viewToKeep applyConstraintsToFillSuperview];  // a helper to add auto layout constraints that make the view always fill it's parent
self.viewController = swapInViewController;

【讨论】:

【参考方案2】:

这样做肯定违背了 UIKit 的原则,因此很可能是个坏主意。

也就是说,这里有一些东西可以防止视图被自动删除,这意味着您不需要使用 addSubview 将其放回原来的位置。

仅对您在下面看到的、警告购买者等进行了测试。在 Swift 中:

class View: UIView 
    var preventRemovalFromSuperView = false
    override func removeFromSuperview() 
        if !preventRemovalFromSuperView 
            super.removeFromSuperview()
        
        preventRemovalFromSuperView = false
    


let vc1 = UIViewController()
let vc2 = UIViewController()
let sv = UIView()
let v = View()

// Existing hierarchy
sv.addSubview(v)
vc1.view = v

// Swap view controllers
v.preventRemovalFromSuperView = true // Prevent automatic removal
vc1.view = nil // Prevent UIViewControllerHierarchyInconsistency exception
vc2.view = v

// Check that view was not automatically removed
v.isDescendantOfView(sv) // true

【讨论】:

以上是关于UIViewController setView nil 自动从 superview 中移除的主要内容,如果未能解决你的问题,请参考以下文章

android AlertDialog setView 规则

QCombobox::setView 在 Windows 7 上崩溃应用程序

Activity启动----setView之后(View的绘制过程)

IllegalArgumentException:尝试 setView 时未找到片段 id 的视图

如何从 alertDialog.setView(R.layout.some_layout) 获取 EditText 的值

[Android FrameWork 6.0源码学习] View的重绘ViewRootImpl的setView方法