IB и UIView. Как правильно загрузить иерархию представления из пера? - PullRequest
0 голосов
/ 06 октября 2009

Может кто-нибудь подскажет, как правильно загрузить иерархию представления из файла пера. Я использую загруженное представление в качестве шаблона, чтобы исключить семейство представлений, и текущий подход, который я использую, слегка нарушен. Кажется, я не копирую и не сохраняю, когда должен быть. Вот соответствующий код:

// pageSet is a list of view tag numbers I'll be using
for (NSNumber *n in pageSet) {

    NSUInteger viewTag = [n integerValue];

    // Ingest the nib. Should there be a copy or retain here?
    NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"RandomStripe" owner:self options:nil];

    // Pull the view from the nib. Should there be a copy or retain here?
    MyView *view = (MyView *)[topLevelObjects objectAtIndex:0];

    // The view has a label as it's subview
    UILabel *pageNumberLabel = [view.subviews objectAtIndex:0];
    pageNumberLabel.text     = [NSString stringWithFormat:@"%d", viewTag];

    CGFloat xOffset = ((float) viewTag) * self.scrollView.bounds.size.width;

    view.frame = CGRectMake(xOffset, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height);
    view.tag = viewTag;

    // Insert the view as a child of my containerView
    [self.containerView addSubview:view];

} // for (pageSet)

Это заставляет мою голову болеть?

Cheers, Дуг

Ответы [ 2 ]

2 голосов
/ 06 октября 2009

Если вы используете IBOutlets из Interface Builder обратно в свой код, все будет немного проще. Таким образом, как только вы пытаетесь получить доступ к настроенному вами выходу UIView, он загружается со всеми дочерними элементами, а затем вызывается initWithCoder из UIView (полезно, если вы его переклассифицировали).

@property (retain, nonatomic) IBOutlet iiView   *iiView;

В противном случае я делаю это:

if (self.numberView == nil) {
    NumberView  *numView = [[NumberView alloc] initWithNibName:@"NumberView" bundle:[NSBundle mainBundle]];
    self.numberView = numView;
    [numView release];
}

(С помощью IBOutlet для numberView я просто продолжаю и начинаю использовать numberView вместо приведенного выше кода)

В обоих условиях все подпредставления - дочерние элементы - numberView будут загружены одновременно. Если бы мне нужно было получить доступ к метке или кнопке, я бы тоже сделал для них IBOutlet, поэтому мне не придется пересматривать иерархию представлений, ища их.

IBOutlet UIButton *nextButton,
          *stopButton1,
          *stopButton2,
          *infoButton,
          *bitsonthegoButton;
IBOutlet UILabel *pointsLabel1,
         *pointsLabel2,
         *totalPointsLabel1,
         *totalPointsLabel2;
0 голосов
/ 06 октября 2009

Я не был уверен, что другой ответ был точно ясен в этом вопросе, но любой IBOutlets, который вы настроили на ваше представление, будет подключен с тем же loadNibNamed: вызов, который вы делаете сегодня. Таким образом, в заголовке этого представления вы должны объявить IBOutlets для myView и pageNumberLabel, а затем прикрепить их к владельцу файла в xib (и установить тип владельца файла в качестве представления, которое вы вызываете loadNibNamed: from).

Это просто, чтобы сделать вашу жизнь проще. Чтобы ответить на заданный вами вопрос, документация для «loadNibNamed: owner: options» сообщает нам:

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

Таким образом, массив автоматически освобожден, и все объекты в нем также (что можно ожидать от вызова, возвращающего автоматически освобожденный массив). Поскольку вы хотите сохранить представление, вы должны сохранить это - это будет означать, что любые подпредставления основного представления также будут сохраняться, поскольку представление будет сохранять все, что установлено в качестве подпредставления. Если вы также сохранили метку, которая может вызвать утечку при выходе из основного вида, если только вы не отпустите метку одновременно (но, похоже, в этом нет смысла).

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

Управление загрузкой пера на первый взгляд кажется сложным, но на самом деле правила намного проще, чем кажется.

...