mutualmobile/MMSpreadsheetView

exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN

mralghazali opened this issue · 4 comments

First thing first I wanna say thank you for making this library, this is really a great work.

But unfortunately I just found an issue. I made a 3-header-rows and 1-header-column table and sometimes when I ran my project, it becomes crash with following error:

2015-02-12 12:35:23.981 mommychi[578:121987] *** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [2.5 nan]'
*** First throw call stack:
(0x2b7ac5f7 0x392fac77 0x2b7ac53d 0x2e6721cf 0x2e6720d3 0x2e672065 0x2ec4afe3 0x1c48dd 0x1c2b69 0x2ec4e19f 0x2e679f65 0x2e675951 0x2e6757d9 0x2e6751c7 0x2e674fd1 0x2e66eedd 0x2b773015 0x2b7706f9 0x2b770afb 0x2b6bdb31 0x2b6bd943 0x32a72051 0x2ecaff21 0x59ef5 0x39896aaf)
libc++abi.dylib: terminating with uncaught exception of type NSException

Recently I realized that the error comes from MMSpreadsheetView.m, particularly at this line:

CGFloat indicatorOffsetY = collectionView.contentOffset.y / (contentSize.height - collectionViewFrame.size.height) * (scrollIndicator.frame.size.height - indicatorHeight);

The problem is (contentSize.height - collectionViewFrame.size.height) comes to zero.

Then I edited that line to:
CGFloat divider = (contentSize.height - collectionViewFrame.size.height > 0) ? (contentSize.height - collectionViewFrame.size.height) : 0.1;
CGFloat indicatorOffsetY = collectionView.contentOffset.y / divider * (scrollIndicator.frame.size.height - indicatorHeight);

I don't really understand what have I edited, but it become works, the error's gone.
Can you enlighten me about this issue? I hope there will be no another problem.

@mralghazali Yes, I found that recently on my own project and added this to updateVerticalScrollIndicator:

        CGFloat divideByZeroOffset = 0.0f;
        if (contentSize.height == collectionViewFrame.size.height) {
            divideByZeroOffset = 1.0f;
        }
        CGFloat indicatorOffsetY = collectionView.contentOffset.y / (contentSize.height - collectionViewFrame.size.height + divideByZeroOffset) * (scrollIndicator.frame.size.height - indicatorHeight);

and this to updateHorizontalScrollIndicator:

        CGFloat divideByZeroOffset = 0.0f;
        if (contentSize.width == collectionViewFrame.size.width) {
            divideByZeroOffset = 1.0f;
        }
        CGFloat indicatorOffsetX = collectionView.contentOffset.x / (contentSize.width - collectionViewFrame.size.width + divideByZeroOffset) * (scrollIndicator.frame.size.width-indicatorWidth);

I haven't committed it yet because I haven't fully tested it yet.

This happens in the rare case that your grid is exactly the same size as your view so I've added 1 pixel to prevent the divideByZero. Let me know if that helps.

@mralghazali See if this PR helps.
#18

@jeffla great, that really helps, thank you very much for the update :)

I suggest the following instead of directly comparing floating values:

CGFloat divideByZeroOffset = fabs(contentSize.height - collectionViewFrame.size.height) < 1.0 ? 1.0f : 0.0f;
CGFloat divideByZeroOffset = fabs(contentSize.width - collectionViewFrame.size.width) ? 1.0f : 0.0f;