Sự khác biệt giữa -viewWillAppear: và -viewDidAppear:?


131

Sự khác biệt giữa -[UIViewController viewWillAppear:]và là -[UIViewController viewDidAppear:]gì?


1
cảm ơn BoltClock, nhưng xin vui lòng cho tôi ví dụ về cả hai nếu có thể ..
PJR

3
@BoltClock sẽ thật tuyệt nếu đó là sự thật. Tôi đoán 15 người đã nâng cấp đọc tên phương thức nhưng chưa bao giờ thực sự đo nó ... Đến đây từ Google vì đó không phải là sự khác biệt giữa họ
Adam

1
Cụ thể: ParentView.viewDidAppear được gọi là MỘT LẦN THỜI GIAN trước khi Apple thực sự hiển thị ParentView ... trước tiên Apple (nguyên tử) vẽ tất cả các cuộc phỏng vấn ... và nếu bạn có nhiều cuộc phỏng vấn, hoặc những cuộc phỏng vấn phức tạp, thì "viewDidAppear" có thể được gọi là hàng chục hoặc hàng trăm mili giây quá sớm :(.
Adam

Câu trả lời:


292

Nói chung, đây là những gì tôi làm:

1) ViewDidLoad - Bất cứ khi nào tôi thêm các điều khiển vào một chế độ xem sẽ xuất hiện cùng với chế độ xem, ngay lập tức, tôi đặt nó trong phương thức ViewDidLoad. Về cơ bản phương thức này được gọi bất cứ khi nào khung nhìn được tải vào bộ nhớ. Vì vậy, ví dụ, nếu chế độ xem của tôi là một biểu mẫu có 3 nhãn, tôi sẽ thêm các nhãn ở đây; quan điểm sẽ không bao giờ tồn tại mà không có những hình thức.

2) ViewWillAppear : Tôi thường sử dụng ViewWillAppear chỉ để cập nhật dữ liệu trên biểu mẫu. Vì vậy, với ví dụ trên, tôi sẽ sử dụng điều này để thực sự tải dữ liệu từ miền của mình vào biểu mẫu. Việc tạo UIViews khá tốn kém và bạn nên tránh càng nhiều càng tốt khi thực hiện điều đó trên phương thức ViewWillAppear, vì điều này được gọi, điều đó có nghĩa là iPhone đã sẵn sàng hiển thị UIView cho người dùng và bất cứ điều gì nặng nề bạn làm ở đây sẽ tác động đến hiệu suất theo cách rất dễ thấy (như hoạt hình bị trì hoãn, v.v.).

3) ViewDidAppear : Cuối cùng, tôi sử dụng ViewDidAppear để bắt đầu các luồng mới cho những thứ sẽ mất nhiều thời gian để thực thi, ví dụ như thực hiện cuộc gọi dịch vụ web để lấy thêm dữ liệu cho biểu mẫu ở trên. Điều tốt là vì chế độ xem đã tồn tại và đang được hiển thị cho người dùng, bạn có thể hiển thị thông báo "Đang chờ" cho người dùng trong khi bạn nhận được dữ liệu.


4
Xin lỗi, nhưng ý bạn là gì khi "tải dữ liệu từ tên miền của tôi vào biểu mẫu" trong viewWillAppear? Bạn có nghĩa là tải qua mạng? Nhưng bạn cũng đề nghị tải công cụ trong viewDidAppear?
Philip007

1
@ Philip007 Tôi nghĩ Stack đang đề cập đến loại tên miền này: en.wikipedia.org/wiki/Domain-specific_modeling . Dữ liệu được tải từ các mô hình của bạn hoặc tương tự.
dentarg

2
Câu trả lời này nên có trong các tài liệu. Nó thực sự hữu ích trong việc làm rõ sự khác biệt giữa ba phương pháp. Cảm ơn bạn!
GangstaGraham

