Общий вопрос о методе класса Objective-C - PullRequest
1 голос
/ 16 января 2010

У меня есть приложение для iPhone, в котором есть несколько методов для сбора информации из Интернета, а затем создается объект, который хранит эту информацию в качестве свойств (скажем, я получу объекты типа x). Поскольку мне могут понадобиться такие объекты из разных точек приложения, я поместил метод для создания одного экземпляра объекта в один файл реализации и назвал этот файл «GetDetails.m» (+ h). В этом методе у меня есть исключительно методы класса * (среди тех, что я создал для создания объекта x), которые создают объект и заполняют его свойства информацией, которую метод собирает из Интернета.

+ (ObjX *)getObjectX:(NSString *key) withParameters:(NSArray *)parameters;

В рамках этого метода мой ObjX заполнен информацией ...

ObjX *objectX = [[ObjX alloc] init];
(...)
objectX.name = gatheredName;  // etc
(...)
return objectX;

Таким образом, мой метод класса вызывается в нескольких точках из приложения (между прочим, из отдельного потока):

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
ObjX *myObject;
myObject = [GetDetails getObjectX:@"09384f9a" withParameters:nil];
[self performSelectorOnMainThread:@selector(doStuffWithNewObject:) withObject:myObject waitUntilDone:NO];
[pool release];

Я не могу избавиться от ощущения, что этот подход не оптимален. Анализатор Xcode также сообщает мне, что при возврате objectX может возникнуть потенциальная утечка.

Может быть, кто-то может указать мне правильное направление и как мне следует разделить функциональные возможности в целом.

* У него также нет метода init и dealloc, нет иваров, нет методов экземпляра ...


Редактировать

Ладно, очевидно, что большинство не видят релиза для объекта, так что, думаю, я не совсем понял - объект будет выпущен позже после того, как он будет присвоен свойству вида. Тем не менее, я вижу, что это практика, чтобы вернуть автоматически освобожденный объект. К сожалению, мое приложение падает, когда я это делаю. Может быть, это из-за того, что я выполняю всю эту обработку в отдельном пуле потоков / авто-релизов? Я протестирую некоторые конфигурации и сообщу, как все прошло.

Ответы [ 3 ]

1 голос
/ 16 января 2010

Анализатор будет доставлять вам горе, потому что вы не autorelease свои объекты, когда вы возвращаете их. Обычный метод будет выглядеть следующим образом:

ObjX *objectX = [[ObjX alloc] init];
...
return [objectX autorelease];

Теперь, что касается реализации, это звучит как место для использования категорий. Я бы сделал что-то вроде этого:

GetDetails_ObjX.h

@interface ObjX (GetDetails)
+ (ObjX *)objXWithIdentifier:(NSString *)ident parameters:(NSArray *)params;
@end

GetDetails_ObjX.m

@implementation ObjX (GetDetails)
+ (ObjX *)objXWithIdentifier:(NSString *)ident parameters:(NSArray *)params
{
    ObjX *objectX = [[ObjX alloc] init];
    ...
    return [objectX autorelease];
}
@end

GetDetails.h

#import "GetDetails_ObjX.h"
#import "GetDetails_ObjY.h"
...

Эту настройку можно использовать следующим образом:

#import "GetDetails.h"
...
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
ObjX *myObject;
myObject = [ObjX objectXWithIdentifier:@"09384f9a" parameters:nil];
[self performSelectorOnMainThread:@selector(doStuffWithNewObject:)
                       withObject:myObject
                    waitUntilDone:NO];
[pool release];

Пара замечаний, здесь:

  1. Я использовал сигнатуру метода objXWithIdentifier..., потому что я не уверен, что строка @ "09384f9a" на самом деле равна . Если это адрес, вы должны использовать objXWithAddress.... Если это ссылочный номер, вы должны использовать objXWithReferenceNumber... и т. Д.

  2. Я должен был найти это, чтобы быть уверенным. Метод performSelectorOnMainThread... сохраняет свой аргумент, поэтому не нужно беспокоиться об освобождении объекта до вызова метода в основном потоке.

1 голос
/ 16 января 2010

Из Руководства по программированию управления памятью для какао : You own any object you create. You “create” an object using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy). Если ваш метод не начинается с какого-либо из этих префиксов, вы должны возвратить автоматически выпущенный объект. Затем вызывающий метод может сохранить объект, если его нужно хранить дольше.

1 голос
/ 16 января 2010

Одна вещь, которая меня бросает в глаза, это то, что каждый раз, когда вы вызываете метод класса, вы делаете:

ObjX *objectX = [[ObjX alloc] init];

Здесь вы создаете новый экземпляр какого-либо объекта. Однако ваш пример кода нигде не показывает, что вы его выпускаете. Помните, что alloc выделяет объекту счетчик ссылок на единицу. Далее, вызывая ваш метод getXXX, вы идете против соглашений об управлении памятью. это будет означать, что вы получаете ссылку на какой-то объект, который вам не принадлежит. Поскольку это не так, вам следует как минимум вызвать ваш метод newXXX или createXXX, чтобы указать, что этот вызывающий объект отвечает за выделенную память. Лучшим подходом было бы автоматически выпустить его и сохранить его у вызывающего абонента.

...