Last active
August 29, 2015 13:57
-
-
Save steipete/9723421 to your computer and use it in GitHub Desktop.
[PSPDFHUDView updatePageLabelFrameAnimated:] resizes a label that is inside PSPDFHUDView by calling sizeToFit. This triggers layoutSubviews on PSPDFHUDView. That's something I would like to prevent. What could I do here? Followup: https://gist.github.com/steipete/9725247
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(lldb) bt | |
* thread #1: tid = 0x6e9f, 0x0036d774 PSPDFCatalog`-[PSPDFDebugLayer setNeedsLayout](self=0x1656a190, _cmd=0x302e001d) + 44 at PSPDFDebugHelper.m:456, queue = 'com.apple.main-thread', stop reason = breakpoint 14.1 | |
frame #0: 0x0036d774 PSPDFCatalog`-[PSPDFDebugLayer setNeedsLayout](self=0x1656a190, _cmd=0x302e001d) + 44 at PSPDFDebugHelper.m:456 | |
frame #1: 0x2f9763e8 QuartzCore`CA::Layer::property_did_change(CA::Transaction*, unsigned int) + 1188 | |
frame #2: 0x2f975f1c QuartzCore`CA::Layer::end_change(CA::Transaction*, unsigned int, objc_object*) + 64 | |
frame #3: 0x2f976a54 QuartzCore`CA::Layer::set_bounds(CA::Rect const&, bool) + 540 | |
frame #4: 0x2f976776 QuartzCore`-[CALayer setBounds:] + 110 | |
frame #5: 0x2f97789c QuartzCore`-[CALayer setFrame:] + 636 | |
frame #6: 0x2fcf6336 UIKit`-[UIView(Geometry) setFrame:] + 254 | |
frame #7: 0x2fd075f4 UIKit`-[UIView(Geometry) sizeToFit] + 304 | |
* frame #8: 0x00461980 PSPDFCatalog`-[PSPDFHUDView updatePageLabelFrameAnimated:](self=0x165afce0, _cmd=0x008297de, animated='\x01') + 684 at PSPDFHUDView.m:245 | |
frame #9: 0x004615ea PSPDFCatalog`-[PSPDFHUDView updatePageLabelAnimated:](self=0x165afce0, _cmd=0x008298b0, animated='\x01') + 1354 at PSPDFHUDView.m:228 | |
frame #10: 0x0046285c PSPDFCatalog`-[PSPDFHUDView configurationChangedNotification:](self=0x165afce0, _cmd=0x0082977a, notification=0x17a903e0) + 264 at PSPDFHUDView.m:284 | |
frame #11: 0x2d536e70 CoreFoundation`__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12 | |
frame #12: 0x2d4aaab0 CoreFoundation`_CFXNotificationPost + 1720 | |
frame #13: 0x2de90ec4 Foundation`-[NSNotificationCenter postNotificationName:object:userInfo:] + 72 | |
frame #14: 0x003acf92 PSPDFCatalog`-[PSPDFViewController setPageInternal:](self=0x16bcfc00, _cmd=0x0082213d, page=91) + 674 at PSPDFViewController.m:1059 | |
frame #15: 0x00386400 PSPDFCatalog`-[PSPDFPageScrollViewController tilePagesForced:](self=0x167edba0, _cmd=0x00821f79, forceUpdate='\0') + 4908 at PSPDFPageScrollViewController.m:320 | |
frame #16: 0x00388654 PSPDFCatalog`-[PSPDFPageScrollViewController scrollViewDidScroll:](self=0x167edba0, _cmd=0x302e1207, scrollView=0x167ee1a0) + 236 at PSPDFPageScrollViewController.m:489 | |
frame #17: 0x2ff9b8bc UIKit`-[UIScrollView(UIScrollViewInternal) _notifyDidScroll] + 64 | |
frame #18: 0x2fd1818c UIKit`-[UIScrollView setContentOffset:] + 604 | |
frame #19: 0x2fda2ba4 UIKit`-[UIScrollView(UIScrollViewInternal) _setContentOffset:animated:animationCurve:animationAdjustsForContentOffsetDelta:] + 412 | |
frame #20: 0x2fda2a02 UIKit`-[UIScrollView(UIScrollViewInternal) _setContentOffset:animated:animationCurve:] + 38 | |
frame #21: 0x2fda29d6 UIKit`-[UIScrollView setContentOffset:animated:] + 30 | |
frame #22: 0x00384b44 PSPDFCatalog`-[PSPDFPageScrollViewController setPage:animated:](self=0x167edba0, _cmd=0x00809ecc, page=91, animated='\0') + 748 at PSPDFPageScrollViewController.m:178 | |
frame #23: 0x003ad576 PSPDFCatalog`-[PSPDFViewController setPage:animated:](self=0x16bcfc00, _cmd=0x00809ecc, page=91, animated='\0') + 1058 at PSPDFViewController.m:1094 | |
frame #24: 0x003cc366 PSPDFCatalog`-[PSPDFViewController scrobbleBar:didSelectPage:](self=0x16bcfc00, _cmd=0x00829941, scrobbleBar=0x165dd930, page=91) + 246 at PSPDFViewController.m:3635 | |
frame #25: 0x002b9870 PSPDFCatalog`-[PSPDFScrobbleBar processTouch:](self=0x165dd930, _cmd=0x00819807, touch=0x16527b40) + 1116 at PSPDFScrobbleBar.m:256 | |
frame #26: 0x002b80d0 PSPDFCatalog`-[PSPDFScrobbleBar touchesMoved:withEvent:](self=0x165dd930, _cmd=0x302eddf2, touches=0x179ae100, event=0x16562fc0) + 140 at PSPDFScrobbleBar.m:102 | |
frame #27: 0x2fe7fea2 UIKit`forwardTouchMethod + 234 | |
frame #28: 0x2fd2d376 UIKit`-[UIWindow _sendTouchesForEvent:] + 354 | |
frame #29: 0x2fd28450 UIKit`-[UIWindow sendEvent:] + 832 | |
frame #30: 0x2fcfdd78 UIKit`-[UIApplication sendEvent:] + 196 | |
frame #31: 0x2fcfc568 UIKit`_UIApplicationHandleEventQueue + 7116 | |
frame #32: 0x2d53ff1e CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14 | |
frame #33: 0x2d53f3e6 CoreFoundation`__CFRunLoopDoSources0 + 206 | |
frame #34: 0x2d53dbd6 CoreFoundation`__CFRunLoopRun + 630 | |
frame #35: 0x2d4a8470 CoreFoundation`CFRunLoopRunSpecific + 524 | |
frame #36: 0x2d4a8252 CoreFoundation`CFRunLoopRunInMode + 106 | |
frame #37: 0x321af2ea GraphicsServices`GSEventRunModal + 138 | |
frame #38: 0x2fd5d844 UIKit`UIApplicationMain + 1136 | |
frame #39: 0x0012132a PSPDFCatalog`main(argc=1, argv=0x27d48cfc) + 134 at main.m:16 | |
What I ended up using: | |
// Define a custom layer class: | |
+ (Class)layerClass { | |
return PSPDFSetNeedsLayoutSupresserLayer.class; | |
} | |
// Add block that executes frame changes, using the generic layer store: | |
static NSString *const PSPDFSupressLayoutKey = @"supressSetNeedsLayout"; | |
- (void)performWithoutTriggeringSetNeedsLayout:(dispatch_block_t)block { | |
[self.layer setValue:@YES forKey:PSPDFSupressLayoutKey]; | |
block(); | |
[self.layer setValue:@NO forKey:PSPDFSupressLayoutKey]; | |
} | |
@implementation PSPDFSetNeedsLayoutSupresserLayer | |
// Checks the layer store to supress certain layoutSubview triggers that we don't want for performance reasons. | |
- (void)setNeedsLayout { | |
if (![[self valueForKey:PSPDFSupressLayoutKey] boolValue]) { | |
[super setNeedsLayout]; | |
} | |
} | |
@end |
In my simple test, calling sizeToFit
on a label which is a subview of parentView
did not result layoutSubviews
being called on parentView
, only setNeedsLayout
is called on parentView.layer
like in your example.
Are sure layoutSubviews
is triggered? Whats the backtrace?
The above IS the backtrace. setNeedsLayout on the layer is invoked - this triggers layoutSubviews at the end of the runloop. It doesn't happen always, that's why I'm so confused.
So apparently changing the size of a frame does trigger the parent's layoutSubviews UNLESS the frame is set within the parent's layoutSubviews method (that would otherwise lead to it being invoked in each runloop until the frame doesn't change anymore)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I can think of lots of workarounds, like defining my own block to ignore the following subview request - but since that is triggered async it's a bit harder. I could also override the layer to work against the async (since dirty flagging is sync) but I'd much rather understand the magic of CA::Layer::property_did_change and block this at the source.