开发者

UITableView crash gives 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [160 nan]'

I have a custom table view in my app. I have implemented the "Load More" feature to the table which loads 25 rows at a time. The problem is after loading 2 times the app crashes giving 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [160 nan]' as error on OS 4.2 and above.

On OS below 4.2 one of the cell goes missing and there is blank space between in the middle of the table. It do not give any crash. But it still gives the error mentioned above.

I check to see where can the division by 0 can occur in my code but i couldnt find any. Following the stack trace i fond. So i cannot even check where this exception is happening.

Anybody have any idea ??

    0   CoreFoundation                      0x020ccbe9 __exceptionPreprocess + 185
 1   libobjc.A.dylib                     0x022215c2 objc_exception_throw + 47
 2   CoreFoundation                      0x02085628 +[NSException raise:format:arguments:] + 136
 3   CoreFoundation                      0x0208559a +[NSException raise:format:] + 58
 4   QuartzCore                          0x0182396a _ZL18CALayerSetPositionP7CALayerRKN2CA4Vec2IdEEb + 177
 5   QuartzCore                          0x018238b5 -[CALayer setPosition:] + 42
 6   QuartzCore                          0x018237cc -[CALayer setFrame:] + 763
 7   UIKit                               0x0073c307 -[UIView(Geometry) setFrame:] + 255
 8   UIKit                               0x008c718a -[UITableViewCell setFrame:] + 166
 9   UIKit                               0x0077aa08 -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] + 1160
 10  UIKit                               0x0077077f -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] + 75
 11  UIKit                               0x00785450 -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1561
 12  UIKit                               0x0077d538 -[UITableView layoutSubviews] + 242
 13  QuartzCore                          0x01828451 -[CALayer layoutSublayers] + 181
 14  QuartzCore                          0x0182817c CALayerLayoutIfNeeded + 220
 15  QuartzCore                          0x0182137c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 310
 16  QuartzCore                          0x018210d0 _ZN2CA11Transaction6commitEv + 292
 17  QuartzCore                          0x018517d5 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 99
 18  CoreFoundation                      0x020adfbb __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 27
 19  CoreFoundation                      0x020430e7 __CFRunLoopDoObservers + 295
 20  CoreFoundation                      0x0200bbd7 __CFRunLoopRun + 1575
 21  CoreFoundation                      0x0200b240 CFRunLoopRunSpecific + 208
 22  CoreFoundation                      0x0200b161 CFRunLoopRunInMode + 97
 23  GraphicsServices                    0x02611268 GSEventRunModal + 217
 24  Gra开发者_StackOverflowphicsServices                    0x0261132d GSEventRun + 115
 25  UIKit                               0x0071542e UIApplicationMain + 1160


I had this same exact error because instead of writing

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { ... }

i wrote:

- (NSInteger)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { ... }

(notice the return value). Hope this helps somebody.


The stack trace looks like the UITableView is busy layouting the visible cells when the exception occurs. Since the position of a cell seems to be set to a NaN value one has to ask how this can happen.

Assuming there's no bug in the UITableView layout code, the only way this can happen is that you implement tableView:heightForRowAtIndexPath: in your table view delegate and return a bad height (or one of the according header or footer methods).

Edit to pinpoint the exact cause of the exception:

I assume you calculated the height of the cell from the geometric size of a string (using UIStringDrawing's -[NSString sizeWithFont:]). When you send a message to a nil value, the return value usually is nil, 0, NO, or whatever value is represented by an all-bits-zero word.

For a method that returns a struct (as sizeWithFont:) this is not true. The returned struct is not initialized at all, containing random values for its elements.

In your case, you probably used one of the uninitialized elements of the CGSize struct, which later turned out not to be a valid IEEE 754 floating point value.

Addendum: Since clang 3.0 the structs returned from messages are initialized to {0} (all bits zero). So above problem should not happen any more.


Messages to nil that return structs of structs can return undefined values in the inner struct.

In practical terms, this means that getting the frame from a nil UIView can return undefined values in the size field of the frame. This bug just bit me and I was surprised.


The simple answer:

Returning a NaN from any of the height related delegate methods causes this error.

 tableView:heightForRowAtIndexPath:
 tableView:heightForHeaderInSection:
 tableView:heightForFooterInSection:

etc..

There may be other ways to produce this error but if you're working with UITableView--check this first!


For me it was caused by the toView in this code being nil:

    [UIView transitionFromView:self.fromView
                        toView:self.toView
                      duration:0.6
                       options:(currentPage > toPage ? UIViewAnimationOptionTransitionCurlDown : UIViewAnimationOptionTransitionCurlUp)
                    completion:^(BOOL finished) {
                        if (finished) {
                        }
                    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