快照如何干扰父子关系?

15

摘要

  1. childVC添加到parentVC
  2. 快照childVC.view
  3. 出现问题。

为什么?

情况

我刚遇到一个奇怪的行为,想知道它是正常的还是一个bug。

我有一个视图控制器childVC,它是parentVC的子代。创建父/子关系时,我的代码如下:

    [parentVC addChildViewController:childVC] ;
    [parentVC.view addSubview:childVC.view] ;
    [childVC didMoveToParentViewController: parentVC] ;

在稍后的几行中,我想创建childVC.view的快照。我的代码是:

UIView * view = childVC.view ;

UIGraphicsBeginImageContextWithOptions(view.contentSize, NO, 0);
{
    [...]

    [view drawViewHierarchyInRect:view.bounds
               afterScreenUpdates:YES];

    image = UIGraphicsGetImageFromCurrentImageContext();

    [...]
}
UIGraphicsEndImageContext();

Bug

出现以下错误:

* Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller: should have parent view controller:(null) but actual parent is:' * First throw call stack: ( 0 CoreFoundation 0x0260b466 __exceptionPreprocess + 182 1 libobjc.A.dylib
0x02290a97 objc_exception_throw + 44 2 CoreFoundation
0x0260b38d +[NSException raise:format:] + 141 3 UIKit
0x01136710 -[UIView(Hierarchy) _associatedViewControllerForwardsAppearanceCallbacks:performHierarchyCheck:isRoot:] + 352 4 UIKit 0x01136b13 -[UIView(Hierarchy) _willMoveToWindow:withAncestorView:] + 285 5 UIKit 0x0114330a -[UIView(Internal) _addSubview:positioned:relativeTo:] + 511 6 UIKit 0x01136252 -[UIView(Hierarchy) addSubview:] + 56 7 UIKit
0x0114ab0e +[_UIReplicantView _pendingSnapshotOfTarget:snapshotBlock:] + 584 8 UIKit 0x011312fe -[UIView drawViewHierarchyInRect:afterScreenUpdates:] + 287

问题

为什么会这样?我该如何解决这个问题?

更多细节

实际上,childVC.view是一个UIScrollView,截图的代码如下:

UIScrollView * scrollView = (UIScrollView *)childVC.view;

UIGraphicsBeginImageContextWithOptions(scrollView.contentSize, NO, 0);
{
    CGPoint savedContentOffset = scrollView.contentOffset;
    CGRect savedFrame = scrollView.frame;

    scrollView.contentOffset = CGPointZero;
    scrollView.frame = CGRectMake(0,
                            0,
                            scrollView.contentSize.width,
                            scrollView.contentSize.height);

    [scrollView drawViewHierarchyInRect:scrollView.bounds
               afterScreenUpdates:YES];

    image = UIGraphicsGetImageFromCurrentImageContext();

    scrollView.contentOffset = savedContentOffset;
    scrollView.frame = savedFrame;
}
UIGraphicsEndImageContext();

也许那会有很大的区别。


2
这是3年前的事情了,但我今天在Swift 4中遇到了同样的问题。你解决了这个问题吗? - agirault
2
不好意思,祝你好运。 - Colas
这是最奇怪的 bug!它对我来说只能正常工作一次,而在后续的快照中会崩溃。 - batman
我遇到了完全相同的崩溃,但情况不同。这种情况发生在你快照一个没有窗口的视图(例如 view.window == nil)。 - rabbitinspace
1
我也遇到过这个问题。我的解决方案是将子视图从父视图中移除,进行快照,然后再添加回父视图。我想子视图控制器就像我的孩子一样——请不要拍照! - Brian M
我曾经遇到过同样的问题并解决了它。为了调试,可以打印scrollView.window,如果它是nil,那么你的某个视图没有被添加到它应该在的父视图中。在我的情况下,是UINavigationController的topViewController。 - Mathieu Hausherr
3个回答

3
今天我遇到了同样的问题,实现自定义转换使用UIViewControllerAnimatedTransitioning。问题是当我尝试对子视图控制器进行快照时,其父级还未成为视图层次结构的一部分。
解决方法是确保父视图已添加到视图层次结构中,然后再尝试对子视图进行快照。在我的情况下,我只需要将“to”视图控制器先添加到transitionContext.containerView中即可。
从您的代码片段中,我无法确定您何时尝试拍摄快照。但如果是在viewDidAppear()之前,它可能不起作用。

你刚刚救了我的命!我在自定义转场中遇到了问题,但是我没有收到任何错误消息或崩溃,只有一个混乱的布局。首先将其添加到容器中解决了这个问题。非常感谢! - Micky

0

在使用view.snapshotView(afterScreenUpdates: true)捕获子视图控制器的视图并将其从父视图中移除之前,我遇到了这个崩溃。

对我来说,将afterScreenUpdates设置为false解决了这个问题。


-2

也许你的父视图控制器已被释放,因此在异常消息中出现了(null)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接