Разъяснение пользовательских методов / указателей init в целом для объектов c - PullRequest
2 голосов
/ 29 марта 2012

Когда у меня есть собственный метод инициализации с такими синтезированными свойствами:

@property (copy, nonatomic)   NSString       *bookName;
@property (strong, nonatomic) NSMutableArray *book;

Когда я хочу инициализировать с помощью своего собственного пользовательского инициализатора, мне показывают, что он напишет это так:

-(id) initWithName: (NSString *)name
{
    self = [super init]
    if (self) {
        bookName = [NSString stringWithString: name];
        book     = [NSMutableArray array];
    }
    return self;
}

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

self.bookName = name;

Для этого следует использовать синтезированный метод и фактически создать новый объект, верно? В основном оба выполняют одно и то же. Я спрашиваю, потому что есть методы, где это показывает, что они делают это обоими способами, поэтому я просто хочу убедиться, что нет других проблем, которые могут возникнуть при использовании того или иного способа. Похоже, что они оба делают одно и то же по-разному (используя синтезированный метод против прямого изменения переменной класса, но создавая для нее новый объект в памяти).

Я также укажу, что это в среде ARC.

Ответы [ 3 ]

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

(обратите внимание, что я предполагаю, что приведенный выше код ARC; в противном случае он неверен.)

Вы почти всегда должны использовать средства доступа для доступа к своим иварам (даже в ARC).Тем не менее, есть некоторые противоречия по поводу того, должен ли init использовать средства доступа или иметь прямой доступ к своим иварам.Я перешел на другую сторону в этом противоречии, но это не очевидное решение IMO.

Основной аргумент в пользу того, что init не может использовать средства доступа, заключается в том, что в будущем (неизвестный) подкласс может создатьэффекты в аксессоре.Обычно вы не хотите, чтобы побочные эффекты происходили во время вашего init.Например, вы, вероятно, не хотите публиковать уведомления об изменениях, когда устанавливаете что-либо на его начальное значение, и возможно, что ваш объект находится в «неопределенном состоянии» и в этом случае его было бы опасно читать.

Тем не менее, и хотя этот аргумент наконец-то меня поколебал, я ни разу не сталкивался с такой ситуацией в многочисленных проектах разных размеров с несколькими командами.Я много раз сталкивался с ошибками разработчиков retain при установке их иваров в init (как вы делали выше, и которые вылетали бы, если это не ARC).Вот почему я долгое время рекомендовал использовать аксессоры даже в init.Но в теории это создает опасность, особенно если вы пишете фреймворк с закрытым исходным кодом (например, Apple).Итак, для моего собственного кода я теперь избегаю доступа в init.Если бы я работал с более младшими командами над старым кодом сохранения / выпуска, я бы, вероятно, все равно использовал их в init.В моем опыте удалось избежать стольких сбоев.

Однако не вызывает сомнений то, что вам следует избегать вызова методов доступа в dealloc.Это определенно может привести к причудливым побочным эффектам в середине разрушения вашего объекта.

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

Поскольку объявленное свойство равно copy, тогда да, они делают то же самое.

Однако во многих случаях это strong, и тогда между этими двумя методами будет разница, поэтому первый метод будет "правильным" способом сделать это.

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

Вы правы, поскольку bookName объявлен как copy, присвоение self.bookName сделает копию переданной строки. Я не уверен, что копирование будет проходить точно так же Путь к коду как [NSString stringWithString: name], но он достиг бы той же цели, создавая копию исходной строки, защищая вас от непредвиденных последствий, когда пользователи передавали изменяемый объект и изменяли его значение за вашей спиной.

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