อะไรคือความแตกต่างระหว่าง-[UIViewController viewWillAppear:]
และ-[UIViewController viewDidAppear:]
?
อะไรคือความแตกต่างระหว่าง-[UIViewController viewWillAppear:]
และ-[UIViewController viewDidAppear:]
?
คำตอบ:
โดยทั่วไปนี่คือสิ่งที่ฉันทำ:
1) ViewDidLoad - เมื่อใดก็ตามที่ฉันเพิ่มการควบคุมไปยังมุมมองที่ควรปรากฏร่วมกับมุมมองทันทีฉันใส่ไว้ในเมธอด ViewDidLoad โดยทั่วไปจะเรียกวิธีนี้ทุกครั้งที่โหลดมุมมองลงในหน่วยความจำ ตัวอย่างเช่นหากมุมมองของฉันเป็นรูปแบบที่มีป้ายกำกับ 3 ป้ายฉันจะเพิ่มป้ายกำกับที่นี่ มุมมองจะไม่มีอยู่หากไม่มีรูปแบบเหล่านั้น
2) ViewWillAppear : ปกติฉันใช้ ViewWillAppear เพื่ออัปเดตข้อมูลในแบบฟอร์ม ดังนั้นตัวอย่างข้างต้นฉันจะใช้สิ่งนี้เพื่อโหลดข้อมูลจากโดเมนของฉันลงในแบบฟอร์ม การสร้าง UIViews นั้นค่อนข้างแพงและคุณควรหลีกเลี่ยงการทำเช่นนั้นบนเมธอด ViewWillAppear ให้มากที่สุดเพราะเมื่อสิ่งนี้ถูกเรียกนั่นหมายความว่า iPhone พร้อมที่จะแสดง UIView ให้กับผู้ใช้แล้วและสิ่งที่หนักหนาที่คุณทำที่นี่ จะส่งผลต่อประสิทธิภาพในลักษณะที่มองเห็นได้ชัดเจน (เช่นภาพเคลื่อนไหวล่าช้าเป็นต้น)
3) ViewDidAppear : ในที่สุดฉันใช้ ViewDidAppear เพื่อเริ่มเธรดใหม่ไปยังสิ่งที่ต้องใช้เวลานานในการดำเนินการเช่นการเรียกใช้บริการเว็บเพื่อรับข้อมูลเพิ่มเติมสำหรับแบบฟอร์มด้านบนสิ่งที่ดีก็คือเนื่องจากมุมมอง มีอยู่แล้วและกำลังแสดงต่อผู้ใช้คุณสามารถแสดงข้อความ "กำลังรอ" ที่ดีต่อผู้ใช้ในขณะที่คุณได้รับข้อมูล
viewWillAppear
อย่างไร คุณหมายถึงการดาวน์โหลดผ่านเครือข่าย? แต่คุณยังแนะนำให้ดาวน์โหลดสิ่งต่างๆในviewDidAppear
?
ViewDidAppear
คุณจะทำให้ผู้ใช้สับสนเกี่ยวกับ UI ได้อย่างง่ายดาย :)
viewDidLoad === >>> ใส่รหัสเริ่มต้นของคุณที่นี่ อย่าใส่ข้อมูลแบบไดนามิกที่อาจเปลี่ยนแปลงระหว่างวงจรการดู ดังนั้นหากคุณกำลังดึงข้อมูลจากข้อมูลหลักคุณไม่ต้องการทำที่นี่หากสิ่งนี้สามารถเปลี่ยนแปลงได้ในช่วงชีวิตของมุมมอง ตัวอย่างเช่นสมมติว่าคุณมีตัวควบคุมแท็บ คุณเปลี่ยนจาก tab1 เป็น tab2 และเปลี่ยนบางอย่างบนโมเดลใน tab2 หากคุณกลับมาที่ tab1 และรหัสโมเดลของคุณเสร็จสิ้นใน viewDidLoad สิ่งนี้จะไม่ถูกอัปเดต (สมมติว่าคุณไม่ได้ใช้ KVO หรือ NSFetchedResultsController เป็นต้น)
viewWillAppear === >>> สิ่งนี้ถูกเรียกทุกครั้งที่มุมมองกำลังจะปรากฏขึ้นไม่ว่ามุมมองนั้นจะอยู่ในหน่วยความจำแล้วหรือไม่ก็ตาม ใส่รหัสไดนามิกของคุณที่นี่เช่นตรรกะของโมเดล
viewDidAppear === >>> ใส่การดำเนินการที่มีราคาแพงที่นี่ที่คุณต้องการทำก็ต่อเมื่อคุณแน่ใจว่ามุมมองนั้นอยู่บนหน้าจอเช่นการโทรผ่านเครือข่าย
ข้อสังเกต: หากแอปของคุณเป็นพื้นหลังและกลับสู่เบื้องหน้าคุณต้องจัดการสิ่งนี้โดยใช้ NSNotificationCenter ฉันเขียนรหัสสำหรับสิ่งนั้นในความคิดเห็นด้านล่าง คุณอาจคิดว่า viewWillAppear / viewDidAppear จะเริ่มทำงาน วางจุดพักไว้ที่นั่นและทดสอบ มันไม่ยิง ดังนั้นหากแอปของคุณเปลี่ยนแปลงไปในขณะที่แอปอยู่เบื้องหลังคุณจะต้องอัปเดตโดยใช้การแจ้งเตือน
viewWillAppear
วิธีการที่เรียกว่าก่อนที่จะโหลดมุมมองที่เกิดขึ้นจริง
viewDidAppear
วิธีการที่เรียกว่ามุมมองเมื่อมีการโหลดแล้วและคุณต้องการที่จะแสดงให้เห็นบางสิ่งบางอย่าง
viewWillAppear:
■เรียกก่อนที่มุมมองจะถูกเพิ่มไปยังลำดับชั้นมุมมองของ windows
■เรียกก่อน [vc.view layoutSubviews] (ถ้าจำเป็น)
viewDidAppear :
■เรียกว่าหลังจากเพิ่มมุมมองในลำดับชั้นของมุมมอง
■เรียกว่าหลังจาก [vc.view layoutSubviews] (ในกรณีที่จำเป็น)
ข้อสังเกตบางประการ:
viewDidLoad
วิธีการที่เรียกว่าเมื่อมุมมองถูกสร้างครั้งแรก IBOutlet
การอ้างอิงจะเชื่อมโยงกันตามเวลาที่มีการเรียก แต่ไม่ใช่ก่อนหน้านี้ frame
ของมุมมองอาจไม่ได้รับการจัดตั้งขึ้นโดยเวลานี้ได้รับการเรียกว่า นี่เป็นสถานที่ที่ดีเยี่ยมในการเพิ่ม / กำหนดค่ามุมมองย่อยและข้อ จำกัด ที่เกี่ยวข้อง แต่ถ้าคุณกำลังทำสิ่งใดใช้การกำหนดค่าframe
ค่าบนพื้นฐานของมิติมุมมองหลักของการกำหนดค่าของเฟรมเหล่านั้นควรจะเลื่อนไปก่อนจนกว่าหรือviewWillAppear
viewDidLayoutSubviews
viewWillAppear
วิธีการที่เรียกว่าเมื่อนำเสนอมุมมองในลำดับชั้นมุมมองที่เป็นเรื่องเกี่ยวกับการเริ่มต้น สิ่งนี้เรียกว่าในช่วงเริ่มต้นของภาพเคลื่อนไหว (ถ้ามี) ของการนำเสนอของมุมมอง สหายของมันviewWillDisappear
ถูกเรียกอย่างชัดเจนเมื่อการเปลี่ยนจากมุมมองนี้เริ่มต้นขึ้น
viewDidAppear
วิธีการที่เรียกว่าเมื่อนำเสนอในมุมมองที่จะทำสะดุดตาเมื่อใด ๆ และภาพเคลื่อนไหวที่เกี่ยวข้องได้เสร็จสิ้น เพื่อนร่วมทางของมันviewDidDisappear
ถูกเรียกอย่างชัดเจนเมื่อการเปลี่ยนจากมุมมองนี้เสร็จสิ้น
คำเตือนที่สำคัญสองประการ:
viewDidLoad
ถูกเรียกครั้งเดียวและครั้งเดียวเมื่อมุมมองถูกสร้างอินสแตนซ์ครั้งแรก ในทางกลับกันviewWillAppear
และviewDidAppear
จะถูกเรียกไม่เพียง แต่เมื่อมีการนำเสนอมุมมองครั้งแรก แต่ทุกครั้งต่อมาจะมีการนำเสนอมุมมองเดียวกันที่เป็นปัญหาอีกครั้ง ตัวอย่างเช่นเมื่อคุณนำเสนอมุมมองครั้งแรกระบบจะเรียกทั้งสามวิธีนี้ หากมุมมองที่เป็นปัญหาในภายหลังนำเสนอมุมมองอื่นซึ่งถูกยกเลิกในภายหลังโดยทั่วไปviewWillAppear
และviewDidAppear
จะถูกเรียกอีกครั้งเมื่อมีการเพิ่มมุมมองที่เป็นปัญหาและเคลื่อนไหวกลับเข้าสู่ลำดับชั้นของมุมมอง แต่viewDidLoad
จะไม่ viewDidLoad
จะถูกเรียกก็ต่อเมื่อมีการสร้างอินสแตนซ์นี้ขึ้นเป็นครั้งแรก
ดังนั้นถ้าคุณต้องการที่จะทำบางสิ่งบางอย่างทุกครั้งที่มีมุมมองที่ปรากฏขึ้นอีกครั้ง (เช่นคุณยกเลิกหรือป๊อปกลับไปมัน) ทำมันในหรือviewWillAppear
หากคุณต้องการให้มันเกิดขึ้นเมื่อเพียงมุมมองถูกสร้างครั้งแรกที่ทำในviewDidAppear
viewDidLoad
การเรียกร้องviewWillAppear
ไม่รับประกันว่าการเปลี่ยนไปใช้มุมมองนั้นจะเสร็จสมบูรณ์ โดยเฉพาะอย่างยิ่งหากคุณกำลังใช้การเปลี่ยนแปลงแบบโต้ตอบที่ขับเคลื่อนโดยการป้อนข้อมูลแบบเรียลไทม์ของผู้ใช้ แต่การเปลี่ยนแปลงแบบโต้ตอบนั้นสามารถยกเลิกได้ กล่าวคือเพียงเพราะviewWillAppear
ถูกเรียกก็ไม่ได้หมายความว่าviewDidAppear
จะเรียก โดยทั่วไปจะเป็น แต่ถ้าท่าทางโต้ตอบถูกยกเลิกมันจะไม่ (เนื่องจากการเปลี่ยนแปลงไม่เสร็จสิ้น)
ในงาน WWDC 2013 ในบริบทของการเปลี่ยนแบบโต้ตอบผู้นำเสนอพูดติดตลกว่าพวกเขาควรเปลี่ยนชื่อviewWillAppear
เป็น " viewMightAppear
หรือviewWillProbablyAppear
หรือiReallyWishThisViewWouldAppear
"
ตัวอย่างท่าทางโต้ตอบในตัวคือเมื่อใช้UINavigationController
และคุณ "ปัดจากขอบด้านซ้าย" เพื่อเริ่มต้นมุมมอง ระบบviewWillAppear
จะเรียกใช้มุมมองที่คุณกำลังโผล่ขึ้นมา แต่ถ้าคุณยกเลิก "ปัดจากขอบด้านซ้าย" เพื่อกลับไปยังมุมมองที่คุณเริ่มท่าทางป๊อปนี้ป๊อปจะถูกยกเลิกและviewDidAppear
สำหรับมุมมองที่คุณเริ่ม ป๊อปกลับไปจะไม่ถูกเรียก
ผลกระทบสุทธิของสิ่งนี้คือคุณควรระวังว่าคุณจะไม่เขียนโค้ดที่ถือว่าการโทรทุกครั้งviewWillAppear
จะตามมาด้วยการโทรไปในviewDidAppear
ที่สุด หากการเปลี่ยนแปลงถูกยกเลิกจะไม่เป็นเช่นนั้น
viewwillappear จะเรียกก่อนที่จะโหลดมุมมองเพื่อให้คุณสามารถทำงานบางอย่างได้ก่อนที่จะโหลดมุมมองนั้นและ viewdidappear จะเรียกหลังจากโหลดมุมมองดังนั้นงานโพสต์จะเสร็จสิ้นในวิธีนั้น
ความแตกต่างระหว่าง "will" และ "did" ... ตามชื่อที่แนะนำ viewWillAppear ถูกเรียกก่อนมุมมองกำลังจะปรากฏขึ้นและ viewDidAppear ถูกเรียกเมื่อมุมมองปรากฏขึ้น
1) ViewWillAppear : มุมมองที่โหลดจริงในหน่วยความจำเรียกว่าหนึ่งครั้งในตัวควบคุมมุมมองและมีเฟรม แต่ยังไม่ปรากฏต่อผู้ใช้
2) ViewDidAppear : ตัวควบคุมที่เพิ่มเข้าไปในลำดับชั้นของมุมมองเพื่อให้คุณสามารถนำเสนอไปยังตัวควบคุมถัดไปได้นอกจากนี้มุมมองยังจัดวางมุมมองย่อย
อดีตเกิดขึ้นก่อนที่มุมมองจะปรากฏขึ้นและสิ่งหลังเกิดขึ้นในภายหลัง
สรุป:
-viewWillAppear -> อัปเดตข้อมูล (โหลดข้อมูลจากมุมมองตาราง)
-viewDidAppear -> การดำเนินการที่มีราคาแพง (การเรียก API ด้วยความคืบหน้าที่ดี!)
ตามชื่อที่แนะนำการviewWillAppear
เรียกก่อนที่มุมมองจะปรากฏขึ้นและviewDidAppear
ถูกเรียกเมื่อมุมมองปรากฏขึ้น
Usecaseคือเมื่อไหร่ที่ควรใช้?
viewDidLoad
- เมื่อป้ายกำกับปุ่ม (i, e ตัวควบคุม / มุมมองย่อยใด ๆ ) เชื่อมต่อกับไฟล์อินเทอร์เฟซของ View และหากคุณต้องการโหลดทั้งหมดเหล่านี้พร้อมกันกับ ViewController's View และหากคุณต้องการโหลดลงในหน่วยความจำเพียงครั้งเดียว ทำกับมัน
viewWillAppear
- พูดว่าคุณต้องการเปลี่ยนสีพื้นหลังของมุมมองทุกครั้งที่ viewController ปรากฏบนหน้าจอ หรือสมจริงยิ่งขึ้นหากคุณต้องการสีพื้นหลัง DarkMode ในเวลากลางคืนของวันและสีอ่อนของมุมมองพื้นหลังในช่วงกลางวันให้ไปที่รหัสนี้ในviewWillAppear
อีกหนึ่ง usecase ดีๆที่นี่ https://stackoverflow.com/a/39395865/5438240
โปรดทราบว่าหากคุณใช้ Navigation stack ( UINavigationController
) viewController ที่กำลังจะโผล่ขึ้นมาจะมีการviewWillDisappear()
เรียกและ ViewController ที่ถัดไปจะอยู่ด้านบนของสแต็กจะviewWillAppear()
เรียกว่า