Tìm hiểu về vòng đời của UIViewControll trên iOS


299

Bạn có thể giải thích cho tôi cách chính xác để quản lý UIViewControllervòng đời?

Đặc biệt, tôi muốn biết làm thế nào để sử dụng Initialize, ViewDidLoad, ViewWillAppear, ViewDidAppear, ViewWillDisappear, ViewDidDisappear, ViewDidUnloadDisposephương pháp trong Mono Touch cho một UIViewControllerlớp.


Có một số thông tin hoặc liên kết cho OSX ViewControll và WindowContoder không? Xin hãy chia sẻ nó.
Anoop Vaidya

Câu trả lời:


410

Tất cả các lệnh này được iOS tự động gọi vào thời điểm thích hợp khi bạn tải / trình bày / ẩn bộ điều khiển xem. Điều quan trọng cần lưu ý là các phương pháp này được gắn liền UIViewControllervà không gắn với UIViewchính chúng. Bạn sẽ không nhận được bất kỳ tính năng nào trong số này chỉ bằng cách sử dụng a UIView.

Có tài liệu tuyệt vời trên trang web của Apple ở đây . Đưa vào đơn giản mặc dù:

  • ViewDidLoad- Được gọi khi bạn tạo lớp và tải từ xib. Tuyệt vời cho thiết lập ban đầu và chỉ làm việc một lần.

  • ViewWillAppear- Được gọi ngay trước khi chế độ xem của bạn xuất hiện, tốt cho việc ẩn / hiển thị các trường hoặc bất kỳ thao tác nào bạn muốn xảy ra mỗi lần trước khi chế độ xem hiển thị. Vì bạn có thể quay lại giữa các chế độ xem, nên điều này sẽ được gọi mỗi khi chế độ xem của bạn sắp xuất hiện trên màn hình.

  • ViewDidAppear - Được gọi sau khi chế độ xem xuất hiện - nơi tuyệt vời để bắt đầu hoạt hình hoặc tải dữ liệu ngoài từ API.

  • ViewWillDisappear/ DidDisappear- Cùng ý tưởng với ViewWillAppear/ ViewDidAppear.

  • ViewDidUnload/ ViewDidDispose- Trong Objective-C, đây là nơi bạn thực hiện việc dọn dẹp và giải phóng công cụ, nhưng việc này được xử lý tự động nên bạn không thực sự cần phải làm gì ở đây.


86
Văn bản này hơi sai lệch, vì ViewDidLoad không nên được sử dụng cho công việc một lần duy nhất. Nó có thể được gọi nhiều lần nếu chế độ xem không được tải do bộ nhớ thấp và sau đó được tải lại.
Ricky Helgesson

4
ViewDidLoad không thực sự được gọi khi bạn tạo / khởi tạo trình điều khiển xem. Nó được gọi là lần đầu tiên bạn thực hiện bất kỳ chế độ xem nào liên quan đến chế độ xem của trình điều khiển chế độ xem. Giống như thêm nó dưới dạng một khung nhìn phụ, đặt khung, v.v ... Nó cũng được gọi là tất nhiên khi tải từ ngòi.
Jason Grandelli

3
ViewDidAppear - Được gọi sau khi chế độ xem xuất hiện - nơi tuyệt vời để bắt đầu hoạt hình hoặc tải dữ liệu ngoài từ API. Tại sao nó là một nơi tốt để bắt đầu tải dữ liệu? Tại sao không xemDidLoad?
Anton Chikin

1
Còn phương thức loadView thì sao, nếu nó được gọi lần đầu tiên khi một nib được tải trong bộ nhớ trước viewDidLoad hay không.
iHulk

@chakrit đây là một điểm tốt - viewDidAppear là một nơi tuyệt vời để làm mới dữ liệu (nếu bạn cần). Tôi không đồng ý về KVO, vì nó có thể gây ra những làm mới không mong muốn trên các chế độ xem mà người dùng không bao giờ thực sự xem.
Anton Chikin

