0

I have a following code in my singleton class

static MySingleton *gManager;
+(void)initialize
{
   if(self == [MySingleton class])
   {
       gManager = [[MySingleton alloc] initWithServices:[[MyServices alloc] init]];
   }
}
+(MySingleton *)sharedInstance
{
   return (gManager);
}

Unfortunately, during the unit tests I see that gManager is an instance of type SenTestCaseRun. I cant seem to figure out why? So a call like [[MySingleton sharedInstance] myFunction];

results in an error that myFunction is an unknown selector although it exists in the MySingleton class.

It is of type SenTestCaseRun because I checked using NSStringFromClass function.

Any pointers? Already banged my head for 3-4 hours on this :(.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836

2 Answers2

1

it may be better to just put the initialization code inside the shared instance method

+(MySingleton *)shared
{
    static MySingleton *sharedInstance = nil;
    if(sharedInstance == nil){
        sharedInstance = [[MySingleton alloc] init];
    }
    return sharedInstance;
}

also in your code you are comparing an object to a class which will never be true instead of comparing [self class] to [MySingleton class].

Colin Wheeler
  • 3,343
  • 2
  • 21
  • 23
  • The advantage of the OP's version is that it is threadsafe. In a class method like `+initialize`, `self` is the class. – Rob Napier Feb 22 '11 at 19:46
0

Put a breakpoint in +initialize to make sure this variable is set correctly. If that doesn't explain it, use a watchpoint on it to see who's modifying it.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • I tried it under the debugger and the only place the global gManager gets initialized is during the unit test startup with following call stack ` #0in +[AudioManager initialize] at AudioManager.m:118 #1in _class_initialize #2in _class_initialize #3in prepareForMethodLookup #4in lookUpMethod #5in _class_lookupMethodAndLoadCache #6in objc_msgSend #7in +[NSObject(SenTestRuntimeUtilities) senAllSubclasses] #8in +[SenTestSuite updateCache] #9in +[SenTestSuite suiteForBundleCache] #10in +[SenTestSuite testSuiteForBundlePath:] #11in +[SenTestProbe specifiedTestSuite] #12in +[SenTestProbe runTests:]` – Nitin Singh Feb 22 '11 at 21:49
  • That's from the watchpoint? And it's assigned to the correct class at that point, but later crashes because it's the wrong class? – Rob Napier Feb 23 '11 at 18:08
  • Ok found out the problem. I was releasing my singleton during the app shutdown [[MySingleton sharedInstance] release]. If referenced later the global was a random instance set by the runtime. It does not makes sense to release a singleton but then I needed to release some resources. So I refactored the code. BTW, my code worked well on the device but unit tests were invoking app shutdown events many times. – Nitin Singh Feb 23 '11 at 22:00
  • Glad it worked out. Remember that -dealloc never guaranteed to run, and is generally skipped during application quit, so if you have external resources you need to release, you have to observe `NSApplicationWillTerminate`, or arrange to be called by someone who does. – Rob Napier Feb 24 '11 at 01:59