Objective-C单例只响应类方法

时间:2012-03-01 21:04:03

标签: iphone objective-c ios singleton

我有一个单例类,实例化如下:

#import "FavoritesManager.h"

static FavoritesManager *sharedFavoritesManager = nil;

@implementation FavoritesManager

+ (id)sharedManager {
    @synchronized(self) {
        if (sharedFavoritesManager == nil) {
            sharedFavoritesManager = [[self alloc] init];
        }
    }

    return self;
}

这会返回一个对象,但由于某种原因它只会响应类方法。如果我调用实例方法,我会得到

+[FavoritesManager testMethod]: unrecognized selector sent to class 0x59198

对于它的价值,这就是testMethod的样子:

- (void)testMethod {
    NSLog(@"Test");
}

我非常肯定它在界面中声明了。我已经在其他课程中使用了这个确切的代码,它就像一个魅力,所以我真的不明白这里的问题是什么。有一件事是可疑的是+[FavoritesManager testMethod]中的加号,但我无法解释。有什么想法吗?

编辑:我混淆了公共/私人和类/方法术语。感谢所有指出这一点的人。

7 个答案:

答案 0 :(得分:6)

如果你想从另一个类方法调用testMethod,那么你需要:

+ (void)testMethod {
    NSLog(@"Test");
}

原因是如果你调用一个类方法,那么就没有实例,所以没有什么可以调用实例方法。但可能你想打电话:

[[FavoritesManager sharedManager] testMethod];

这意味着'获取共享实例,然后在其上调用testMethod。在我输入时,您可能还想添加:

+ (void)forwardInvocation:(NSInvocation *)anInvocation
{
    id sharedManager = [self sharedManager];

    if ([sharedManager respondsToSelector:
            [anInvocation selector]])
        [anInvocation invokeWithTarget:sharedManager];
    else
        [super forwardInvocation:anInvocation];
}

用于消息转发的Objective-C方法。因此,如果元类FavoritesManager收到无法响应的消息,它会让其共享管理器实例执行操作。这意味着:

[FavoritesManager testMethod];

在功能上等同于(虽然有点慢):

[[FavoritesManager sharedManager] testMethod];

假设除了实例方法之外还没有实现类方法。您可以在Apple's official documentation中了解有关邮件转发的详情。

答案 1 :(得分:4)

错误表示您正在向类中发送消息testMethod,而不是实例。

原因是您的sharedManager方法不正确。您当前正在返回self,在此类方法中,它是类本身。这意味着当您撰写[[FavoritesManager sharedManger] testMethod]时,您最终会向课程发送testMethod。由于testMethod不是类方法,因此会出错。

return sharedFavoritesManager;末尾应该有sharedManager,而不是return self;。后者仅在实例方法初始化器中正确。

另外,正如dbrajkovic评论的那样,你似乎对公共/私有和类/实例方法感到困惑。严格来说,ObjC没有私人方法。您可以隐藏声明,这将导致编译器警告,但仍将发送消息并调用该方法。 +-将类方法与实例方法区分开来;区别在于您向哪个对象发送消息。信息在这里:What is the difference between class and instance methods?

答案 2 :(得分:2)

错误是正确的,您必须调用[FavoritesManager testMethod],这意味着您正在尝试调用类方法。我相信你想要[[FavoritesManager sharedManager] testMethod];

答案 3 :(得分:1)

+在方法声明的开头意味着它是一个类方法, - 意味着它是一个实例方法。这样做:

+(void)testMethod {
    NSLog(@"Test");
}

如果要在sharedManager上调用testMethod,请保留testMethod声明,而不是将调用更改为

[[FavoritesManager sharedFavoritesManager] testMethod];

要么工作,要在两者之间进行选择是应用程序设计的问题。

答案 4 :(得分:1)

而是尝试

[[FavoritesManager sharedFavoritesManager] testMethod];

答案 5 :(得分:0)

obj-c中没有priavte方法。 但无论如何,在单身人士中,你总是从班级外部打电话,所以只宣称“公共方法”。有关发布代码的详细帮助。

答案 6 :(得分:0)

调用您的单例实例:

[[FavoritesManager sharedManager] testMethod];