Reputation: 10971
I have a singleton class that is instantiated as follows:
#import "FavoritesManager.h"
static FavoritesManager *sharedFavoritesManager = nil;
@implementation FavoritesManager
+ (id)sharedManager {
@synchronized(self) {
if (sharedFavoritesManager == nil) {
sharedFavoritesManager = [[self alloc] init];
}
}
return self;
}
This returns an object, but for some reason it will only respond to class methods. If I call a instance method I get
+[FavoritesManager testMethod]: unrecognized selector sent to class 0x59198
For what it's worth, this is what testMethod looks like:
- (void)testMethod {
NSLog(@"Test");
}
and I'm absolutely positive it's declared in the interface. I've used this exact code in other classes and it works like a charm, so I don't really understand what the problem is here. One thing that is suspicious is the plus sign in +[FavoritesManager testMethod]
, but I can't explain it. Any ideas?
EDIT: I was confusing public/private and class/method terminology. Thanks to everyone who pointed that out.
Upvotes: 0
Views: 2635
Reputation: 64002
The error indicates that you're sending the message testMethod
to the class, rather than an instance.
The reason for this is that your sharedManager
method is incorrect. You are currently returning self
, which, in this class method, is the class itself. This means that when you write [[FavoritesManager sharedManger] testMethod]
you end up sending testMethod
to the class. Since testMethod
isn't a class method, you get an error.
You should have return sharedFavoritesManager;
at the end of sharedManager
, not return self;
. The latter is correct only in instance method initializers.
Also, as dbrajkovic commented, you seem to be confused about public/private and class/instance methods. Strictly, ObjC has no private methods. You can hide the declaration, which will cause a compiler warning, but the message will still be sent and the method will be called. The +
and -
distinguish class methods from instance methods; the distinction is which kind of object you send a message to. Info here: What is the difference between class and instance methods?
Upvotes: 4
Reputation: 100622
If you want to call testMethod from another class method then you need:
+ (void)testMethod {
NSLog(@"Test");
}
The reason is that if you call a class method then there's no instance, so nothing on which to call instance methods. But probably you want to call:
[[FavoritesManager sharedManager] testMethod];
Which means 'get the shared instance, then call testMethod
on it'. Thinking as I type, you might also like to add:
+ (void)forwardInvocation:(NSInvocation *)anInvocation
{
id sharedManager = [self sharedManager];
if ([sharedManager respondsToSelector:
[anInvocation selector]])
[anInvocation invokeWithTarget:sharedManager];
else
[super forwardInvocation:anInvocation];
}
Which is the Objective-C means for message forwarding. So if the metaclass FavoritesManager
receives a message it can't respond to, it lets its shared manager instance have a go. That means that:
[FavoritesManager testMethod];
Becomes functionally equivalent to (though a little slower than):
[[FavoritesManager sharedManager] testMethod];
Providing that you haven't implemented a class method in addition to an instance method. You can learn more about message forwarding in Apple's official documentation.
Upvotes: 6
Reputation: 4427
Call your singleton instance:
[[ FavoritesManager sharedManager] testMethod];
Upvotes: 0
Reputation: 3703
The error is right you must be calling [FavoritesManager testMethod]
which means you're trying to call a class method. I believe you want [[FavoritesManager sharedManager] testMethod];
Upvotes: 2
Reputation: 557
Instead try
[[FavoritesManager sharedFavoritesManager] testMethod];
Upvotes: 1
Reputation: 9977
there are no priavte methods in obj-c. But anyway on a singleton you are always calling from the outside of the class, so only declare "public methods". for detailed help post your code.
Upvotes: 0
Reputation: 9923
+ at the start of a method declaration means that it's a class method, - means that it's an instance method. Do this:
+(void)testMethod {
NSLog(@"Test");
}
If you want to invoke testMethod on your sharedManager, then keep the testMethod declaration as you have it and instead change your invocation to
[[FavoritesManager sharedFavoritesManager] testMethod];
Either will work, and choosing between the two is a matter of app design.
Upvotes: 1