Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does snapshotting interfere with parent/child relationships?

Summary

  1. Add a childVC to a parentVC
  2. Snapshot childVC.view
  3. It bugs.

Why?

Situation

I've just encountered a strange behavior and I would like to know if it is normal or if it is a bug.

I have a view controller childVC which is a child of parentVC. When creating the parent/child relationship, my code is

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

Few lines further, I want to create a snapshot of childVC.view. My code is

UIView * view = childVC.view ;

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

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

    image = UIGraphicsGetImageFromCurrentImageContext();

    [...]
}
UIGraphicsEndImageContext();

Bug

Then I have the error:

* 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

Question

Why is it so? Can I solve this issue?

More details

Actually, childVC.view is a UIScrollView and the code for snapshotting is

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();

Maybe that makes a big difference.

like image 612
Colas Avatar asked May 29 '15 13:05

Colas


1 Answers

I ran into this same issue today, when implementing a custom transition using UIViewControllerAnimatedTransitioning. The problem was that when I tried to snapshot the child view controller, its parent was not part of a view hierarchy yet.

The solution is to make sure that the parent's view has been added to a view hierarchy before you try to snapshot the child. In my case, I just needed to add the "to" view controller to the transitionContext.containerView first.

From your code snippet, I can't tell when you are trying to take the snapshot. But if it is before viewDidAppear(), it probably won't work.

like image 128
Nate Petersen Avatar answered Nov 16 '22 23:11

Nate Petersen