Nil value in variable when it should be non-nil

Discussion in 'iOS Programming' started by moonman239, Apr 17, 2014.

  1. moonman239 macrumors 68000

    Joined:
    Mar 27, 2009
    #1
    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.
     
  2. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #2
    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.
     
  3. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #3
    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.
     
  4. JohnsonK macrumors regular

    Joined:
    Mar 6, 2014
    #4
    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.
     
  5. TheWatchfulOne macrumors 6502

    Joined:
    Jun 19, 2009
    #5
    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.
     
  6. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #6
    Then I'm glad I blamed it on the Sock Gnomes.
     
  7. moonman239, Apr 18, 2014
    Last edited: Apr 18, 2014

    moonman239 thread starter macrumors 68000

    Joined:
    Mar 27, 2009
    #7
    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.
     
  8. TheWatchfulOne, Apr 18, 2014
    Last edited: Apr 18, 2014

    TheWatchfulOne macrumors 6502

    Joined:
    Jun 19, 2009
    #8
    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?
     
  9. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #9
    Figure where your code retains the object. If nowhere, that's a bug.
     
  10. moonman239 thread starter macrumors 68000

    Joined:
    Mar 27, 2009
    #10
    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.
     
  11. MorphingDragon macrumors 603

    MorphingDragon

    Joined:
    Mar 27, 2009
    Location:
    The World Inbetween
    #11
    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.
     
  12. moonman239 thread starter macrumors 68000

    Joined:
    Mar 27, 2009
    #12
    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.
     
  13. TheWatchfulOne, Apr 18, 2014
    Last edited: Apr 18, 2014

    TheWatchfulOne macrumors 6502

    Joined:
    Jun 19, 2009
    #13
    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?

    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?
     
  14. MorphingDragon macrumors 603

    MorphingDragon

    Joined:
    Mar 27, 2009
    Location:
    The World Inbetween
    #14
    That's what a debugger is for.
     
  15. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #15
    That's not a schematic. That a written explanation of what the code does. Not providing actual problematic code at this point is bordering on rudeness. I'm surprised you're getting any help at all.
     
  16. moonman239, Apr 21, 2014
    Last edited: Apr 21, 2014

    moonman239 thread starter macrumors 68000

    Joined:
    Mar 27, 2009
    #16
    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];
    }
    
    What I did was set breakpoints so I could look at the relevant variables.
     
  17. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #17
    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.
     
  18. TheWatchfulOne macrumors 6502

    Joined:
    Jun 19, 2009
    #18
    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.
     

Share This Page