What causes this error? "CALayer position contains NaN: [240 nan]"
I've seen this happen whenever i rotate a screen that has a UITableView
on it. I've found out that it happens inbetween the willRotate
and didRotate
method calls in UIViewController
My co-workers have seen it in other spots as well, usually around rotation. It hadnt started happening until very recently, and we're stumped as to how we should deal with it (google searches don't turn up the error message in its e开发者_如何学JAVAxact form). Has anyone else encountered this that knows what to do about it?
(Decided to take this out of comments and put it as an answer, since I think it's a darned good answer :)
Ha! I had an NaN calculation (div0), too. Key debugging aid: the message in question is output by NSLog(), so set a breakpoint on NSLog() and watch what the OS is doing at that time. For me, it was myUISlider.value = NaN.
To set breakpoint:
XCode 3.x
- CMD-SHIFT-Y (debug window.)
- Breakpoints button.
- "Double-click for symbol"
- Type in "NSLog" (no quotes.)
XCode 4.x
- CMD-6 (breakpoints navigator.)
- "+" to add breakpoint (lower left.)
- Select ADD SYMBOLIC BREAKPOINT.
- Symbol: NSLog
- Confirm: Done.
XCode 5.x - 7.1 (at least) (Same as 4.x, except breakpoints navigator is CMD-7, now.)
Run app, watch it break on NSLog, check the stack traces.
I've found the problem.
When you reset the frame of a tableview
, it calls the delegate method tableView:heightForRowAtIndexPath:
for each row in the table so it can recalculate its content size if it needs to. At that point, we do some special handling to return the height, and due to some bad assumptions in our code, we mistakenly returned NaN
due to a divide by zero error (the variable we divide by was assumed to never be zero). Making sure that we do not divide by zero here fixed it.
I've spent a day trying to find the code that causes same problem and solved it within a minutes after enabling "break on exception" in Xcode. Check this tutorial to see how to enable it.
I had this problem when i was assumed that:
tableView:heightForHeaderInSection:
returned an NSInteger
, but it returns CGFloat
...
changing:
-(NSInteger)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
to
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
fixed my issue.
Edit:
At some point I figured out how computers work below the C level, so I thought I would share it... (I will use an register names from x86_64 as I am most familiar with them, ARM would be slightly different but analogous)
int f(){
float someFloat=5.0f;
return someFloat;
}
results in converting the value of someFloat
to an integer type then copying that to a particular register: %rax
then calling the return instruction.
float f(){
float someFloat=5.0f;
return someFloat;
}
results in copying the value of someFloat
from its current location to a particular register: %xmm0
then calling the return instruction.
So if you have the wrong prototype the calling code will expect the value to be in the wrong place, you will end up really returning a garbage value.
This error also cost me a long time.
At the end I found my colleague wrote something like this:
UIEdgeInsets a;
a.left = (...some calculation);
button.imageEdgeInsets = a;
And I rewrote these code like this and fix the issue:
UIEdgeInsets a;
a.left = (...some calculation);
a.top = 0;
a.bottom = 0;
a.right = 0;
button.imageEdgeInsets = a;
some value of UIEdgeInsets isn't initialised properly, and it sometimes turn into a NaN value, and crash the application.
More generally, you should check whether all values of C-style structs are initialised properly.
There is an another way to reproduce the issue: using insetBy(dx:dy:)
on a too small rect
You can try this yourTableview?.bounces = false
. It works for me.
精彩评论