Синглтон Objective C отвечает только на методы класса - PullRequest
0 голосов
/ 02 марта 2012

У меня есть одноэлементный класс, который создается следующим образом:

#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], но я не могу это объяснить.Есть идеи?

РЕДАКТИРОВАТЬ: Я путал терминологию public / private и class / method.Спасибо всем, кто указал на это.

Ответы [ 7 ]

6 голосов
/ 02 марта 2012

Если вы хотите вызвать 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 .

4 голосов
/ 02 марта 2012

Ошибка указывает, что вы отправляете сообщение testMethod классу, а не экземпляру.

Причина этого в том, что ваш sharedManager метод неверен.В настоящее время вы возвращаете self, который в этом методе класса является самим классом.Это означает, что когда вы пишете [[FavoritesManager sharedManger] testMethod], вы в конечном итоге отправляете testMethod в класс.Так как testMethod не является методом класса, вы получите ошибку.

В конце sharedManager должно быть return sharedFavoritesManager;, а не return self;.Последнее верно только в инициализаторах метода экземпляра.

Кроме того, как прокомментировал dbrajkovic, вы, похоже, не понимаете методы public / private и class / instance.Строго говоря, у ObjC нет частных методов.Вы можете скрыть объявление, которое вызовет предупреждение компилятора, но сообщение все равно будет отправлено и будет вызван метод.+ и - отличают методы класса от методов экземпляра;Различие заключается в том, на какой объект вы отправляете сообщение.Информация здесь: В чем разница между методами класса и экземпляра?

2 голосов
/ 02 марта 2012

Ошибка верна, вы должны вызывать [FavoritesManager testMethod], что означает, что вы пытаетесь вызвать метод классаЯ верю, что вы хотите [[FavoritesManager sharedManager] testMethod];

1 голос
/ 02 марта 2012

Вместо этого попробуйте

[[FavoritesManager sharedFavoritesManager] testMethod];
1 голос
/ 02 марта 2012

+ в начале объявления метода означает, что это метод класса, - означает, что это метод экземпляра.Сделайте это:

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

Если вы хотите вызвать testMethod в вашем sharedManager, сохраните объявление testMethod, как оно есть, и вместо этого измените ваш вызов на

[[FavoritesManager sharedFavoritesManager] testMethod];

Либо будет работатьи выбор между ними зависит от дизайна приложения.

0 голосов
/ 02 марта 2012

Вызовите ваш экземпляр синглтона:

[[FavoritesManager sharedManager] testMethod];

0 голосов
/ 02 марта 2012

нет методов priavte в obj-c. Но в любом случае для одиночного вызова вы всегда вызываете извне класса, поэтому объявляйте только «открытые методы» для подробной справки оставьте свой код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...