409

CẬP NHẬT: ViewDidUnload không được dùng trong iOS 6, vì vậy đã cập nhật câu trả lời tương ứng.

Vòng đời của UIViewControll được sơ đồ hóa ở đây:

Vòng đời của bộ điều khiển xem, được lập sơ đồ

Ưu điểm của việc sử dụng Xamarin Native / Mono Touch là nó sử dụng các API gốc và do đó, nó tuân theo vòng đời ViewContoder giống như bạn thấy trong Tài liệu của Apple.


17
Trường hợp viewWillLayoutSubview và viewDidLayoutSubview đi đâu trong sơ đồ này?
Max_Power89

7
Sơ đồ này không chính xác. viewDidUnload bị phản đối từ iOS6: stackoverflow.com/questions/12509102/...
occulus

2
Điều này thực sự đơn giản là sai . Một ví dụ khác về một câu trả lời sai đơn giản về SO, khi năm tháng trôi qua. Máy tính rất không tĩnh.
Fattie

186

Đây là phiên bản iOS mới nhất (Được sửa đổi bằng Xcode 9.3, Swift 4.1 ). Dưới đây là tất cả các giai đoạn làm cho vòng đời UIViewControllerhoàn thành.

  • loadView()

  • loadViewIfNeeded()

  • viewDidLoad()

  • viewWillAppear(_ animated: Bool)

  • viewWillLayoutSubviews()

  • viewDidLayoutSubviews()

  • viewDidAppear(_ animated: Bool)

  • viewWillDisappear(_ animated: Bool)

  • viewDidDisappear(_ animated: Bool)

Hãy để tôi giải thích tất cả các giai đoạn.

1. loadView

Sự kiện này tạo / tải chế độ xem mà bộ điều khiển quản lý. Nó có thể tải từ một tệp nib liên quan hoặc trống UIViewnếu null được tìm thấy. Điều này làm cho nó trở thành một nơi tốt để tạo các khung nhìn của bạn trong mã theo chương trình.

Đây là nơi các lớp con sẽ tạo cấu trúc phân cấp chế độ xem tùy chỉnh nếu chúng không sử dụng ngòi. Không bao giờ nên được gọi trực tiếp. Chỉ ghi đè phương thức này khi bạn lập trình tạo các khung nhìn và gán chế độ xem gốc cho thuộc viewtính Đừng gọi siêu phương thức khi bạn ghi đè loadView

2. loadViewIfNeeded

Nếu chế độ xem hiện tại viewControllerchưa được đặt thì phương thức này sẽ tải chế độ xem nhưng hãy nhớ, điều này chỉ khả dụng trong iOS> = 9.0. Vì vậy, nếu bạn đang hỗ trợ iOS <9.0 thì đừng hy vọng nó sẽ xuất hiện trong ảnh.

Tải chế độ xem của trình điều khiển xem nếu nó chưa được đặt.

3. viewDidLoad

Sự viewDidLoadkiện chỉ được gọi khi chế độ xem được tạo và tải vào bộ nhớ nhưng giới hạn cho chế độ xem chưa được xác định. Đây là một nơi tốt để khởi tạo các đối tượng mà trình điều khiển khung nhìn sẽ sử dụng.

Được gọi sau khi xem đã được tải. Đối với các bộ điều khiển xem được tạo trong mã, đây là sau -loadView. Đối với các bộ điều khiển chế độ xem không được lưu trữ từ ngòi, đây là sau khi chế độ xem được đặt.

4. viewWillAppear

Sự kiện này thông báo viewControllerbất cứ khi nào chế độ xem xuất hiện trên màn hình. Trong bước này, khung nhìn có các giới hạn được xác định nhưng hướng không được đặt.

Được gọi khi chế độ xem sắp hiển thị. Mặc định không có gì.

5. viewWillLayoutSubviews

