Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fatal Exception: CALayerInvalidGeometry CALayer bounds contains NaN #1173

Open
rzzvn opened this issue Nov 3, 2019 · 20 comments
Open

Fatal Exception: CALayerInvalidGeometry CALayer bounds contains NaN #1173

rzzvn opened this issue Nov 3, 2019 · 20 comments

Comments

@rzzvn
Copy link

rzzvn commented Nov 3, 2019

Hi I have encountered the following crashes on my app, happening in both iOS 12.4 and 13.x devices. However I am not able to reproduce this crash. Is there a way to solve this?
Thanks for the amazing library.

(Required) Version Number:
7.1.8

Fatal Exception: CALayerInvalidGeometry
CALayer bounds contains NaN: [nan 0; 0 0]. Layer: <CALayer:0x281d81e00; position = CGPoint (0 0); bounds = CGRect (0 0; 0 0); delegate = <JTAppleCalendar.JTAppleCalendarView: 0x1048a5400; baseClass = UICollectionView; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x281300210>; layer = <CALayer: 0x281d81e00>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}; layout: <JTAppleCalendar.JTAppleCalendarLayout: 0x11b574e20>; dataSource: <JTAppleCalendar.JTAppleCalendarView: 0x1048a5400; baseClass = UICollectionView; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x281300210>; layer = <CALayer: 0x281d81e00>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}; layout: <JTAppleCalendar.JTAppleCalendarLayout: 0x11b574e20>; dataSource: <JTAppleCalendar.JTAppleCalendarView: 0x1048a5400>>>; sublayers = (<CALayer: 0x281dcc740>); masksToBounds = YES; allowsGroupOpacity = YES; backgroundColor = <CGColor 0x283ebcff0> [<CGColorSpace 0x28398a940> (kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Generic Gray Gamma 2.2 Profile; extended range)] ( 1 1 )>

Last Exception Backtrace (0)#0 (null) in __exceptionPreprocess ()
#1 (null) in objc_exception_throw ()
#2 (null) in +[NSException raise:format:] ()
#3 (null) in CA::Layer::set_bounds(CA::Rect const&, bool) ()
#4 (null) in -[CALayer setBounds:] ()
#5 (null) in -[UIView(Geometry) setBounds:] ()
#6 (null) in -[UIScrollView setBounds:] ()
#7 (null) in -[UICollectionView setBounds:] ()
#8 (null) in -[UIScrollView setContentOffset:] ()
#9 (null) in -[UICollectionView setContentOffset:] ()
#10 (null) in -[UIScrollView _setContentOffset:animated:animationCurve:animationAdjustsForContentOffsetDelta:an... ()
#11 (null) in -[UICollectionView setContentOffset:animated:] ()
#12 0x101f6622c in JTAppleCalendarLayout.prepare() at /Users/rm/Documents/Project/TripO/Pods/JTAppleCalendar/Sources/JTAppleCalendarLayout.swift:154
#13 (null) in @objc JTAppleCalendarLayout.prepare() ()
#14 (null) in -[UICollectionViewData _prepareToLoadData] ()
#15 (null) in -[UICollectionViewData validateLayoutInRect:] ()
#16 (null) in -[UICollectionView layoutSubviews] ()
#17 0x101f4f698 in JTAppleCalendarView.layoutSubviews() at /Users/rm/Documents/Project/TripO/Pods/JTAppleCalendar/Sources/InternalActionFunctions.swift:28
#18 (null) in @objc JTAppleCalendarView.layoutSubviews() ()
#19 (null) in -[UIView(CALayerDelegate) layoutSublayersOfLayer:] ()
#20 (null) in -[CALayer layoutSublayers] ()
#21 (null) in CA::Layer::layout_if_needed(CA::Transaction*) ()
#22 (null) in CA::Layer::layout_and_display_if_needed(CA::Transaction*) ()
#23 (null) in CA::Context::commit_transaction(CA::Transaction*, double) ()
#24 (null) in CA::Transaction::commit() ()
#25 (null) in CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) ()
#26 (null) in display_timer_callback(__CFMachPort*, void*, long, void*) ()
#27 (null) in __CFMachPortPerform ()
#28 (null) in CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION ()
#29 (null) in __CFRunLoopDoSource1 ()
#30 (null) in __CFRunLoopRun ()
#31 (null) in CFRunLoopRunSpecific ()
#32 (null) in GSEventRunModal ()
#33 (null) in UIApplicationMain ()
#34 0x100c43018 in main at /Users/j/Documents/Project/Navagio/Controller/DateEditController.swift:24