1
+1 Tôi đã có một chút nhầm lẫn khi hiểu sự khác biệt giữa ba người này, nhưng bạn đã xóa nó hoàn toàn hơn @ChetanBhalara
Chisx

@ChetanBhalara nhưng nếu bạn làm việc lâu, ViewDidAppearbạn sẽ dễ khiến người dùng nhầm lẫn về UI :)
hqt

46

viewDidLoad === >>> Đặt mã khởi tạo của bạn ở đây. Không đặt dữ liệu động có thể thay đổi trong vòng đời xem. Vì vậy, nếu bạn đang lấy dữ liệu từ dữ liệu cốt lõi, bạn không muốn làm điều đó ở đây nếu điều này có thể thay đổi trong suốt vòng đời của chế độ xem. Ví dụ: giả sử bạn có bộ điều khiển tab. Bạn chuyển từ tab1 sang tab2 và thay đổi một cái gì đó trên mô hình trong tab2. Nếu bạn quay lại tab1 và mã mô hình của bạn đã được thực hiện trong viewDidLoad, điều này sẽ không được cập nhật (giả sử bạn không sử dụng KVO hoặc NSFetchedResultsControll, v.v.).

viewWillAppear === >>> Điều này được gọi mỗi khi chế độ xem sắp xuất hiện, cho dù chế độ xem đã có trong bộ nhớ hay chưa. Đặt mã động của bạn ở đây, chẳng hạn như logic mô hình.

viewDidAppear === >>> Đặt các thao tác đắt tiền ở đây mà bạn chỉ muốn làm nếu bạn chắc chắn chế độ xem trên màn hình, chẳng hạn như các cuộc gọi mạng.

Lưu ý: nếu ứng dụng của bạn được chạy nền và trở về nền trước, bạn cần xử lý việc này bằng NSNotificationCenter. Tôi đã viết mã ra cho điều đó trong các ý kiến ​​dưới đây. Bạn có thể nghĩ viewWillAppear / viewDidAppear sẽ kích hoạt. Đặt một điểm dừng ở đó và kiểm tra nó. Nó không cháy. Vì vậy, nếu có gì đó đã thay đổi cho ứng dụng của bạn khi ứng dụng chạy ở chế độ nền, bạn sẽ cần cập nhật thông báo đó bằng thông báo.


1
ViewWill hoặc ViewDid có được chạy mỗi lần bạn hủy thu nhỏ ứng dụng không?
Jeef

2
@Jeef Đây là một câu hỏi tuyệt vời. Không được chạy trừ khi ứng dụng bị hệ thống hoặc người dùng giết trong khi ở chế độ nền. Những gì bạn phải làm để nhận được thông báo khi ứng dụng chưa được thu nhỏ là bạn phải sử dụng NSNotificationCenter và addObserver cho tên UIApplicationWill EntryForegroundNotification. Công cụ chọn phải là applicationWill EntryForeground: nó có một tham số NSNotification. Đặt mã của bạn vào phương thức đó để tải lại dữ liệu, v.v. Điều bạn có thể làm là tạo một phương thức tải lại mà bạn gọi là phương thức này và cũng xem viewDidAppear nếu chúng cần giống nhau.
smileBot

2
@Jeef một cái gì đó như thế này: - (void) viewDidLoad {[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector (applicationWill EntryForeground :) name: UIApplicationWill EntryForegroundNotification object: nil] } - (void) applicationWill
EntryForeground

12

Các viewWillAppearphương pháp được gọi là trước khi tải quan điểm thực tế.

Các viewDidAppearphương pháp được gọi khi xem đã được nạp, và bạn muốn hiển thị một cái gì đó.


9

viewWillAppear:
■ Được gọi trước khi chế độ xem được thêm vào phân cấp chế độ xem của cửa sổ
■ Được gọi trước [vc.view layoutSubview] (nếu cần)
viewDidAppear :
■ Được gọi sau khi chế độ xem được thêm vào chế độ xem
■ Được gọi sau [vc.view layoutSubview] (Nếu cần)


7

Một vài quan sát:

  • Các viewDidLoadphương pháp được gọi khi xem được khởi tạo đầu tiên. IBOutlettài liệu tham khảo được nối vào thời điểm này đã được gọi, nhưng không phải trước đó. Các framesố quan điểm có thể không được thành lập vào thời điểm này đã được gọi là, mặc dù. Đây là một nơi tuyệt vời để thêm / cấu hình các cuộc phỏng vấn và các ràng buộc liên quan của chúng. Nhưng nếu bạn đang thực hiện bất kỳ cấu hình thủ công nào của các framegiá trị trên cơ sở kích thước của chế độ xem chính, cấu hình của các khung đó sẽ được hoãn lại cho đến khi viewWillAppearhoặc viewDidLayoutSubviews.

  • Các viewWillAppearphương pháp được gọi khi trình bày quan điểm trong hệ thống phân cấp xem là sắp bắt đầu. Đáng chú ý, điều này được gọi khi bắt đầu hoạt hình (nếu có) của phần trình bày của chế độ xem. Đồng hành của nó, viewWillDisappearrõ ràng được gọi khi quá trình chuyển đổi khỏi quan điểm này bắt đầu.

  • Các viewDidAppearphương pháp được gọi khi trình bày quan điểm được thực hiện, đặc biệt là khi bất kỳ và tất cả các hình ảnh động liên quan đã hoàn tất. Đồng hành của nó, viewDidDisappearrõ ràng được gọi khi quá trình chuyển đổi khỏi quan điểm này được thực hiện.

Hai cảnh báo quan trọng:

  • viewDidLoadđược gọi một lần và chỉ một lần, khi chế độ xem được khởi tạo lần đầu tiên. Mặt khác, viewWillAppearviewDidAppearsẽ được gọi không chỉ khi chế độ xem được trình bày lần đầu tiên, mà mỗi lần tiếp theo, cùng một quan điểm trong câu hỏi được trình bày lại. Ví dụ, khi bạn lần đầu tiên trình bày một khung nhìn, cả ba phương thức này sẽ được gọi. Nếu chế độ xem trong câu hỏi sau đó trình bày một chế độ xem khác bị loại bỏ sau đó, viewWillAppearviewDidAppearthường sẽ được gọi lại khi chế độ xem trong câu hỏi được thêm vào và hoạt hình trở lại vào hệ thống phân cấp chế độ xem, nhưng viewDidLoadsẽ không. viewDidLoadchỉ được gọi khi trường hợp cụ thể này được tạo lần đầu tiên.

    Vì vậy, nếu bạn muốn làm gì đó mỗi khi một khung nhìn xuất hiện lại (ví dụ: bạn loại bỏ hoặc bật lại nó), hãy thực hiện trong viewWillAppearhoặc viewDidAppear. Nếu bạn muốn nó chỉ xảy ra khi chế độ xem được khởi tạo lần đầu tiên, hãy thực hiện điều đó trong viewDidLoad.

  • Việc kêu gọi viewWillAppearkhông đảm bảo rằng việc chuyển đổi sang quan điểm đó sẽ được hoàn thành. Đáng chú ý, nếu bạn đang sử dụng chuyển đổi tương tác được điều khiển bởi đầu vào của người dùng thời gian thực, nhưng quá trình chuyển đổi tương tác đó có thể bị hủy. Tức là, chỉ vì viewWillAppearđược gọi, nó không có nghĩa là viewDidAppearsẽ được gọi. Nói chung là như vậy, nhưng nếu cử chỉ tương tác bị hủy thì sẽ không (vì quá trình chuyển đổi không bao giờ kết thúc).

    Tại WWDC 2013, trong bối cảnh chuyển tiếp tương tác, một người dẫn chương trình nói đùa rằng họ nên đổi tên viewWillAppearđể viewMightAppear"hoặc viewWillProbablyAppear, hoặc iReallyWishThisViewWouldAppear".

    Một ví dụ về cử chỉ tương tác tích hợp là khi sử dụng UINavigationControllervà bạn "vuốt từ cạnh trái" để bắt đầu một cửa sổ bật lên của chế độ xem. Các viewWillAppearsẽ được gọi cho quan điểm mà bạn đang popping, nhưng nếu bạn hủy rằng "vuốt từ mép trái" để trở lại quan điểm mà từ đó bạn bắt đầu cử chỉ pop này, các cửa sổ pop bị hủy bỏ và viewDidAppearcho quan điểm bạn bắt đầu bật trở lại sẽ không bao giờ được gọi.

    Hiệu quả ròng của việc này là bạn nên cẩn thận rằng bạn không viết mã giả định rằng mọi cuộc gọi đến viewWillAppearsẽ được thực hiện theo sau bởi một cuộc gọi đến viewDidAppear. Nếu quá trình chuyển đổi bị hủy bỏ, điều này sẽ không xảy ra.