Đây là bước đầu tiên trong vòng đời mà giới hạn được hoàn thành. Nếu bạn không sử dụng các ràng buộc hoặc Bố cục tự động, có lẽ bạn muốn cập nhật các bài phỏng vấn ở đây. Điều này chỉ khả dụng trong iOS> = 5.0. Vì vậy, nếu bạn đang hỗ trợ iOS <5.0 thì đừng hy vọng nó sẽ xuất hiện trong ảnh.

Được gọi ngay trước khi phương thức layoutSubview của trình điều khiển khung nhìn được gọi. Các lớp con có thể thực hiện khi cần thiết. Mặc định là một nop.

6. viewDidLayoutSubviews

Sự kiện này thông báo cho bộ điều khiển xem rằng các cuộc phỏng vấn đã được thiết lập. Đó là một nơi tốt để thực hiện bất kỳ thay đổi cho các cuộc phỏng vấn sau khi chúng đã được thiết lập. Điều này chỉ khả dụng trong iOS> = 5.0. Vì vậy, nếu bạn đang hỗ trợ iOS <5.0 thì đừng hy vọng nó sẽ xuất hiện trong ảnh.

Được gọi ngay sau khi phương thức layoutSubview của trình điều khiển khung nhìn được gọi. Các lớp con có thể thực hiện khi cần thiết. Mặc định là một nop.

7. viewDidAppear

Sự viewDidAppearkiện này sẽ kích hoạt sau khi chế độ xem được hiển thị trên màn hình. Điều này làm cho nó trở thành một nơi tốt để lấy dữ liệu từ dịch vụ phụ trợ hoặc cơ sở dữ liệu.

Được gọi khi chế độ xem đã được chuyển hoàn toàn lên màn hình. Mặc định không có gì

số 8. viewWillDisappear

Sự viewWillDisappearkiện này bùng cháy khi chế độ xem được trình bày viewControllersắp biến mất, loại bỏ, che đậy hoặc ẩn đằng sau khác viewController. Đây là một nơi tốt để bạn có thể hạn chế các cuộc gọi mạng, hẹn giờ không hợp lệ hoặc giải phóng các đối tượng bị ràng buộc với điều đó viewController.

Được gọi khi chế độ xem bị loại bỏ, được bảo hiểm hoặc ẩn.

9. viewDidDisappear

Đây là bước cuối cùng của vòng đời mà bất kỳ ai cũng có thể giải quyết khi sự kiện này diễn ra ngay sau khi chế độ xem được trình bày viewControllerđã bị biến mất, bị loại bỏ, che đậy hoặc ẩn đi.

Được gọi sau khi chế độ xem bị loại bỏ, được bảo hiểm hoặc ẩn. Mặc định không có gì

Bây giờ theo Apple khi bạn đang thực hiện các phương pháp này, bạn nên nhớ gọi superthực hiện phương pháp cụ thể đó.

Nếu bạn phân lớp UIViewControll, bạn phải gọi siêu triển khai của phương thức này, ngay cả khi bạn không sử dụng NIB. (Để thuận tiện, phương thức init mặc định sẽ thực hiện điều này cho bạn và chỉ định nil cho cả hai đối số của phương thức này.) kết nối với quan điểm chính. Nếu bạn gọi phương thức này bằng tên nil, thì -loadViewphương thức của lớp này sẽ cố tải một NIB có tên giống với lớp của trình điều khiển xem của bạn. Nếu thực tế không tồn tại NIB như vậy thì bạn phải gọi -setView:trước khi -viewđược gọi hoặc ghi đè -loadViewphương thức để thiết lập các khung nhìn của bạn theo chương trình.

Hy vọng điều này sẽ giúp. Cảm ơn.

CẬP NHẬT - Như @ThomasW đã chỉ bên trong nhận xét viewWillLayoutSubviewsviewDidLayoutSubviewscũng sẽ được gọi vào thời điểm khác khi các chế độ xem của chế độ xem chính được tải, ví dụ khi các ô của chế độ xem bảng hoặc chế độ xem bộ sưu tập được tải.

