2009-11-05 2 views
3

Мне просто интересно, если это правильно, или плохая практика? (т. е. с помощью метода класса для размещения/инициализации экземпляра)? Также я прав, думая, что я должен освободить экземпляр в main(), поскольку это единственное место, где у меня есть доступ к указателю экземпляра?Выделение объектов из метода класса?

// IMPLEMENTATION 
+(id) newData { 
    DataPoint *myNewData; 
    myNewData = [[DataPoint alloc] init]; 
    return myNewData; 
} 

.

// MAIN 
DataPoint *myData; 
myData = [DataPoint newData]; 
... stuff 
[myData release]; 

EDIT:

Также следует

myNewData = [[DataPoint alloc] init]; 

быть (или это не имеет значения)

myNewData = [[self alloc] init]; 

EDIT_002:

Странно, когда я добавляю autorelease Я получаю ...

alt text

EDIT_003:

Делонг @ Dave, один последний вопрос, что ваше высказывание является его perferable к:

+(id) dataPoint { 
    return [[[self alloc] init] autorelease]; 
} 

вместо (где вы бы выпустить в основной)

+(id) new { 
    return [[self alloc] init]; 
} 

ура гари

+0

фрагменты авторезиста в коде выше (и в ответах) могут (и должны) быть удалены в коде ARC. – Snowcrash

ответ

14

В соответствии с условными обозначениями, вы должны называть его +dataPoint. Причина, по которой анализатор работает на вас, заключается в том, что (по соглашению) ожидается, что метод класса, который использует «новый», возвращает объект с сохранением +1. Вы возвращаете объект с +0 (автореализованным) счетом сохранения и, следовательно, нарушаете соглашение.

Как было указано в ответе @ Peter, чтобы создать пустой объект, обычно это делается с помощью методов [ClassName className]. Пример: [NSArray array], [NSData data], [NSString string] и т.д. Таким образом, правильная вещь для вас сделать, было бы переименовать его [DataPoint dataPoint], а затем реализовать его как return [[[self alloc] init] autorelease];

Использование [self alloc] предпочтительнее, так как он переводит вниз к подклассам. IE, если вы создаете подкласс MutableDataPoint, тогда (если вы используете [self alloc]), то [MutableDataPoint dataPoint] возвращает MutableDataPoint, тогда как если вы оставите его как [DataPoint alloc], он вернется как объект DataPoint (потому что это то, что вы выделяете). (На стороне записки, self относится к объекту, который оперированный в контексте методы для методов экземпляров, это экземпляр для методов класса, это сама Class объекта..)

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

Если вы хотите, чтобы метод класса возвращал объект со значением сохранения +1, а затем (по соглашению) вам просто нужно называть его +new (то есть DataPoint * p = [DataPoint new];). Однако использование метода +new, по-видимому, впало в более или менее неиспользование, причем +alloc/-init... или способ удобства класса являются благоприятными альтернативами.

Edit # 2 (Re: Edit_003):

Я лично предпочитаю бывшего (+dataPoint), но только потому, что +new не так часто и не нужно помнить, чтобы -release объекта. Однако любой из них является вполне приемлемым и правильным.

+0

@Dave Delong, большое вам спасибо, я не знал, что использование нового в этом контексте будет иметь такой эффект. Также я понимаю смысл использования себя. Большое спасибо, большое спасибо снова и вам, и всем, кто внес свой вклад. – fuzzygoat

+1

В третьем вопросе помните, что + [NSObject new] определен, и он вызывает + alloc/-init для вас и возвращает объект с сохранением +1. –

+0

@Quinn - спасибо, я забыл, что он уже был там! =) –

2

Ваш статический метод newData - это совершенно нормальная практика, и вы можете видеть подобные методы во всем API Cocoa (например, [NSString string] и [NSData data]).

Единственное, что вы должны делать (если вы не используете сборщик мусора) добавляет его в пул автономии. Соглашение заключается в том, что если вы получаете новый объект из alloc, new, copy или mutableCopy, вам нужно сохранить/освободить его самостоятельно. Если вы получаете объект с помощью любых других средств (которые ваш метод newData будет квалифицироваться как «другие средства»), то предполагается, что объект был добавлен в пул автозапуска, и вам не нужно самостоятельно управлять памятью.

Что касается [DataPoint alloc] против [self alloc], они оба скомпилированы и обе работают одинаково хорошо из того, что я могу сказать. Исходя из фона Java, я бы предложил [DataPoint alloc], так как вы находитесь в статическом контексте (self, похожий на java this, не должен существовать в нестационарном контексте). Конечно, я довольно новичок в Objective-C, а Objective-C не является Java ничем, поэтому ваше перемещение может отличаться.

+0

А я вижу, поэтому добавьте «авторекламу» в методе класса и удалите [myData release]; от основной. – fuzzygoat

+0

«Соглашение состоит в том, что если вы получаете новый объект из alloc, new, copy или mutableCopy, вам нужно его сохранить/освободить». - конечно, вам нужно только освободить его самостоятельно; Дело в том, что оно эффективно было сохранено для вас. С другой стороны, вам нужно сохранить объекты с автореализацией, которые вы хотите сохранить. – Nefrubyr

+0

@Nefrubyr, вы правы, alloc сохраняет это неявно, и вы несете ответственность за его освобождение. Я был непреднамеренно неоднозначным. – Peter

5

Вы можете написать это много опереться как;

+ (id)dataPoint { 
    return [[[MyDataPoint alloc] init] autorelease]; 
} 

Примечание: вы все равно должны написать метод init; такие методы класса обычно используются для удобства. Кроме того, если у вас нет GC, возвращаемое значение должно быть автореализовано в соответствии с правилами управления памятью.

Редактировать переименован в + dataPoint как исправлено Дейвом.

+0

Ack, эта ломается соглашение! Поскольку метод содержит «новый», анализатор ожидает, что значение +1 останется. –

1

EDIT_002:

Странно, когда я добавляю autorelease я получаю ...

Не странно вообще. Прочитайте то, что он говорит:

  1. Метод возвращает объект Objective-C с +1 сохранить счетчик (владеющей ссылкой)

    Вы назвали свой метод newData. Метод new возвращает ссылку на владение.

  2. Объект отправлено сообщение -autorelease

    Да. Прямо там.

  3. Объекта вернулся к абоненту, как и владение ссылки (одиночному сохранить счетчик передаваемого абонента)

    new метод (например, newData) возвращает владеющую ссылку, что означает вызывающее этого new метода получает владение ссылкой. Вызывающий должен владеть этим объектом. Вместо того, чтобы ...

  4. Объект возвращается к абоненту с +0 (без владеющим) сохраняют COUNT

    Вы autoreleased объект, отрицающий право собственности. Вы больше не возвращаете ссылку на владение, хотя вы и должны это делать. Это суммируется в последнем флаге:

  5. Объект с +0 сохраняет подсчет [так] вернулся к абоненту, где +1 (владеющий) сохраняет отсчет, как ожидается,

    Вызывающие следует ожидать собственный объект, поскольку он исходил из метода new, но это не так, потому что вы его автореализовали. Поскольку вызывающий объект считает, что он принадлежит этому объекту, он должен освободить его или авторейтировать позже, но поскольку вы уже это сделали, это будет чрезмерный выпуск.

Решение должно подчиняться соглашениям об именах какао и исправлять это нарушение ожидания. Это означает одно из двух решений:

  1. Храните имя как есть и не подвергайте автообновлению объекту.
  2. Измените имя метода таким образом, чтобы он не был методом new и автоматически удалял объект.

Я бы сделал # 2, так как это обычное дело и вообще меньше работает для звонящих.

+0

Спасибо, Питер, я на самом деле правильно это сделал в первый раз (просто случайно), я просто сделал выделение в методе, а затем выпустил в main() Теперь я понимаю, как это работает, и это имеет смысл, я просто не понимал что я испортил соглашение об именах и не понял, как это в свою очередь повлияло на авторекламу. Еще раз спасибо за то, что я поступил неправильно. Очень признателен. – fuzzygoat

Смежные вопросы