@patchthecode
Copy link
Owner

What version are you using?

@jansvancer
Copy link

Hi,
I'm facing the same issue:

*** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer bounds contains NaN: [nan 0; 0 0]. Layer: <CALayer:0x281f7c1c0; position = CGPoint (0 0); bounds = CGRect (0 0; 0 0); delegate = <JTAppleCalendar.JTACMonthView: 0x10c82f400; baseClass = UICollectionView; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x2810f0150>; layer = <CALayer: 0x281f7c1c0>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}; layout: <JTAppleCalendar.JTACMonthLayout: 0x10ab38e80>; dataSource: <JTAppleCalendar.JTACMonthView: 0x10c82f400; baseClass = UICollectionView; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x2810f0150>; layer = <CALayer: 0x281f7c1c0>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}; layout: <JTAppleCalendar.JTACMonthLayout: 0x10ab38e80>; dataSource: <JTAppleCalendar.JTACMonthView: 0x10c82f400>>>; sublayers = (<CALayer: 0x281f7cb80>); masksToBounds = YES; allowsGroupOpacity = YES; backgroundColor = <CGColor 0x283bcbc60> [<CGColorSpace 0x283bdab20> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( 0.941176 0.952941 0.960784 1 )>

iOS: 13.1.3
Version number: 8.0.2

Thank you

@patchthecode
Copy link
Owner

@jansvancer are you experiencing this in production? or development.
and if in dev, then how do i reproduce it?

@jansvancer
Copy link

@patchthecode both, production and development.
In my case this happens after fresh app install only. In all other cases it looks, like it works. Which makes it really weird.
I actually found a temporary solution to call:

calendarView.setNeedsLayout()
calendarView.layoutIfNeeded()

before calling reloadData. But I'm not sure if this is the right solution and why this happens only in one specific case.

The actual crash happens at line 157 in JTACMonthLayout.swift

        // Set the first content offset only once. This will prevent scrolling animation on viewDidload.
        if !firstContentOffsetWasSet {
            firstContentOffsetWasSet = true
            let firstContentOffset = delegate.requestedContentOffset
--->     collectionView!.setContentOffset(firstContentOffset, animated: false)
        }

firstContentOffset has the x = NaN.

Hope this helps at least a little bit.

Thank you

@bsweett
Copy link

bsweett commented Apr 21, 2020

We just updated our app to use JTAppleCalendar and we are also seeing this issue in production. We are calling reloadDataWithAnchor from viewDidAppear.

A simple fix for this on the libraries side could be to verify the x and y points using isNaN.

@patchthecode
Copy link
Owner

@bsweett are you also using version 7? (and not version 8)

@patchthecode
Copy link
Owner

The reason why I have been slow to update this is because. It is hard for me to update so many versions.
The current version is now 8.0.3 and it has some improvements to work with latest iOS.
I can focus on the version 8+ fixes. But will need assistance on the 7+ versions.

@bsweett
Copy link

bsweett commented Apr 21, 2020

We are using version 8.0.3. Here is our stack trace:

Fatal Exception: CALayerInvalidGeometry
0  CoreFoundation                 0x1ae082a48 __exceptionPreprocess
1  libobjc.A.dylib                0x1adda9fa4 objc_exception_throw
2  CoreFoundation                 0x1adf781c0 -[NSCache init]
3  QuartzCore                     0x1b4b10c24 CA::Layer::set_bounds(CA::Rect const&, bool)
4  QuartzCore                     0x1b4b0085c -[CALayer setBounds:]
5  UIKitCore                      0x1b2584780 -[UIView(Geometry) setBounds:]
6  UIKitCore                      0x1b2517868 -[UIScrollView setBounds:]
7  UIKitCore                      0x1b196ab7c -[UICollectionView setBounds:]
8  UIKitCore                      0x1b2518aa4 -[UIScrollView setContentOffset:]
9  UIKitCore                      0x1b197d3d4 -[UICollectionView setContentOffset:]
10 UIKitCore                      0x1b2531e64 -[UIScrollView _setContentOffset:animated:animationCurve:animationAdjustsForContentOffsetDelta:animation:]
11 UIKitCore                      0x1b197d344 -[UICollectionView setContentOffset:animated:]
12 JTAppleCalendar                0x10404e494 JTACMonthLayout.prepare() + 133 (JTACMonthLayout.swift:133)
13 JTAppleCalendar                0x10404e6a0 @objc JTACMonthLayout.prepare() (<compiler-generated>)
14 UIKitCore                      0x1b19a42e4 -[UICollectionViewData _prepareToLoadData]
15 UIKitCore                      0x1b19a4b78 -[UICollectionViewData validateLayoutInRect:]
16 UIKitCore                      0x1b1975f5c -[UICollectionView layoutSubviews]
17 JTAppleCalendar                0x10404760c JTACMonthView.layoutSubviews() (JTACMonthView.swift)
18 JTAppleCalendar                0x104047780 @objc JTACMonthView.layoutSubviews() (<compiler-generated>)
19 UIKitCore                      0x1b259e17c -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
20 QuartzCore                     0x1b4b062c0 -[CALayer layoutSublayers]
21 QuartzCore                     0x1b4b0c43c CA::Layer::layout_if_needed(CA::Transaction*)
22 QuartzCore                     0x1b4b17140 CA::Layer::layout_and_display_if_needed(CA::Transaction*)
23 QuartzCore                     0x1b4a5f884 CA::Context::commit_transaction(CA::Transaction*, double)
24 QuartzCore                     0x1b4a89574 CA::Transaction::commit()
25 QuartzCore                     0x1b4a89f68 CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*)
26 CoreFoundation                 0x1adfffe68 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
27 CoreFoundation                 0x1adffad54 __CFRunLoopDoObservers
28 CoreFoundation                 0x1adffaafc CFRunLoopRunSpecific
29 GraphicsServices               0x1b7f9b328 GSEventRunModal
30 UIKitCore                      0x1b210863c UIApplicationMain