CẬP NHẬT - Như @Maria chỉ trong bình luận, mô tả về loadViewđã được cập nhật


6
viewWillLayoutSubviewsviewDidLayoutSubviewscũng sẽ được gọi vào các thời điểm khác khi các chế độ xem của chế độ xem chính được tải, ví dụ khi các ô của chế độ xem bảng hoặc chế độ xem bộ sưu tập được tải.
ThomasW

Có một sự hiểu lầm nhỏ trong câu trả lời này: loadView () luôn được gọi, nó không nên bị ghi đè khi chế độ xem cho bộ điều khiển được tạo trong IB.
Maria

@Maria Hãy tiếp tục và chỉnh sửa câu trả lời nếu bạn nghĩ rằng nó có thể được cải thiện. Cảm ơn.
onCompletion

Mặc định không có gì là sai cho viewWillAppear viewDidAppear viewDidDisappear. Bạn phải gọi siêu tại một số điểm.
Mick

47

iOS 10,11 (Swift 3.1, Swift 4.0)

Theo UIViewControllertrong UIKitnhà phát triển,

1. loadView ()

Đây là nơi các lớp con sẽ tạo cấu trúc phân cấp chế độ xem tùy chỉnh nếu chúng không sử dụng ngòi . Không bao giờ nên được gọi trực tiếp.

2. loadView IfNeeded ()

Tải chế độ xem của trình điều khiển xem nếu nó chưa được đặt.

3. viewDidLoad ()

Được gọi sau khi xem đã được tải. Đối với các bộ điều khiển xem được tạo trong mã, đây là sau -loadView. Đối với các bộ điều khiển chế độ xem không được lưu trữ từ ngòi, đây là sau khi chế độ xem được đặt.

4. viewWillAppear (_ hoạt hình: Bool)

Được gọi khi chế độ xem sắp hiển thị. Mặc định không có gì

5. viewWillLayoutSubview ()

Được gọi ngay trước khi phương thức layoutSubview của trình điều khiển khung nhìn được gọi. Các lớp con có thể thực hiện khi cần thiết. Mặc định không có gì.

6. viewDidLayoutSubview ()

Được gọi ngay sau khi phương thức layoutSubview của trình điều khiển khung nhìn được gọi. Các lớp con có thể thực hiện khi cần thiết. Mặc định không có gì.

7. viewDidAppear (_ hoạt hình: Bool)

Được gọi khi chế độ xem đã được chuyển hoàn toàn lên màn hình. Mặc định không có gì

8. viewWillDisappear (_ hoạt hình: Bool)

Được gọi khi chế độ xem bị loại bỏ, được bảo hiểm hoặc ẩn. Mặc định không có gì

9. viewDidDisappear (_ hoạt hình: Bool )

Được gọi sau khi chế độ xem bị loại bỏ, được bảo hiểm hoặc ẩn. Mặc định không có gì

10. viewWillTransition (theo kích thước: CGSize, với điều phối viên: UIViewControllTransitionCoordinator)

Được gọi khi xem là Transitioning.

11. willMove (cha mẹ của toParentViewControll: UIViewControll?)

12. didMove (cha mẹ của toParentViewControll: UIViewControll?)

Hai phương thức này được công khai để các lớp con container gọi khi chuyển đổi giữa các bộ điều khiển con. Nếu chúng bị ghi đè, phần ghi đè phải đảm bảo gọi siêu.

Đối số cha trong cả hai phương thức này là không khi một đứa trẻ bị xóa khỏi cha mẹ của nó; mặt khác, nó bằng với bộ điều khiển xem cha mẹ mới.

13. didReceiveMemoryWarning ()

Được gọi khi ứng dụng cha nhận được cảnh báo bộ nhớ. Trên iOS 6.0, nó sẽ không còn xóa chế độ xem theo mặc định.


2
Nó thực sự rất hữu ích khi stackoverflow sẽ không thanh lọc tất cả các câu trả lời sai và không đầy đủ từ toàn bộ chủ đề này. Câu trả lời của bạn có vẻ hoàn chỉnh khi có các cuộc gọi phương thức, vì vậy tôi sẽ cho rằng câu trả lời của bạn là chính xác và làm việc với điều đó.
Logicsaurus Rex

Một nibnhư được đề cập dưới đây là loadViewgì?
Petrus Theron

2
@LogicsaurusRex Tôi đồng ý. Theo cùng một cách mà SO đánh dấu các câu hỏi là trùng lặp hoặc được bảo vệ, tôi nghĩ rằng nó có thể đánh dấu các câu trả lời là lỗi thời hoặc lỗi thời
rmp251

Điểm 5 ở trên là sai. viewWillLayoutSubviews()được gọi trước khi đối tượng khung nhìn của ViewContoder gọi layoutSubviews()phương thức của nó
williamukoh

28

Kể từ iOS 6 trở đi. Sơ đồ mới như sau:

nhập mô tả hình ảnh ở đây


1
Gọi quan điểm đó là "A". Xem xét chế độ xem thứ hai "B" xuất hiện trong khi "A" biến mất. Là "B.viewWillAppear" trước hay sau "A.viewDidDisappear"? Và có tình huống nào thứ tự của hai thay đổi đó không?
ToolmakerSteve

Có vẻ như (B) willApear của view mới sẽ được gọi trước khi disAppears. Đối với câu hỏi thứ hai. Cần một chút thời gian để xem xét nó.
Saad

21

Hãy tập trung vào các phương thức chịu trách nhiệm cho vòng đời của UIViewContoder :

  • Sự sáng tạo:

    - (void)init

    - (void)initWithNibName:

  • Xem sáng tạo:

    - (BOOL)isViewLoaded

    - (void)loadView

    - (void)viewDidLoad

    - (UIView *)initWithFrame:(CGRect)frame

    - (UIView *)initWithCoder:(NSCoder *)coder

  • Xử lý thay đổi trạng thái xem:

    - (void)viewDidLoad

    - (void)viewWillAppear:(BOOL)animated

    - (void)viewDidAppear:(BOOL)animated

    - (void)viewWillDisappear:(BOOL)animated

    - (void)viewDidDisappear:(BOOL)animated

    - (void)viewDidUnload

  • Xử lý cảnh báo bộ nhớ:

    - (void)didReceiveMemoryWarning

  • Giao dịch

    - (void)viewDidUnload

    - (void)dealloc

Sơ đồ vòng đời của UIViewControll

Để biết thêm thông tin, vui lòng xem qua Tham khảo lớp UIViewControll .


19

Các phương thức viewWillLayoutSubviewsviewDidLayoutSubviewskhông được đề cập trong sơ đồ, nhưng chúng được gọi là giữa viewWillAppearviewDidAppear. Chúng có thể được gọi nhiều lần.


Chúng cũng sẽ được gọi vào các thời điểm khác khi các chế độ xem của chế độ xem chính được tải, ví dụ khi các ô của chế độ xem bảng hoặc chế độ xem bộ sưu tập được tải.
ThomasW

16

Câu trả lời của Haider là chính xác cho tiền iOS 6. Tuy nhiên, kể từ iOS 6, viewDidUnload và viewWillUnload không bao giờ được gọi. Các tài liệu nêu rõ: "Lượt xem không còn bị xóa trong điều kiện bộ nhớ thấp và vì vậy phương thức này không bao giờ được gọi."


Tôi đã thử đặt một điểm dừng trong ViewWillDisappear, ViewDidDisappear, Vứt bỏ. Nhưng không ai trong số họ được gọi khi tôi điều hướng bằng phương thức PresentViewControll (). Điều gì có thể là lý do ?
Sreeraj

