2012-05-28 2 views
1

Если у меня есть свойство, скажем, в NSArray, что собирается быть инициализирован только один раз для каждого экземпляра моего класса, есть что-то не так с этим:Неправильно ли устанавливать свойство в методе геттера?

(в интерфейсе)

@property(strong, nonatomic)NSArray *bubbleArr; 

(в реализации)

-(NSArray*)bubbleArr 
{ 
    if(!bubbleArr) 
    { 
     NSMutableArray *tempBubbArr = [[NSMutableArray alloc] init]; 
     // get filepath for first speech bubble image for page 
     NSString *speechBubbleImgPath = [[NSBundle mainBundle] pathForResource: 
             [NSString stringWithFormat:@"speech_%i_0", pageIndex] 
                     ofType:@"png"]; 

     for(int i = 1; speechBubbleImgPath; i++) 
     { 
      UIImage *speechBubbleImg = [[UIImage alloc] initWithContentsOfFile:speechBubbleImgPath]; 
      UIImageView *speechBubbleImgView = [[UIImageView alloc] initWithImage:speechBubbleImg]; 

      [tempBubbArr addObject:speechBubbleImgView]; 

      speechBubbleImg = nil; 
      speechBubbleImgView = nil; 
      speechBubbleImgPath = nil; 

      speechBubbleImgPath = [[NSBundle mainBundle] pathForResource: 
            [NSString stringWithFormat:@"speech_%i_%i", pageIndex, i] 
                    ofType:@"png"]; 
     } 

     bubbleArr = [[NSArray alloc] initWithArray:tempBubbArr]; 

     tempBubbArr = nil; 
    } 

    return bubbleArr; 
} 

Я никогда не использовал пользовательские методы доступа, но это похоже на чистый способ, чтобы установить его, так что я не должен настроить каждое свойство в моем viewDidLoad или в другом месте, и не нужно беспокоиться о i t nil. Я не помню, чтобы на самом деле приходил код, который делает это. Это рекомендуемый способ сделать это? Кроме того, я всегда хочу использовать self.bubbleArr, чтобы убедиться, что этот метод вызывается, не так ли?

+1

сторона примечание: имейте в виду, что если вы не используете ARC, ваш код выше утечки – Sean

+2

Посмотрев на код, я предполагаю, что вы не хотите, чтобы ссылка на массив была изменена, поскольку она является разовой настроить. Вы можете подумать о том, чтобы сделать это «readonly' свойство, чтобы это сделать. Иначе код вроде 'object. bubbleArr = [[NSArray alloc] init] '; может испортить вещи. – Anurag

+2

Абсолютно ничего плохого в использовании ленивой техники инициализации внутри геттера. Однако для свойства, отличного от readonly, вы должны быть уверены, что установщик правильно знает, как все работает, и если асинхронный доступ (многопоточность) - это возможность, вы должны учитывать это как в getter, так и в setter. (Я не пытался анализировать/критиковать вашу реализацию.) –

ответ

2

Это полностью действующий способ настройки вашего имущества. Apple делает это очень часто в своем примере кода, а также в своих шаблонах проектов. Посмотрите, например, на настройку стека основных данных во вновь созданный проект iOS с базовыми данными. Как отметил @WendiKidd, вам нужно постоянно обращаться к своей переменной через аксессоров, чтобы убедиться, что это работает хорошо (что, вероятно, и должно быть в любом случае).

В частности, это хороший способ реализовать свойство класса, которое действительно может вернуть только одно (что, по вашему мнению, похоже на то, что вы пытаетесь сделать). Если это ваша цель, вот некоторые руководящие принципы, чтобы следовать:

  1. Объявите вашу собственность как readonly
  2. Объявить его в общественном заголовке, если оно должно быть доступным для общественности, или в расширении класса в.m файл, если он должен быть «частным»
  3. Если он может/должен быть подкреплен переменной, синтезируйте ivar и перезапишите получателя, как вы это сделали
  4. Если это не должно/не должно быть подкреплен переменной, объявите свойство, как @dynamic в реализации и перезаписать поглотитель
  5. доступ только ваш Ивар через аксессору

Декларирование переменную как динамический в 4-ом пункте будет сигнализировать для всех, кто смотрит на ваш кода, который, скорее всего, написал пользовательский аксессуар для этого свойства.

+0

Не нужно объявлять как @dynamic для переопределения getter ... – bbum

+0

@bbum - Очень верно. Я делаю это как напоминание себе, что я переопределил аксессуры, не синтезируя ивара. Я полагаю, что это действительно вопрос личного вкуса ... – Sean

+0

Я не думаю, что точка 1 - это все, что действительно, так как часто бывает удобно загружать объект по умолчанию, если он не был специально настроен и назначен. –

1

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

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

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

+0

Я не знаю, что они гарантированно будут init или ноль, но я никогда не видел случая, когда этого не происходит. –

+2

http://stackoverflow.com/questions/990817 - далее, это довольно распространено, и любой будущий сопровождающий должен знать об идиоме. Также принято называть переменную экземпляра '_bubbleArr' защитой от случайного обращения к переменной экземпляра напрямую. –

+0

@IanHenry И есть это любопытство! Благодаря! Очень хорошо знать :) – WendiKidd

0

Да, если вы не используете self.bubbleArray OR [self bubbleArray], вы не будете использовать этот метод.

Кроме этого, это прекрасный способ управления созданием объекта.

0

Кажется, что это чистое решение, оно немного похоже на ленивую загрузку. Но я не уверен, что сделаю это так.

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