[英]Should we add UITableView in initializer or layoutsubviews method in iOS?
[英]iOS 7.1 UITableView layoutSubviews issue
我正在研究一個必須同時支持iOS 8和iOS 7.1的項目。 現在,我遇到一個僅在iOS 7.1上出現但在iOS 8上正常工作的問題。我有一個ViewController,它在tableHeaderView中包含一個表視圖和一個自定義視圖。 我將按以下方式發布代碼。 所有約束都以編程方式添加。
//查看控制器。
-(void)viewDidLoad
{
[super viewDidLoad];
self.commentsArray = [NSMutableArray new];
[self.commentsArray addObject:@"TEST"];
[self.commentsArray addObject:@"TEST"];
[self.commentsArray addObject:@"TEST"];
[self.commentsArray addObject:@"TEST"];
[self.commentsArray addObject:@"TEST"];
[self.commentsArray addObject:@"TEST"];
[self.view addSubview:self.masterTableView];
self.masterTableView.tableHeaderView = self.detailsView;
[self.view setNeedsUpdateConstraints];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.view layoutIfNeeded];
}
//Table view getter
- (UITableView *)masterTableView
{
if(!_masterTableView)
{
_masterTableView = [UITableView new];
_masterTableView.translatesAutoresizingMaskIntoConstraints = NO;
_masterTableView.backgroundColor = [UIColor greyColor];
_masterTableView.delegate = self;
_masterTableView.dataSource = self;
_masterTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_masterTableView.showsVerticalScrollIndicator = NO;
_masterTableView.separatorInset = UIEdgeInsetsZero;
}
return _masterTableView;
}
-(void)updateViewConstraints
{
NSDictionary *views = @{
@"table" : self.masterTableView,
@"details" : self.detailsView,
};
NSDictionary *metrics = @{
@"width" : @([UIScreen mainScreen].applicationFrame.size.width)
};
//Table view constraints
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[table]-0-|" options:0 metrics:0 views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[table]-0-|" options:0 metrics:0 views:views]];
//Details View
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[details(width)]-0-|" options:0 metrics:metrics views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[details]-0-|" options:0 metrics:metrics views:views]];
}
//Details View Getter
- (DetailsView *)detailsView
{
if(!_detailsView)
{
_detailsView = [[DetailsView alloc]initWithFrame:CGRectMake(0, 0, 0, 100)];
_detailsView.backgroundColor = [UIColor orangeColor];
return _detailsView;
}
現在,詳細信息視圖包含一些基本子視圖,這些子視圖均從UIView派生,而詳細信息視圖本身從更通用的超類派生。 我將按以下方式發布代碼。
//Parent View
@interface ParentView (): UIView
- (instancetype)init
{
self = [super init];
if (self)
{
[self setupViews];
}
return self;
}
- (void)setupViews
{
[self addSubview:self.publishedTimeView];
}
- (void)updateConstraints
{
NSDictionary *views = @{
@"time" : self.publishedTimeView,
};
// Header with published video time
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[time]-10-|" options:0 metrics:0 views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[time(11)]" options:0 metrics:0 views:views]];
[super updateConstraints];
}
//Getter for the timePublished view added to the detail view. Will not post all its related code for //the sake of brevity.
- (TimePublishedDetailView *)publishedTimeView
{
if(!_publishedTimeView)
{
_publishedTimeView = [TimePublishedDetailView new];
_publishedTimeView.translatesAutoresizingMaskIntoConstraints = NO;
}
return _publishedTimeView;
}
//Child View (or the detailsView) of the view controller.
@interface DetailsView : ParentView
@implementation RecordingDetailsView
- (void)updateConstraints
{
NSDictionary *views = @{
@"time" : self.publishedTimeView,
};
//Vertical alignment of all views
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[time]" options:0 metrics:nil views:views]];
[super updateConstraints];
}
- (void)setModel:(DetailViewModel *)model
{
self.publishedTimeView.date = model.dateTime;
[self setNeedsUpdateConstraints];
[self layoutSubviews];
}
現在在iOS 8上,它看起來像這樣:
但是在iOS 7.1上,這將崩潰並顯示以下錯誤消息:
“例外:執行-layoutSubviews之后仍然需要自動布局。UITableView的-layoutSubviews實現需要調用超級”
我已經對此進行了搜索,並在布局調用中使用了代碼,以查看是否可以解決該問題,但到目前為止仍未成功。 如果有人可以發布一些技巧或建議以解決此問題,我將不勝感激。
我知道這個問題很舊,但是最近我遇到了一個類似的問題,經過大量的Google搜索,嘗試和失敗,我在此答案和一些更改的幫助下使其起作用。
只需將此類別添加到您的項目中,然后調用[UITableView fixLayoutSubviewsMethod];
僅一次(我建議在AppDelegate
內部)。
#import <objc/runtime.h>
#import <objc/message.h>
@implementation UITableView (FixUITableViewAutolayoutIHope)
+ (void)fixLayoutSubviewsMethod
{
Method existing = class_getInstanceMethod(self, @selector(layoutSubviews));
Method new = class_getInstanceMethod(self, @selector(_autolayout_replacementLayoutSubviews));
method_exchangeImplementations(existing, new);
}
- (void)_autolayout_replacementLayoutSubviews
{
[super layoutSubviews];
[self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling
[super layoutSubviews];
}
@end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.