1
Liên kết không hoạt động ... Vậy HĐH làm gì trong bộ nhớ thấp?
Con trai

Lưu chúng vào đĩa?
Ian Warburton

16

Có rất nhiều thông tin lỗi thời và không đầy đủ ở đây. Chỉ dành cho iOS 6 và mới hơn :

  1. loadView[a]
  2. viewDidLoad[a]
  3. viewWillAppear
  4. viewWillLayoutSubviews là lần đầu tiên giới hạn được hoàn thành
  5. viewDidLayoutSubviews
  6. viewDidAppear
  7. * viewWillLayoutSubviews[b]
  8. * viewDidLayoutSubviews[b]

Chú thích:

(a) - Nếu bạn tự Nil ra tầm nhìn của bạn trong suốt didReceiveMemoryWarning, loadViewviewDidLoadsẽ được gọi một lần nữa. Đó là, theo mặc định loadViewviewDidLoadchỉ được gọi một lần cho mỗi phiên bản trình điều khiển xem.

(b) Có thể được gọi là 0 lần trở lên.


1
viewWillLayoutSubviewsviewDidLayoutSubviewscũng sẽ được gọi vào các thời điểm khác khi các chế độ xem của chế độ xem chính được tải, ví dụ khi các ô của chế độ xem bảng hoặc chế độ xem bộ sưu tập được tải.
ThomasW

11

Giải thích các chuyển đổi trạng thái trong tài liệu chính thức: https://developer.apple.com/l Library / ios / document / uikit / report / UIViewContoder_Class / index.html

Hình ảnh này cho thấy các chuyển đổi trạng thái hợp lệ giữa các phương thức gọi lại khác nhau 'sẽ' và 'đã làm'

Chuyển trạng thái hợp lệ:


Lấy từ: https://developer.apple.com/l Library / ios / document / uikit / reference / UIViewControll_Class / Art / UIViewControll Class Reference_2x.png


0

Theo tài liệu của Apple - Bắt đầu phát triển ứng dụng iOS (Swift) - Làm việc với bộ điều khiển xem - Hiểu vòng đời của bộ điều khiển xem

viewDidLoad()Hối lộ khi chế độ xem nội dung của trình điều khiển khung nhìn (phần trên cùng của hệ thống phân cấp khung nhìn) được tạo và được tải từ bảng phân cảnh. Sử dụng phương pháp này để thực hiện bất kỳ thiết lập bổ sung nào theo yêu cầu của bộ điều khiển xem của bạn.

viewWillAppear()Ngay trước khi chế độ xem nội dung của trình điều khiển chế độ xem được thêm vào phân cấp chế độ xem của ứng dụng. Sử dụng phương pháp này để kích hoạt mọi hoạt động cần xảy ra trước khi chế độ xem nội dung được hiển thị trên màn hình

viewDidAppear()Ngay sau khi chế độ xem nội dung của trình điều khiển chế độ xem đã được thêm vào phân cấp chế độ xem của ứng dụng. Sử dụng phương pháp này để kích hoạt bất kỳ hoạt động nào cần xảy ra ngay khi chế độ xem được hiển thị trên màn hình, chẳng hạn như tìm nạp dữ liệu hoặc hiển thị hình động.

viewWillDisappear()Ngay trước khi chế độ xem nội dung của trình điều khiển chế độ xem bị xóa khỏi phân cấp chế độ xem của ứng dụng. Sử dụng phương pháp này để thực hiện các tác vụ dọn dẹp như cam kết thay đổi hoặc từ bỏ trạng thái phản hồi đầu tiên.

viewDidDisappear()Ngay sau khi chế độ xem nội dung của trình điều khiển chế độ xem đã bị xóa khỏi phân cấp chế độ xem của ứng dụng. Sử dụng phương pháp này để thực hiện các hoạt động phá vỡ bổ sung.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.