2013-03-19 3 views
1

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

Так, например, в UIViewController подкласс мой код будет выглядеть примерно так:

-(id)initWithValue:(int)val { 
    self.value = val; 
    return [self initWithNibName:nil bundle:nil]; 
} 

где value представляет собой целое число, которое принадлежит к этому ViewController подкласса, и, как правило, больше значения, чем это.

Однако в последнее время я начал сначала настраивать себя, потому что думал, что self = [self init...] заменит текущий экземпляр класса, и, таким образом, я потеряю этот экземпляр себя. Итак, я начал делать:

-(id)initWithValue:(int)val { 
    self = [self initWithNibName:nil bundle:nil]; 
    self.value = val; 
    return self; 
} 

Затем я недавно проверил оригинальную версию и понял, что все работает должным образом, и изменение было ненужно.

Итак, мой вопрос заключается в следующем:

  1. Что делает [супер initWithNibName: расслоение:] сделать, создающее это создать объект, но не заменить исходный объект?
  2. Является ли одна из двух версий лучше, чем другая, или они оба эквивалентны? Если лучше, что нужно использовать?

Спасибо, продвинутый!

ответ

0

Первый код, который вы написали, не сохранит value, потому что перед созданием объекта вы пытаетесь сохранить данные. Но, второй код, требуется небольшая модификация для лучшей практики, т.е., как это ...

-(id)initWithValue:(int)val { 
    self = [self initWithNibName:nil bundle:nil]; 

    if(self) 
    _value = val; 

    return self; 
} 

Надеется, что это полезно для вас ... :-)

+0

Вот что я подумал, но я попытался установить значения, а затем выполнил 'self = [self initWithNibName: bundle:]', затем распечатал значения, и они были верны. Я предполагаю, что я не всегда будет изменен, но, как правило, безопаснее делать это по-своему. – Jsdodgers

+0

Кроме того, спасибо за отзыв о '_value'. Просто чтобы убедиться, что я это понимаю, при использовании '_value',' [self setValue:] 'не будет вызван, правильно? И если это так, единственная причина не использовать self.value или есть другой? – Jsdodgers

+0

Значение является свойством в вашем случае, поэтому при синтезе используйте этот стандартный код ... @synthesize value = _value; Вы также можете получить значение с помощью [self setValue:]. –

1

Пожалуйста, используйте следующий код переопределить метод инициализации

-(id)initWithValue:(int)val 
{ 
    self = [super init]; 
    if(self) 
    { 
    self.value = val; 
    } 

    return self; 
} 
0

кнопку [супер initWithNibName: расслоение:] на самом деле вызвать метод суперкласса. , если вы используете [self initWithNibName: bundle:], на самом деле это вызовет переписывание initWithNibName: bundle: конечно, вы должны переписать его, иначе он также вызовет метод суперкласса. поэтому, если вы хотите выполнить некоторую инициализацию в перезаписи initWithNibName, вы можете использовать [self initWithNibName: bundle:], но если вам не нужна дополнительная инициализация, нет никакой разницы между методом;

2

Вы должны сделать это следующим образом:

- (id)initWithValue:(int)val { 
    self = [super initWithNibName:nil bundle:nil]; 
    if (self) { 
     _value = val; 
    } 
    return self; 
} 

В прошивке, общая картина возвращать ноль, если параметры посланных инициализаций методов, являются недействительными. Значение будет одной из двух вещей: текущий указатель на себя или ноль. Если вызов super возвращает nil, тогда объект не был настроен правильно, поэтому вы также должны вернуть нуль.Выполнение self = [super initWithNibName: nil bundle: nil]; просто упрощает уважение возможного значения nil, возвращаемого супер

+0

Обратите внимание, что это действительно отлично для возврата другого объекта (не 'nil' или текущего значения' self') из метода 'init'. Это делается для того, чтобы заменить существующий объект новым, возможно, одним, загруженным из ниба, или одного из определенного подкласса, или одноэлементным. Вы должны немедленно сохранить этот объект в 'self' и использовать его вместо исходного экземпляра во время остальной части вашего' init' метода. –

+0

Обычно они называются кластерными классами, и по этой причине не следует подклассифицировать их. сам, скорее всего, станет другим типом подкласса суперкласса, поэтому доступ к методам и переменным экземпляра, определяемым в текущем классе, приведет к тому, что EXC_BAD_ACCESS –

+0

Ник, кластеры классов являются лишь одним из * многих причин, по которым суперкласс может вернуть другой экземпляр от '-init'. См. Статью Майка Эша [«Как и почему инициаторы какао») (http://www.mikeash.com/pyblog/the-how-and-why-of-cocoa-initializers.html) и, в частности, раздел «Миф/Факт» , Больше подробностей. –

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