Методы класса, которые создают новые экземпляры - PullRequest
20 голосов
/ 13 мая 2011

Помимо стандартного шаблона [[MyClass alloc] init], некоторые объекты создаются из статических методов, таких как MyClass *obj = [MyClass classWithString:@"blabla"]

. Согласно широко распространенным руководствам по управлению памятью (включая Apple), вы несете ответственность только за освобождение объектов, которыеВы alloc.

Может кто-нибудь предоставить мне шаблон для таких методов?Как вы возвращаете выделенный объект ([self alloc]; return self;, возможно)?Как вы убедитесь, что он будет выпущен?

Ответы [ 4 ]

48 голосов
/ 13 мая 2011

Это классовые методы, а не статические 1 . Этот конкретный тип, создающий автоматически выпущенные объекты, может называться «фабричными методами» (ранее также «удобными конструкторами»), и они обсуждаются в Концепциях в Руководстве ObjC . Они идут примерно так:

+ (instancetype)whatsisWithThingummy: (Thingummy *)theThingummy {
    return [[self alloc] initWithThingummy:theThingummy];
}

Где Whatsis - ваш класс, а Thingummy - другой класс, используемый вашим классом.

Если вы не компилируете с ARC, существует соглашение autorelease к экземпляру перед его возвратом.

Ключевое слово instancetype было введено Clang для таких методов; в сочетании с self (который является объектом класса сам по себе 2 в методе класса) он обеспечивает правильное поведение подкласса: метод создает экземпляр класса, получившего сообщение. 3 instancetype позволяет компилятору выполнять более строгую проверку типов, чем id.

Иллюстрация такого использования в подклассах из фреймворка: +[NSString stringWithFormat:] возвращает экземпляр NSString, тогда как +[NSMutableString stringWithFormat:] возвращает экземпляр подкласса NSMutableString, без необходимости NSMutableString явно переопределять метод .

Как обсуждалось в документе [ Основы ] [1], существуют и другие способы использования этих заводских методов, такие как доступ к одноэлементному протоколу или оценка необходимого выделения памяти перед его выполнением (возможно, но меньше удобно , со стандартной парой alloc / init.


1"Статические методы" в Java или C ++, "Методы класса" в Objective-C. В ObjC не существует статических методов

2 Принимая во внимание, что в методе экземпляра self разумно является ссылкой на экземпляр.

3 Ранее подобно обычным методам инициализации (initWith...), вы бы использовали id в качестве возвращаемого типа. Использование определенного имени класса излишне заставляет подклассы переопределять метод.

4 голосов
/ 13 мая 2011

Объекты, возвращаемые фабричными методами, должны быть автоматически освобождены, то есть они будут очищены при сливе соответствующего пула автоматического выпуска.Это означает, что вы не являетесь владельцем возвращаемых объектов, если вы не copy или retain их.Ниже приведен пример фабричного метода:

+ (id)myClassWithString:(NSString *)string {
    return [[[MyClass alloc] initWithString:string] autorelease];
}
2 голосов
/ 13 мая 2011

Эти методы просто возвращают автоматически выпущенную версию объекта.

+(MyClass*)class
{
  MyClass* object = [[MyClass alloc] init];
  return [object autorelease];
}
1 голос
/ 16 июля 2013

Современный способ сделать это с ARC и новейшим компилятором:

+ (instancetype) myClassWithString:(NSString *)string {
     return [[MyClass alloc] initWithString:string];
}
  • Нет необходимости автоматического выпуска с ARC.
  • instancetype обеспечивает лучшую проверку времени компиляции, делая возможным создание подклассов.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...