@patchthecode
Copy link
Owner

@bsweett hmm.
Sounds like a divide by zero error.

By any chance does your calendar change size? or anything like that?

There are two places in the source code I suspect is casing this. This bug should have been caught in development though. Let me do a check.
I suspect it has to do with this pull request -> #1154

I have not merged it yet though.
Will take a look

@bsweett
Copy link

bsweett commented Apr 22, 2020

Yes we do change the calendar size for two reasons:

  1. When the user rotates the devices from landscape to portrait
  2. When the user changes their font size (dynamic type)

I'm not sure that this is the specific cause though as our logs just show the user launching the controller with the calendar. We reload the data in the calendar when the view appears incase something changed from a view deeper in the navigation stack.

It seems like some point being sent to the collection view is invalid:
CALayer bounds contains NaN: [nan 0; 0 279]

@bsweett
Copy link

bsweett commented May 7, 2020

We resolved this on our end by changing the scrolling mode to none. In our case we didn't need scrolling.

I would still advise that the library verify the CGPoint that is constructed before passing it to the collection view.

@rs658726
Copy link

rs658726 commented Jul 13, 2020

EDIT: Nevermind, @bsweett 's fix did not work for me. I'm still seeing the error which results in a crash:

*** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer bounds contains NaN: [nan 0; 0 0]. Layer: <CALayer:0x7b0800157660; position = CGPoint (0 0); bounds = CGRect (0 0; 0 0); delegate = <JTAppleCalendar.JTACMonthView: 0x7b7c000b0c00; baseClass = UICollectionView; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7b0c00062d30>; layer = <CALayer: 0x7b0800157660>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}; layout: <JTAppleCalendar.JTACMonthLayout: 0x7b580012e700>; dataSource: <JTAppleCalendar.JTACMonthView: 0x7b7c000b0c00; baseClass = UICollectionView; frame = (0 0; 0 0); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7b0c00062d30>; layer = <CALayer: 0x7b0800157660>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}; layout: <JTAppleCalendar.JTACMonthLayout: 0x7b580012e700>; dataSource: <JTAppleCalendar.JTACMonthView: 0x7b7c000b0c00>>>; masksToBounds = YES; allowsEdgeAntialiasing = NO; backgroundColor = <CGColor 0x7b14000361f0> [<CGColorSpace 0x7b180004db80> (kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Profil gamma 2.2 gris générique; extended range)] ( 0 0 )>'