5

viewwillappear sẽ gọi trước khi tải view để bạn có thể thực hiện một số tác vụ nhất định trước khi tải view đó và viewdidappear sẽ gọi sau khi tải view để tác vụ post sẽ được thực hiện trong phương thức đó


4

Sự khác biệt giữa "will" và "did" ... Như tên cho thấy viewWillAppear được gọi trước khi view sắp xuất hiện và viewDidAppear được gọi khi view xuất hiện.


nhìn vào câu trả lời được chấp nhận, trong đó có hơn 70 lượt upvote. :)
PJR

4

1) ViewWillAppear : Chế độ xem được tải thực sự trong bộ nhớ, được gọi một lần trong trình điều khiển chế độ xem và có khung của nó, nhưng vẫn không xuất hiện cho người dùng

2) ViewDidAppear : Bộ điều khiển được thêm vào cấu trúc phân cấp chế độ xem, do đó bạn có thể trình bày cho bộ điều khiển tiếp theo, ngoài ra, chế độ xem đã bố trí các bản xem trước


3

Cái trước xảy ra trước khi cái nhìn xuất hiện và cái sau xảy ra sau đó.


3

Tóm lại:

-viewWillAppear -> cập nhật dữ liệu (tải lại dữ liệu từ chế độ xem bảng)

-viewDidAppear -> các hoạt động đắt tiền (cuộc gọi API với một tiến trình tốt đẹp!)


1

Như tên cho thấy, viewWillAppearđược gọi trước khi chế độ xem sắp xuất hiện và viewDidAppearđược gọi khi chế độ xem xuất hiện.


0

Usecase , tức là khi nào tôi nên sử dụng?

viewDidLoad - khi các nhãn, nút (i, e bất kỳ điều khiển / xem trước nào) được kết nối với tệp giao diện của Chế độ xem và nếu bạn muốn tải tất cả các mục này cùng lúc với Chế độ xem của Trình điều khiển và nếu bạn muốn tải tệp này vào bộ nhớ một lần và được thực hiện với nó

viewWillAppear- giả sử, bạn muốn thay đổi màu nền của chế độ xem mỗi khi viewContoder xuất hiện trên màn hình. Hoặc thực tế hơn nếu bạn muốn màu nền DarkMode vào ban đêm trong ngày và màu sáng của chế độ xem nền vào ban ngày, hãy tìm mã này trongviewWillAppear

Một usecase tốt khác tại đây https://stackoverflow.com/a/39395865/5438240

Cũng lưu ý rằng, nếu bạn đang sử dụng ngăn xếp Điều hướng ( UINavigationController), thì trình điều khiển viewCont ra sắp xuất hiện có viewWillDisappear()tên được gọi và Trình điều khiển ViewCont tiếp theo sẽ nằm trên đầu ngăn xếp sẽ viewWillAppear()được gọi

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.