iOS Nil value in variable when it should be non-nil

moonman239

macrumors 68000
Original poster
Mar 27, 2009
1,521
22
My app has this weird bug in it. I have a method that returns a variable. Later on in the app, a variable is supposed to be set to what the method returns. This variable ends up being nil, while the variable returned by the method is not nil. It seems like the simulator is ignoring the part where the former variable is supposed to be set to the method's returned variable.

I didn't intentionally set it to nil. It just happened inexplicably.
 

dejo

Moderator
Staff member
Sep 2, 2004
15,725
447
The Centennial State
You do your fellow developers a discourtesy by not providing any code with your post. Please be kind to those you seek help from. Also, read and follow Mike Ash's advice in his wonderful Getting Answers article.
 

chown33

Moderator
Staff member
Aug 9, 2009
8,445
4,448
Pale blue comma
My guess is Sock Gnomes. They're desperate after the Great Polyestering, and have taken to stealing objects from unsuspecting apps. They promise to return it, but none of those promises has a deadline, so it's impossible to get a properly returned value from them in a timely manner.

In the past, I would have suggested running 'lint', but the Sock Gnomes long ago collected all the lint, so it's impossible to even build 'lint' from source without a Sock Gnome instantly popping in and stealing it.
 

JohnsonK

macrumors regular
Mar 6, 2014
142
0
I don't know why this gentleman ALWAYS fails to provide code. It is not like he doesn't know he must provide us code in order to get help because we ALWAYS tell him we can't magically figure out what on earth he is coding.
 

TheWatchfulOne

macrumors 6502
Jun 19, 2009
403
271
I don't know why this gentleman ALWAYS fails to provide code. It is not like he doesn't know he must provide us code in order to get help because we ALWAYS tell him we can't magically figure out what on earth he is coding.
I think he's working on a top secret project. He cold post the code, but then he'd have to kill us. ;)

moonman, I suggest verifying that the variable you're trying to capture the return value in is actually pointing to a location in memory.

Then make sure you're not changing the value again at a later time.
 

moonman239

macrumors 68000
Original poster
Mar 27, 2009
1,521
22
Here is a modified version of the code: (I prefer not to hint at what I am doing):
Code:
// The method
-(TreeNode *)nextNode
{
    TreeNode *node = [unfinishedNodes firstObject];  // This variable is not nil.
    [unfinishedNodes removeObject:node];
    return node;
}
// The variable that is supposed to be set to the return value of the method.  It is nil.
currentNode = [[self info] nextNode];
Edit: I should add that the method is only called once.
 
Last edited:

TheWatchfulOne

macrumors 6502
Jun 19, 2009
403
271
Here is a modified version of the code: (I prefer not to hint at what I am doing):
Code:
// The method
-(TreeNode *)nextNode
{
    TreeNode *node = [unfinishedNodes firstObject];  // This variable is not nil.
    [unfinishedNodes removeObject:node];
    return node;
}
// The variable that is supposed to be set to the return value of the method.  It is nil.
currentNode = [[self info] nextNode];
Edit: I should add that the method is only called once.
Great!

Which variable is not nil? node or unfinishedNodes?

How many objects does unfinishedNodes contain?

Have you accounted for what happens when unfinishedNodes is empty?
 
Last edited:

moonman239

macrumors 68000
Original poster
Mar 27, 2009
1,521
22
Great!

Which variable is not nil? node or unfinishedNodes?

How many objects does unfinishedNodes contain?

Have you accounted for what happens when unfinishedNodes is empty?
1) Both are not nil.
2) It gets filled with two.
3) No, because by the time unfinishedNodes becomes empty, the app is not supposed to call nextNode.

Figure where your code retains the object. If nowhere, that's a bug.
I am using ARC, and I don't see why the object wouldn't be retained while the view controller is up. Besides, I would get an EXC_BAD_ACCESS error.
 

MorphingDragon

macrumors 603
Mar 27, 2009
5,160
5
The World Inbetween
1) Both are not nil.
2) It gets filled with two.
3) No, because by the time unfinishedNodes becomes empty, the app is not supposed to call nextNode.



I am using ARC, and I don't see why the object wouldn't be retained while the view controller is up. Besides, I would get an EXC_BAD_ACCESS error.
This seems like something suited for steeping through with a debugger than asking a forum with a fraction of the code needed to understand what is going on.
 

moonman239

macrumors 68000
Original poster
Mar 27, 2009
1,521
22
This seems like something suited for steeping through with a debugger than asking a forum with a fraction of the code needed to understand what is going on.
Here's a schematic to help you guys understand what is going on:

I have a view controller. This view controller has a strongly-referenced property whose class's implementation file contains the method I posted, and whose header file declares it. The view controller also has a strongly-referenced property named currentNode. This property, as indicated in the code I posted, is set to the return value of the above method in viewDidLoad.

If I caused the problem, I don't know how I did.
 

TheWatchfulOne

macrumors 6502
Jun 19, 2009
403
271
1) Both are not nil.
3) No, because by the time unfinishedNodes becomes empty, the app is not supposed to call nextNode.
Does your app check the count of unfinishedNodes as a condition of whether to call nextNode? Or is unfinishedNodes being empty a result of the same condition which is also supposed to cause nextNode to not be called?

My own app which I'm developing sometimes does things it's "not supposed to do" but it's up to me to figure out why and put a stop to it.

In this line:
Code:
currentNode = [[self info] nextNode];
Is currentNode assigned a value by any other means than the method you posted?

Is currentNode found to be nil right away after your method is called, or later on after the program does some other things?

This property...
I just noticed this. Didn't realize before that this was a property. Did you manually declare a variable to back it up or are you letting Xcode do it automatically? Would you mind posting the declaration of this property and the declaration of any variables that back it and any @synthesize statements associated with it?

Also, when you find that currentNode is nil, are you accessing through the property or are you accessing the variable directly?

If you are implementing the getter and setter methods yourself, can you post those too?

Is currentNode always nil, or just sometimes?
 
Last edited:

moonman239

macrumors 68000
Original poster
Mar 27, 2009
1,521
22
Does your app check the count of unfinishedNodes as a condition of whether to call nextNode? Or is unfinishedNodes being empty a result of the same condition which is also supposed to cause nextNode to not be called?

My own app which I'm developing sometimes does things it's "not supposed to do" but it's up to me to figure out why and put a stop to it.

In this line:
Code:
currentNode = [[self info] nextNode];
Is currentNode assigned a value by any other means than the method you posted? No.

Is currentNode found to be nil right away after your method is called, or later on after the program does some other things? After the method is called.



I just noticed this. Didn't realize before that this was a property. Did you manually declare a variable to back it up or are you letting Xcode do it automatically? I let Xcode do it automatically. Would you mind posting the declaration of this property and the declaration of any variables that back it and any @synthesize statements associated with it? I wouldn't.

Also, when you find that currentNode is nil, are you accessing through the property or are you accessing the variable directly? I guess I'm accessing the variable directly.

If you are implementing the getter and setter methods yourself, can you post those too?

Is currentNode always nil, or just sometimes?Always.
Here's what you requested. *Please note that I intend to reveal as little information as reasonably possible because I follow a non-disclosure rule.
Code:
#Headers
@interface Info : NSObject <NSXMLParserDelegate>
@property (strong,nonatomic) TreeNode *nextNode;
@end




@interface ViewController : UIViewController
@property (strong,nonatomic,readonly) TreeNode *currentNode;
@end




@implementation ViewController
@synthesize currentNode;




-(void)viewDidLoad
{
currentNode = [[self Info] nextNode];
}
That's what a debugger is for.
What I did was set breakpoints so I could look at the relevant variables.
 
Last edited:

firewood

macrumors 604
Jul 29, 2003
7,645
872
Silicon Valley
If you make currentNode a property, you can check for nil in a custom setter. Set a breakpoint there and you will catch the culprit. Log the owner object to make sure you are setting the same currentNode, and not one in a different object. You can also put an assert for the return value of nextNode.
 

TheWatchfulOne

macrumors 6502
Jun 19, 2009
403
271
According to this line of code:

Code:
@property (strong,nonatomic,readonly) TreeNode *currentNode;
Your property is ready only. Do you get any warning stating something along the lines of "error assignemnt to readonly property?"

You posted this line of code earlier:
Code:
currentNode = [[self info] nextNode];
Which looks like you're accessing the variable directly as you said.
Is that the entire line?
If you had done this:
Code:
self.currentNode = [[self info] nextNode];
You would get the compiler warning about assigning to a readonly property.

If you want to access the variable directly, I suggest manually declaring it like this:

Code:
TreeNode *_currentNode;
Your property declaration would look the same, but your synthesize statement would look like this:

Code:
@synthesize currentNode = _currentNode;
That tells your property to use your manually declared variable as its backing store. Then you can more easily tell which is which.