@patchthecode This is only happening when I'm showing the calendar inside a popOver. I'm really not sure what's causing this. Do you have any idea what could be the culprit here?

Here is how I set up my calendar:

    fileprivate func setupCalendar() {

        calendar.calendarDelegate = self
        calendar.calendarDataSource = self
                        
        calendar.scrollingMode = .stopAtEachCalendarFrame
                
        nextMonthButton.addTarget(self, action: #selector(nextMonth(_:)), for: .touchUpInside)
        previousMonthButton.addTarget(self, action: #selector(previousMonth(_:)), for: .touchUpInside)
        
        // Initial date selection
        if dueDate == nil || dueDate! < Date().startOfDay { dueDate = Date() }
        calendar.selectDates([dueDate!])
        
        calendar.scrollToDate(dueDate!, triggerScrollToDateDelegate: true, animateScroll: false) {
            self.calendar.visibleDates { visibleDates in
                DispatchQueue.main.async {
                     // ...
                }
            }
        }
    }

Regarding the layout, The calendar is inside a container view of fixed width 350 and is pin to the latter's 4 edges. Height and cellSize are calculated based off of the width.

@rafalwojcik
Copy link

@patchthecode We have the same issue with scrolling. At viewDidAppear we want to scroll to the actual month, but initially calendar is hidden in stack view. It is causing crash dividing by zero as in the examples above. I'm trying to fix this without hacking but it seems impossible.

@rs658726
Copy link

Hey @rafalwojcik, is your calendar presented in a popover?

@rafalwojcik
Copy link

rafalwojcik commented Aug 25, 2020

No, the issue occurs only when the calendar is initially hidden and we are using scrollToDate method.

It crashes right there (JTACMonthLayout.swift:158 in latest release):

// Set the first content offset only once. This will prevent scrolling animation on viewDidload.
if !firstContentOffsetWasSet {
    firstContentOffsetWasSet = true
    let firstContentOffset = delegate.requestedContentOffset
>>>    collectionView!.setContentOffset(firstContentOffset, animated: false)
}

@patchthecode
Copy link
Owner

Thank you for letting me know how to reproduce it
i'll look into a fix this weekend

@rafalwojcik
Copy link

@patchthecode nice. Thank you when do you have a plan to release new version? I can create PR to fix that but we need this fix to be oficially released :)

@rs658726
Copy link

2 solutions I can think of:
1 - Try scrolling on viewDidLoad and hiding the calendar on viewWillAppear?
2- Use scrollToDate's completion handler to hide your calendar. In other words, your calendar is showing, scrolling is executed and then on completion you hide your calendar. All of this code can be added to viewDidLoad.

Solution 2 might be the better one here.

@patchthecode
Copy link
Owner

@rafalwojcik i can create a minor release probably the same time as well. It will be version 8.0.4

@patchthecode
Copy link
Owner

@rafalwojcik If you can create a PR this will be awesome, as I am swamped with work.
@rs658726 I will take a look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants