Objective-C: variable holds different value from that returned by method

Discussion in 'iOS Programming' started by moonman239, Jan 14, 2016.

  1. moonman239 macrumors 68000

    Joined:
    Mar 27, 2009
    #1
    I think something's wrong with my debugger. I have a line of code that is syntactically similar to this:

    Code:
    NSManagedObjectSubclass1 *someObject = [[NSManagedObjectSubclass2 sharedObject] someObject];
    
    I set a breakpoint two lines down at another point, and there's no code to change someObject anywhere between the code line and the breakpoint.

    However, when the app stops at the breakpoint and I run "po someObject" and "po [[NSManagedObjectSubclass2 sharedObject] someObject]", for some unknown reason the former returns "nil" while the latter actually returns the right object.

    It's weird.
     
  2. Mascots, Jan 15, 2016
    Last edited: Jan 15, 2016

    Mascots macrumors 65816

    Mascots

    Joined:
    Sep 5, 2009
    #2
    We can't debug or offer guidance without more code, but it looks as if you messed up your singleton declaration. There's little chance your debugger is reporting different data because it's messed up and your code isn't.

    A lot of your issues seem unrelated to what you've supplied us in previous threads. The more information and code, the better. Otherwise we are stabbing at the dark.
     
  3. moonman239 thread starter macrumors 68000

    Joined:
    Mar 27, 2009
    #3
    OK, here's the actual code:
    Code:
       PlaceEntity *entity = [[UserEntitysharedEntity] placeEntityForLevel:[LevelObjectcurrentLevel]];
    
        NSInteger placeTag = [entity familyNum] * 10 + [entity activityNum];
    
     
  4. Mascots macrumors 65816

    Mascots

    Joined:
    Sep 5, 2009
    #4
    Unfortunately, that's still not enough to work on since I have no real understanding of how that plays into the grand scheme of your functioning.

    By my previous advice, all I can suspect is that your declaration for the singleton is incorrect - are you sure that
    NSManagedObjectSubclass2 (not someObject on that singleton) is actually the same object in both cases? I highly doubt it or there is something in your declaration that is preventing that property from being set until the second trip to the shared instance, after it has already been initialized by the first call.
     
  5. moonman239 thread starter macrumors 68000

    Joined:
    Mar 27, 2009
    #5
    Most likely. The singleton instance is set in a view controller that the user only sees once. Not once in my code do I set either managed object pointer to "nil".

    Edit: If you'd like to see my placeEntityForLevel code, please let me know.
     
  6. Mascots, Jan 15, 2016
    Last edited: Jan 15, 2016

    Mascots macrumors 65816

    Mascots

    Joined:
    Sep 5, 2009
    #6
    I'm not talking about the someObject instance on your singleton, I'm talking about the singleton itself. Here is a slightly more clear example of what you wrote:
    Code:
    NSManagedObjectSubclass *firstSingleton = [NSManagedObjectSubclass sharedObject]
    
    id *someObject = [someSingleton someObject];
    id *anotherSomeObjectObject = [[NSManagedObjectSubclass sharedObject] someObject];
    
    You are saying that someObject !=anotherSomeOtherObject.

    However, you're assuming that the above code is exactly the same as:
    Code:
    NSManagedObjectSubclass *firstSingleton = [NSManagedObjectSubclass sharedObject]
    
    id *someObject = [firstSingleton someObject];
    id *someObjectAgain = [firstSingleton someObject];
    
    Which it is not because if that were the case, the second code can only translate into: someObject == someObjectAgain. The problem, from my limited POV, is that firstSingleton != firstSingletonAgain

    What you wrote translates more into:
    Code:
    NSManagedObjectSubclass *firstSingleton = [NSManagedObjectSubclass sharedObject]
    id *someObject = [firstSingleton someObject];
    
    NSManagedObjectSubclass *firstSingletonAgain = [NSManagedObjectSubclass sharedObject]
    id *someObjectAgain = [firstSingletonAgain someObject];
    
    Meaning either: sharedObject is giving you two different Singletons, one without filled properties and one with filled properties or you are being given the same singleton and sharedObject it isn't setting up your Singleton properly the first time it is called.

    So back to my question: are references to the singleton (firstSingleton and firstSingletonAgain in the above snippet) the same or not? Using something similar to the last example I gave, you can set a breakpoint after your two calls and see what the identities of those objects are.

    Also, what is happening when you attempt to set it in the VC? Is your someObject property just returning nil? Is one method working and the other not? Or is the second attempt at grabbing the someObject always successful while the first fails? Depending on what happens in this spot, I may be pointing you down the incorrect path, but that's about the best I can do.
     
  7. moonman239, Jan 18, 2016
    Last edited: Jan 18, 2016

    moonman239 thread starter macrumors 68000

    Joined:
    Mar 27, 2009
    #7
    Hi, @Mascots apologies for the late response.

    sharedObject should return one - and only one - instance. It is set once, and only once.

    I seem, however, to be experiencing only a somewhat reproducible bug, perhaps a Heisenbug. The last time I tried debugging, everything seemed to work. However, I will try again.

    Edit: I re-read your post, and I feel I must clarify:

    1)
     
  8. ArtOfWarfare macrumors 604

    ArtOfWarfare

    Joined:
    Nov 26, 2007
    #8
    ... is the loneliest number...?
     
  9. Mascots macrumors 65816

    Mascots

    Joined:
    Sep 5, 2009
    #9
    We need you to confirm that sharedObject is actually producing the same object & that object is set up correctly on both calls. So far, you only assume it should be - you should be checking using breakpoints to get memory addresses so you know de facto. What about the questions I ask at the end of my last post? By observing those side effects, it may be easier to find enough consistency to address the root of the problem.

    Most likely, there's an issue with your sharedObject method and I do not think that you are experiencing a Heisenbug - I've described why it is pretty much only possible that a piece of code that you haven't shown us is causing your inconsistency - and if it is a random bug caused by an invalid state in your app, you must be doing something to cause that to happen. It isn't just happening.

    Can we see how you are creating this singleton and actual code behind calling the instance?
     
  10. moonman239, Jan 19, 2016
    Last edited: Jan 20, 2016

    moonman239 thread starter macrumors 68000

    Joined:
    Mar 27, 2009
    #10
    OK, I have confirmed that the singleton is always the same.

    Edit: Actually, what happens is this: When the sharedObject is first inserted, a new PlaceEntity is created. I think what I need to do is make sure the "level" attribute on PlaceEntity is initialized.
     
  11. Dookieman macrumors 6502

    Joined:
    Oct 12, 2009
    #11
    Can you please post the ALL of code for the Singleton class as well as the class where you want to use the Singleton. Like Mascots mentioned before, it looks like you don't have you Singleton set up correctly or are using it incorrectly.

    In the future, like Mascots said, we need more than just one or two lines of code. Your questions make zero sense based on the code you provide so we can't help you.
     
  12. moonman239, Jan 21, 2016
    Last edited: Jan 21, 2016

    moonman239 thread starter macrumors 68000

    Joined:
    Mar 27, 2009
    #12
    Sorry about that, at this point I'm kind of holding myself to a non-disclosure agreement.

    Having said that, here's the code for placeEntityForLevel:
    Code:
    -(PlaceEntity *)placeEntityForLevel:(NSInteger)level
    
    {
    
        NSPredicate *entityPredicate = [NSPredicate predicateWithFormat:@"level==%f",level];
    
        NSSet *filteredSet = [self.places filteredSetUsingPredicate:entityPredicate];
    
        return [filteredSet anyObject];
    
    }
    
    Edit: I notice that the data appears to persist, as I can stop the app and it remembers exactly what I intended it to. (A "save" operation actually occurs in a succeeding view controller.)
    Edit: What in the heck? Problem's not there anymore. I'll do a re-run, see what happens. I do have a breakpoint that alters the values of the entity, but that should be completely irrelevant given the breakpoint's location.
    Edit #2: Problem's gone, and I disabled that breakpoint after first firing.
     
  13. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #13
    Add some assertions before the line:
    Code:
        return [filteredSet anyObject];
    I'm guessing the following should always be true, and if they're not, it's a serious failure:
    1. filteredSet is non-null.
    2. filteredSet has exactly one item in it.

    If you get an assertion failure, then you need to look at the data of self.places at that point in time, to figure out what led to the failed assertion.

    https://www.mikeash.com/pyblog/friday-qa-2013-05-03-proper-use-of-asserts.html
    Asserts should be written for conditions that, according to your understanding of the program, should never occur. ​
     
  14. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #14
    What's the optimization level? Optimized code sometimes doesn't store a result into the actual result variable's memory until it needs to be used way later. That's what renamed registers, data caches, and thread pools (etc.) are for.
     
  15. bjet767 macrumors 6502a

    Joined:
    Oct 2, 2010
    #15
    You have so many objects without letting the readers know what's in them or what they are required to return figuring out your problem is impossible.

    I would personally believe the real issue is you don't have default returns and error checking. When you expect a return then your objects need to either give the excepted return, an error or a default object.

    Don't expect the debugger to do your work for you. Use a lot of NSLog()s and error checking as you develop. The old C method was printf and code pauses with getch to work through difficult areas.
     

Share This Page