Objective-C - Работа с подпредставлениями - PullRequest
0 голосов
/ 29 сентября 2011

Я немного растерялся. Я создаю подкласс UITableViewCell, чтобы создать свой собственный дизайн ячейки. В методе -initWithStyle: я настраиваю некоторые UILabel s так:

self.careerTitleLabel = [[UILabel alloc] init];
[self.contentView addSubview:careerTitleLabel];
[self.careerTitleLabel release];

Затем, чтобы разместить метку, я делаю это в -layoutSubviews примерно так:

CGRect careerTitleLabelFrame = CGRectMake(10, 10, 280, 20);

self.careerTitleLabel.frame = careerTitleLabelFrame;

Этот код действительно работает. Он размещает мой ярлык там, где я хочу его разместить. Но то, что я не понимаю, это КАК это работает. Поскольку я просто изменяю фрейм ивара careerTitleLabel, а не карьерного заголовка, который был добавлен в качестве subView в contentView.

Я предполагаю, что для изменения фрейма метки, который я добавил в contentView, мне придется извлечь его с помощью -viewWithTag:, а затем изменить этот фрейм. Прямо сейчас я просто изменяю ивару класса?

P.S Еще один вопрос, не связанный с этим вопросом, - почему self.careerTitleLabel имеет retainCount, равный 2, после освобождения? D.S

Ответы [ 2 ]

3 голосов
/ 29 сентября 2011

addSubview: не копирует представление, которое вы передаете, оно сохраняет его. Поэтому, когда вы отпускаете его, он на самом деле не освобождается. Он остается в живых, потому что self.contentView все еще использует его. Это означает, что ваша ссылка на self.careerTitleLabel в дальнейшем все еще работает, хотя я думаю, что большинство сочло бы это плохим стилем на том основании, что вы должны продолжать владеть ссылками на любые объекты, которые вы намереваетесь отправить позже, а не навязывать знания из шаблонов собственности, используемых в других местах.

retainCount никогда не следует полагаться абсолютно. Также непрозрачно, насколько addSubview: увеличит количество сохраненных команд, в отличие от этого, оно будет как минимум 1. При этом наиболее вероятная причина, если вы объявили careerTitleLabel как свойство и у вас есть строка вроде:

NSLog(@"%d", [self.careerTitleLabel retainCount]);

Это стандартный получатель:

return [[careerTitleLabel retain] autorelease];

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

1 голос
/ 29 сентября 2011

careerTitleLabel - указатель на объект.Поэтому, когда вы делаете addSubview: careerTitleLabel, код, который вы вызываете, сохраняет ссылку на careerTitleLabel.

Позже, когда вы устанавливаете фрейм на careerTitleLabel в layoutSubviews, вы обновляете тот же объект.

layoutSubviews - абсолютно правильное место для этого.Он вызывается автоматически в начале и снова, если границы представления меняются.Например, если ориентация устройства изменяется.

viewWithTag - это еще один способ доступа к подпредставлению.Лично я считаю чище поддерживать ивару.Не забывайте, что вы можете использовать IBOutlets для подключения этих вещей с помощью Interface Builder.

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

В любом случае, вот в чем проблема:

self.careerTitleLabel = [[UILabel alloc] init];

Если ваше свойство в файле .h настроенокак:

@property (nonatomic, retain)

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

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

Намного безопаснее просто иметь:

    careerTitleLabel = [[UILabel alloc] init];

Еще лучше, в вашем .h файле префикс этого с «m» для переменной члена.Тогда у вас будет

    mCareerTitleLabel = [[UILabel alloc] init];

В вашем синтезе используйте:

    synthesize careerTitleLabel = mCareerTitleLabel;

Это будет означать, что извне - или изнутри - вашего кода, вы можете получить доступ к этому как:

    self.careerTitleLabel

или

    myObjectName.careerTitleLabel

Надеюсь, это поможет!Это много, чтобы покрыть!

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