2012-10-26 20 views
37

Tôi đã tự hỏi liệu có ai biết lý do tại sao khi bạn đặt khung của một chế độ xem phụ trong viewDidLoadviewWillAppear các thay đổi không ảnh hưởng đến màn hình, nhưng nếu bạn đặt nó ở viewDidAppear thì sao?Không thể đặt khung chính xác trước khi xemDidAppear

Trong trường hợp của tôi, tôi đang tải xib tùy chỉnh với hai lần xem bảng rồi cố gắng chuyển chúng xuống viewDidLoad để cho phép không gian cho một chế độ xem khác được thêm vào viewDidLoad vì không phải lúc nào cũng cần thiết để hiển thị nó.

Vấn đề là khi tôi đặt khung ở viewDidLoad hoặc viewWillAppear nó được đặt trên đối tượng, tôi có thể thấy bằng cách in ra, nhưng nó không được phản ánh trên màn hình. Di chuyển các cuộc gọi khung đã đặt thành viewDidAppear sẽ khiến mọi thứ hoạt động như mong đợi.

Có sai khi nghĩ rằng tôi có thể đặt khung ở viewDidLoad không?

- (id)init { 
    if (self = [super initWithNibName:@"MyView" bundle:nil]) {} 

    return self; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    self.descriptionWebView = [[[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)] autorelease]; 

    [self.view addSubview:self.descriptionWebView]; 

    self.tableView1.autoresizingMask = UIViewAutoresizingNone; 
    self.tableView2.autoresizingMask = UIViewAutoresizingNone; 

    [self.descriptionWebView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"...." withExtension:@"html"]]]; 

    table1LocationWithHeader = CGRectMake(self.tableView1.frame.origin.x, 200, self.tableView1.frame.size.width, self.tableView1.frame.size.height - 200); 
    table2LocationWithHeader = CGRectMake(self.tableView2.frame.origin.x, 200, self.tableView2.frame.size.width, self.tableView2.frame.size.height - 200); 

    //this will NOT work 
    self.tableView1.frame = table1LocationWithHeader; 
    self.tableView2.frame = table2LocationWithHeader; 
} 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 

    //this will NOT work 
    self.tableView1.frame = table1LocationWithHeader; 
    self.tableView2.frame = table2LocationWithHeader; 
} 


- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 

    //this WILL work 
    self.tableView1.frame = table1LocationWithHeader; 
    self.tableView2.frame = table2LocationWithHeader; 
} 


//I added these after comments for stack overflow users, it seems like viewDidLayoutSubviews is the best place to set the frame 

- (void)viewWillLayoutSubviews { 
    [super viewWillLayoutSubviews]; 

    //this will NOT work 
    self.tableView1.frame = table1LocationWithHeader; 
    self.tableView2.frame = table2LocationWithHeader; 
} 

- (void)viewDidLayoutSubviews { 
    [super viewDidLayoutSubviews]; 

    //this WILL work 
    self.tableView1.frame = table1LocationWithHeader; 
    self.tableView2.frame = table2LocationWithHeader; 
} 
+0

Bạn có thể hiển thị mã của mình không? – Nekto

+2

có thể trùng lặp của [UIViewController trả về khung không hợp lệ?] (Http://stackoverflow.com/questions/9539676/uiviewcontroller-returns-invalid-frame) –

+0

NB! ViewWillAppear của bạn gọi '[super viewDidAppear];' Có vẻ như lỗi sao chép-dán. – Speakus

Trả lời

93

viewDidLoad được gọi khi lớp được nạp tuy nhiên không có yếu tố ui đã được khởi tạo và do đó bất kỳ nỗ lực để tham khảo họ sẽ được ghi đè hoặc unavaliable trong quá trình khởi động mà xảy ra giữa viewDidLoad và viewDidAppear gọi. Một khi tất cả các phần tử ui đã được initalised và rút ra viewDidAppear được gọi.

viewDidLoad - Được gọi là sau khi quan điểm của bộ điều khiển được nạp vào bộ nhớ

Tại thời điểm này quan điểm không nằm trong hệ thống phân cấp xem.

viewWillAppear - Thông báo cho trình điều khiển chế độ xem mà khung nhìn của nó sắp được thêm vào phân cấp khung nhìn.

Một lần nữa, chế độ xem vẫn chưa được thêm vào phân cấp chế độ xem.

chế độ xemDidAppear - Thông báo cho trình điều khiển chế độ xem mà chế độ xem của nó đã được thêm vào phân cấp chế độ xem.

Chỉ sau đó là chế độ xem được thêm vào phân cấp chế độ xem.

Cập nhật

Các viewDidLayoutSubviews là nơi thích hợp nhất để thay đổi giao diện người dùng trước khi nó thực sự xuất hiện trên màn hình.

chế độ xemDidLayoutSubviews - Thông báo cho trình điều khiển chế độ xem mà chế độ xem của nó vừa trình bày các bản xem con của nó.

+0

Được rồi, vì vậy viewDidLoad và viewWillAppear khá đơn giản là nơi sai để cố gắng sửa đổi khung. Có lẽ vị trí chính xác để đặt khung hình thực sự trong khung nhìn ViewWill/DidLayoutSubviews mà tôi vừa thấy trong câu hỏi được liên kết bởi Rob, vì viewDidAppear dường như đã quá muộn để sửa đổi khung. Tôi sẽ thử nó và xem nó có hoạt động không. – nacross

+8

Tôi vừa thử và xemDidLayoutSubviews có vẻ như là nơi tốt nhất để đặt khung. Cảm ơn vì đã giúp tôi làm rõ điều đó. – nacross

+0

Điều này không thực sự giải thích tại sao đặt giá trị khung trong 'viewDidLoad' không hoạt động. Tôi thực sự thiết lập các khung trong 'viewDidLoad' rất thường xuyên không bao giờ có một vấn đề với nó. – Sulthan

2

Xem chủ đề này When is layoutSubviews called?
Khi sử dụng autolayout, framework không gọi layoutSubviews tự động. Điều đó rất quan trọng.Từ ref:

  • init không gây layoutSubviews được gọi là (duh)
  • addSubview: gây layoutSubviews được gọi là trên quan điểm được bổ sung, quan điểm nó được thêm vào (xem mục tiêu), và tất cả các subviews của mục tiêu. ...


Nếu bạn thêm chế độ xem phụ trong chế độ xemDidLoad, layoutSubviews được gọi trước viewDidAppear và bạn có thể nhận được kích thước chính xác của các bản xem trước. Nhưng nếu bạn không làm gì cả, layoutSubviews sẽ được gọi sau khi viewDidAppear. Nó thuộc vào mã của bạn.

0

trong viewWillAppear()

chỉ cần gọi layoutIfNeeded() một lần cho xem mà khung bạn muốn nhận được.

nếu tableView sau đó tableView.layoutIfNeeded() cho exmple