从情节提要重新加载视图时,以编程方式添加的 iOS 子视图会丢失

Posted

技术标签:

【中文标题】从情节提要重新加载视图时,以编程方式添加的 iOS 子视图会丢失【英文标题】:iOS Subviews added programmatically are lost when view is reloaded from the storyboard 【发布时间】:2012-06-12 20:21:14 【问题描述】:

我有一个带有两个视图控制器的应用程序。 ViewControllerA 是一个分配了点击手势的空白视图,它允许用户在视图上进行选项卡并在点击点创建一个 UITextView。用户可以根据需要创建任意数量的 UITextView,然后以编程方式将它们添加到视图 (ViewControllerA) 作为子视图。

还有一个按钮允许用户更改文本字体和样式。这会触发第二个视图控制器 ViewControllerB 的 Segue,然后允许用户设置字体、文本大小、颜色等。一旦完成,用户单击 ViewControllerB 上的 DONE 按钮,另一个 Segue 切换回初始视图 (ViewControllerA)。

这一切都很好。除非用户从 ViewControllerB 切换回初始视图 (ViewControllerA),否则视图会从情节提要中重新加载,并且我以编程方式添加的子视图消失了。

在视图(ViewControllerA)中,ViewDidLoad 和 ViewWillAppear 触发得很好,所以问题似乎是在第一个 Segue 触发时释放了初始视图,然后在转换回来时从情节提要重新创建,但子视图当然不包括在内它们不在情节提要中,因为我以编程方式添加它们。

关于如何解决这个问题的最佳实践的任何建议,以便在主视图 (ViewControllerA) 重新加载时也重新创​​建子视图?

非常感谢您的任何建议!

【问题讨论】:

【参考方案1】:

从问题看来,您对文本样式视图有一个转场,然后是另一个转场“回到原始” - 它不像那样工作,转场总是会创建目标 VC 的新实例。您应该对文本样式视图进行模态搜索,然后关闭模态视图控制器 - 这将返回到您的原始实例。

【讨论】:

【参考方案2】:

为了记录,我解决了这个问题,以防其他人需要解决方案。

我在 ViewControllerA 中创建了一个子视图,它是主视图的大小,不包括工具栏。我称之为canvasView。然后我将我所有的 ImageViews 和 TextViews 添加到这个画布视图中。

然后在 ViewControllerA viewWillDisappear 中,我将 canvasView 及其所有子视图存档到这样的文件中。

    NSString *archivePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"Canvas.archive"];
BOOL result = [NSKeyedArchiver archiveRootObject:_canvasView
                                     toFile:archivePath];
if (!result) 
    NSLog(@"Archive failed to archivePath %@",archivePath);

然后在 ViewControllerA viewWillAppear 中检查是否存在现有存档,如果存在则重新加载它以正确顺序加载子视图。否则我会像这样创建一个空的 canvasView。

    // If the collageView already exists then restore it from the achive, otherwise initialize a new one.

NSString *archivePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"Canvas.archive"];

_canvasView = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];

if (_canvasView) 
    // Restore existing canvasView
    [_backgroundView addSubview:_canvasView];
 else 
    // Initialize a new canvasView
    _canvasView = [[UIScrollView alloc] initWithFrame:CGRectMake(_backgroundView.frame.origin.x, 
                                                           _backgroundView.frame.origin.y, 
                                                           _backgroundView.frame.size.width, 
                                                           _backgroundView.frame.size.height)];
    [_backgroundView addSubview:_canvasView];

【讨论】:

其实我认为你把它复杂化了。从这个问题听起来你对文本样式视图有一个转场,然后是另一个转场“回到原来的” - 它不像那样工作,转场总是会创建目标 VC 的新实例。您应该对文本样式视图进行模态搜索,然后关闭模态视图控制器 - 这将返回到您的原始实例。 非常感谢 jrturton,这是一个更好的解决方案,无需完全归档。 在这种情况下,我已将其添加为答案。

以上是关于从情节提要重新加载视图时,以编程方式添加的 iOS 子视图会丢失的主要内容,如果未能解决你的问题,请参考以下文章

iOS:如何以编程方式将视图添加到情节提要视图

如何从情节提要以编程方式加载 UIViewController?

如何在 ios swift 中以编程方式将情节提要视图控制器加载到标签栏控制器中?

如何以编程方式从情节提要中填充静态 UITableView?

当我以编程方式从情节提要加载窗口时,为啥在 NSView 中未调用 drawRect?

以编程方式将视图添加到情节提要