Документы описывают - [UIView layoutSubviews] как
"Overridden by subclasses to layout subviews when layoutIfNeeded is invoked. The default implementation of this method does nothing."
Это описание не сложное, но точное. В этом случае поведение метода заключается в размещении ваших подпредставлений. Он будет вызываться каждый раз, когда изменяется ориентация устройства. Это также запланировано для последующего вызова всякий раз, когда вы вызываете -setNeedsLayout.
Поскольку реализация UIView ничего не делает (и я предполагаю, что то же самое для UIControl), вы получаете полную свободу творчества, чтобы размещать подвиды подкласса UIView в любом месте.
При создании подкласса UITableViewCell у вас есть несколько вариантов:
- Переопределить -layoutSubviews и
- манипулировать положением встроенных представлений textLabel и -detailLabel.
- Переопределить -viewDidLoad,
- создайте два собственных UILabels для предоставления текста и подробного текста,
- добавьте их в self.contentView и
- override -layoutSubviews для управления положением ваших пользовательских представлений UILabel
В связанном SO вопросе рекомендуется избегать # 1 манипулирования встроенными textLabel и detailTextLabel.
Более надежной ставкой было бы сделать что-то вроде этого:
@interface MyTableViewCell : UITableViewCell {
UILabel *myTextLabel;
UILabel *myDetailTextLabel;
}
// ... property declarations
@end
@implementation MyTableViewCell
@synthesize myTextLabel, myDetailTextLabel;
- (id) initWithFrame: (CGRect)frame {
self = [super initWithFrame: frame];
if (self) {
myTextLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
[self.contentView addSubview: myTextLabel];
myDetailTextLabel = [[[UILabel alloc] initWithFrame:CGRectZero] autorelease];
[self.contentView addSubview: myDetailTextLabel];
}
return self;
}
- (void) dealloc {
[myTextLabel release];
[myDetailTextLabel release];
[super dealloc];
}
- (void) layoutSubviews {
// Let the super class UITableViewCell do whatever layout it wants.
// Just don't use the built-in textLabel or detailTextLabel properties
[super layoutSubviews];
// Now do the layout of your custom views
// Let the labels size themselves to accommodate their text
[myTextLabel sizeToFit];
[myDetailTextLabel sizeToFit];
// Position the labels at the top of the table cell
CGRect newFrame = myTextLabel.frame;
newFrame.origin.x = CGRectGetMinX (self.contentView.bounds);
newFrame.origin.y = CGRectGetMinY (self.contentView.bounds);
[myTextLabel setFrame: newFrame];
// Put the detail text label immediately to the right
// w/10 pixel gap between them
newFrame = myDetailTextLabel.frame;
newFrame.origin.x = CGRectGetMaxX (myTextLabel.frame) + 10.;
newFrame.origin.y = CGRectGetMinY (self.contentView.bounds);
[myDetailTextLabel setFrame: newFrame];
}
@end
В MyTableViewCell вы игнорируете встроенные текстовые метки и используете свои собственные пользовательские метки UILabel. Вы полностью контролируете их размещение в прямоугольнике содержимого ячейки табличного представления.
Я оставляю много вещей вне. При создании пользовательского макета с текстовыми метками, вы должны учитывать:
Выяснение собственного алгоритма компоновки.
Я использую алгоритм макета выше, который изменяет размеры пользовательских UILabels, чтобы соответствовать их текстовому содержимому, а затем размещает их рядом. Вы, вероятно, захотите что-то более конкретное для своего приложения.
Сохранение пользовательских меток в представлении содержимого.
В -layoutSubviews вы, возможно, захотите, чтобы логика поддерживала размер и расположение пользовательских UILabel таким образом, чтобы они не выходили за границы прямоугольника содержимого. С моей наивной логикой компоновки любой длинный текст, помещенный в UILabel (или в оба), может привести к тому, что метки будут расположены прямо за пределами представления содержимого.
Как обрабатывать -viewDidLoad / -viewDidUnload.
Как написано выше, этот подкласс не обрабатывает загрузку с пера. Возможно, вы захотите использовать IB для разметки вашей ячейки, и если вам это нужно, вам нужно подумать о -viewDidLoad / -viewDidUnload / -initWithCoder: