การปิดตัวควบคุมมุมมองที่นำเสนอ


117

ฉันมีคำถามตามทฤษฎี ตอนนี้ฉันกำลังอ่านคู่มือViewControllerของ Apple

พวกเขาเขียน:

เมื่อถึงเวลาที่ต้องปิดตัวควบคุมมุมมองที่นำเสนอแนวทางที่ต้องการคือให้ตัวควบคุมมุมมองที่นำเสนอปิดมัน กล่าวอีกนัยหนึ่งเมื่อใดก็ตามที่เป็นไปได้ตัวควบคุมมุมมองเดียวกับที่นำเสนอตัวควบคุมมุมมองควรรับผิดชอบในการปิดมันด้วย แม้ว่าจะมีเทคนิคหลายประการในการแจ้งตัวควบคุมมุมมองการนำเสนอว่าควรปิดตัวควบคุมมุมมองที่นำเสนอ แต่เทคนิคที่ต้องการคือการมอบหมาย

แต่ฉันไม่สามารถอธิบายได้ว่าทำไมฉันต้องสร้างโปรโตคอลใน VC ที่นำเสนอและเพิ่มตัวแทนที่เปลี่ยนแปลงได้สร้างวิธีการมอบสิทธิ์ในการนำเสนอ VC เพื่อปิด VC ที่นำเสนอแทนที่จะเรียกแบบธรรมดาในวิธีการควบคุมมุมมองที่นำเสนอ

[self dismissViewControllerAnimated:NO completion:nil]เหรอ?

ทำไมตัวเลือกแรกจึงดีกว่า? ทำไม Apple ถึงแนะนำ

คำตอบ:


122

ฉันคิดว่า Apple กำลังปกปิดส่วนหลังของพวกเขาไว้เล็กน้อยที่นี่เพื่อหาชิ้นส่วน API ที่ไม่ดี

  [self dismissViewControllerAnimated:NO completion:nil]

เป็นบิตของซอ แม้ว่าคุณจะสามารถเรียกสิ่งนี้ได้อย่างถูกต้องตามกฎหมายในตัวควบคุมมุมมองที่นำเสนอ แต่สิ่งที่ทำคือส่งต่อข้อความไปยังตัวควบคุมมุมมองการนำเสนอ หากคุณต้องการทำอะไรซ้ำ ๆ เพียงแค่ปิด VC คุณจะต้องรู้สิ่งนี้และคุณต้องปฏิบัติกับมันมากเช่นเดียวกับวิธีการมอบหมาย - เพราะนั่นคือสิ่งที่เป็นอยู่ค่อนข้างไม่ยืดหยุ่น วิธีการมอบหมาย

บางทีพวกเขาอาจเจอโค้ดที่ไม่ดีมากมายโดยผู้คนไม่เข้าใจจริงๆว่ามันรวมกันอย่างไรดังนั้นจึงควรระมัดระวัง

แต่แน่นอนว่าถ้าสิ่งที่คุณต้องทำคือละทิ้งสิ่งนั้นไปข้างหน้า

แนวทางของฉันคือการประนีประนอมอย่างน้อยมันก็เตือนฉันว่าเกิดอะไรขึ้น:

  [[self presentingViewController] dismissViewControllerAnimated:NO completion:nil]

[Swift]

  self.presentingViewController?.dismiss(animated: false, completion:nil)

26
ควรสังเกตว่าการใช้งานpresentingViewControllerส่วนใหญ่ไม่มีประโยชน์เนื่องจากจะอ้างถึงUINavigationControllerif ที่selfฝังอยู่ในที่เดียว ในกรณีนี้คุณจะไม่สามารถรับได้presentingViewControllerเลย แต่[self dismissViewControllerAnimated:completion]ก็ยังใช้ได้ในกรณีนั้น คำแนะนำของฉันคือให้ใช้สิ่งนั้นต่อไปจนกว่า Apple จะแก้ไข
memmons

4
ฉันชอบที่คำตอบนี้ยังคงมีความเกี่ยวข้องโดยสิ้นเชิงในอีก 3 ปีต่อมา
user1021430

1
สิ่งอื่นที่ต้องพิจารณาคือตัวควบคุมมุมมองไม่ทราบว่ามันแสดงอย่างไร อาจถูกนำเสนอผลักไปยังตัวควบคุมการนำทางส่วนหนึ่งของตัวควบคุมแถบแท็บเป็นต้นการใช้ผู้รับมอบสิทธิ์ช่วยให้ตัวควบคุมมุมมอง "นำเสนอ" สามารถ "ปิด" ตัวควบคุมมุมมองโดยใช้วิธีผกผันของวิธีใดก็ตามที่ใช้ในการนำเสนอ
David Smith

51

อัปเดตสำหรับ Swift 3

ฉันมาที่นี่เพียงแค่ต้องการยกเลิก View Controller ปัจจุบัน (ที่นำเสนอ) ฉันกำลังตอบคำถามนี้สำหรับทุกคนที่มาที่นี่ด้วยจุดประสงค์เดียวกัน

ตัวควบคุมการนำทาง

หากคุณใช้ตัวควบคุมการนำทางมันค่อนข้างง่าย

กลับไปที่ตัวควบคุมมุมมองก่อนหน้า:

// Swift
self.navigationController?.popViewController(animated: true)

// Objective-C
[self.navigationController popViewControllerAnimated:YES];

กลับไปที่ตัวควบคุมมุมมองรูท:

// Swift
self.navigationController?.popToRootViewController(animated: true)

// Objective-C
[self.navigationController popToRootViewControllerAnimated:YES];

(ขอบคุณสำหรับคำตอบนี้สำหรับ Objective-C)

Modal View Controller

เมื่อมีการนำเสนอ View Controller แบบโมฆะคุณสามารถปิดได้ (จากตัวควบคุมมุมมองที่สอง) โดยการโทร

// Swift
self.dismiss(animated: true, completion: nil)

// Objective-C
[self dismissViewControllerAnimated:YES completion:nil];

เอกสารกล่าวว่า

ตัวควบคุมมุมมองการนำเสนอมีหน้าที่ปิดตัวควบคุมมุมมองที่นำเสนอ หากคุณเรียกใช้วิธีนี้บนตัวควบคุมมุมมองที่นำเสนอเอง UIKit จะขอให้ตัวควบคุมมุมมองการนำเสนอจัดการการเลิกจ้าง

ดังนั้นจึงใช้ได้กับตัวควบคุมมุมมองที่นำเสนอเพื่อเรียกใช้ด้วยตัวเอง นี่คือตัวอย่างทั้งหมด

ผู้รับมอบสิทธิ์

คำถามของ OP เกี่ยวกับความซับซ้อนของการใช้ผู้รับมอบสิทธิ์เพื่อยกเลิกการดู

ด้วยเหตุนี้ฉันจึงไม่จำเป็นต้องใช้ผู้รับมอบสิทธิ์เนื่องจากโดยปกติฉันจะมีตัวควบคุมการนำทางหรือตัวควบคุมมุมมองแบบโมดอล แต่ถ้าฉันจำเป็นต้องใช้รูปแบบผู้ร่วมประชุมในอนาคตฉันจะเพิ่มการอัปเดต


50

นี่คือการใช้งานตัวควบคุมมุมมองซ้ำ

ตัวควบคุมมุมมองของคุณไม่ควรสนใจว่าจะนำเสนอเป็นโมดอลผลักตัวควบคุมการนำทางหรืออะไรก็ตาม หากตัวควบคุมมุมมองของคุณปิดตัวเองแสดงว่าคุณกำลังสมมติว่าตัวควบคุมมุมมองของคุณถูกนำเสนอแบบโมฆะ คุณจะไม่สามารถผลักตัวควบคุมมุมมองนั้นไปยังตัวควบคุมการนำทางได้

ด้วยการใช้โปรโตคอลคุณปล่อยให้ตัวควบคุมมุมมองหลักเป็นผู้ตัดสินใจว่าควรนำเสนอ / ผลักและปิด / โผล่ออกมาอย่างไร



6

จากประสบการณ์ของผมมันมาในสะดวกเมื่อคุณต้องการที่จะยกเลิกได้จากใด ๆ ViewController ที่คุณต้องการและดำเนินการที่แตกต่างกันสำหรับแต่ละ ViewController ที่ห้ามมัน viewController ใด ๆ ที่ใช้โปรโตคอลสามารถปิดมุมมองได้ในแบบของตัวเอง (ipad เทียบกับ iphone หรือส่งผ่านข้อมูลที่แตกต่างกันเมื่อปิดจากมุมมองที่แตกต่างกันเรียกวิธีการที่แตกต่างกันเมื่อปิด ฯลฯ )

แก้ไข:

ดังนั้นเพื่อความชัดเจนหากสิ่งที่คุณต้องการทำคือปิดมุมมองฉันไม่จำเป็นต้องตั้งค่าโปรโตคอลผู้ร่วมประชุม หากคุณต้องการทำสิ่งต่างๆหลังจากที่คุณปิดมันจากตัวควบคุมมุมมองการนำเสนอที่แตกต่างกันวิธีนี้เป็นวิธีที่ดีที่สุดในการใช้ผู้รับมอบสิทธิ์


แต่ถ้าฉันไม่ต้องการ "การส่งผ่านข้อมูลที่แตกต่างกันเมื่อปิดจากมุมมองที่แตกต่างกันการเรียกใช้วิธีการที่แตกต่างกันเมื่อปิด ฯลฯ .. " ฉันสามารถโทรเพียงครั้งเดียวในเมธอด View Controller ที่นำเสนอ - [self dischargeViewControllerAnimate: NO complete: nil] ได้หรือไม่
nikitahils

การปล่อยให้ผู้นำเสนอยกเลิกมุมมองที่นำเสนอทำให้เห็นได้ชัดว่าผู้นำเสนอพร้อมจริงและจัดการกับการกลับสู่เบื้องหน้า: ลำดับการดำเนินการนั้นง่ายต่อการปฏิบัติตามและความรับผิดชอบของการอัปเดต UI ใด ๆ ก็ชัดเจนโดยปริยาย
Johan


2

อ้างจาก View Controller Programming Guide , "How View Controllers Present Other View Controllers"

ตัวควบคุมมุมมองแต่ละตัวในสายของตัวควบคุมมุมมองที่นำเสนอจะมีตัวชี้ไปยังวัตถุอื่น ๆ ที่อยู่รอบ ๆ ในห่วงโซ่ กล่าวอีกนัยหนึ่งตัวควบคุมมุมมองที่นำเสนอซึ่งนำเสนอตัวควบคุมมุมมองอื่นมีวัตถุที่ถูกต้องทั้งในคุณสมบัติการนำเสนอ ViewController และการนำเสนอ ViewController คุณสามารถใช้ความสัมพันธ์เหล่านี้เพื่อติดตามผ่านห่วงโซ่ของตัวควบคุมมุมมองได้ตามต้องการ ตัวอย่างเช่นหากผู้ใช้ยกเลิกการดำเนินการปัจจุบันคุณสามารถลบออบเจ็กต์ทั้งหมดในห่วงโซ่ได้โดยการปิดตัวควบคุมมุมมองที่นำเสนอครั้งแรก การปิดตัวควบคุมมุมมองไม่เพียง แต่จะเป็นการปิดตัวควบคุมมุมมองนั้นเท่านั้น แต่ยังรวมถึงตัวควบคุมมุมมองที่นำเสนอด้วย

ดังนั้นในแง่หนึ่งมันทำให้เกิดการออกแบบที่สมดุลที่ดีการถอดข้อต่อที่ดี ฯลฯ ... แต่ในทางกลับกันมันใช้งานได้จริงมากเพราะคุณสามารถกลับไปยังจุดหนึ่งในการนำทางได้อย่างรวดเร็ว

แม้ว่าโดยส่วนตัวแล้วฉันค่อนข้างจะใช้การแบ่งส่วนที่คลี่คลายมากกว่าการพยายามย้อนกลับไปด้านหลังแผนผังตัวควบคุมมุมมองที่นำเสนอซึ่งเป็นสิ่งที่ Apple พูดถึงในบทนี้ซึ่งเป็นที่มาของคำพูด


2

ประเด็นหนึ่งคือนี่เป็นวิธีการเข้ารหัสที่ดี เป็นไปOOPตามหลักการหลายประการเช่น SRP การแยกข้อกังวลเป็นต้น

ดังนั้นตัวควบคุมมุมมองที่นำเสนอมุมมองควรเป็นตัวควบคุมมุมมอง

เช่นเดียวกับ บริษัท อสังหาริมทรัพย์ที่ให้บ้านเช่าควรเป็นผู้มีอำนาจในการเอาคืน


1

นอกเหนือจากคำตอบของ Michael Enriquez แล้วฉันยังนึกถึงอีกเหตุผลหนึ่งว่าทำไมสิ่งนี้จึงเป็นวิธีที่ดีในการปกป้องตัวเองจากสภาวะที่บึกบึน:

พูด ViewControllerA นำเสนอ ViewControllerB แบบมอดูล แต่เนื่องจากคุณอาจไม่ได้เขียนโค้ดสำหรับ ViewControllerA คุณจึงไม่ทราบถึงวงจรชีวิตของ ViewControllerA อาจปิด 5 วินาที (พูด) หลังจากนำเสนอ ViewControllerB.

ในกรณีนี้หากคุณเพียงแค่ใช้dismissViewControllerจาก ViewControllerB เพื่อปิดตัวเองคุณจะอยู่ในสถานะที่ไม่ได้กำหนด - อาจไม่ใช่ความผิดพลาดหรือหน้าจอสีดำ แต่เป็นสถานะที่ไม่ได้กำหนดจากมุมมองของคุณ

หากคุณใช้รูปแบบผู้รับมอบสิทธิ์แทนคุณจะทราบถึงสถานะของ ViewControllerB และคุณสามารถตั้งโปรแกรมสำหรับกรณีเช่นเดียวกับที่ฉันอธิบายไว้



0

หากคุณกำลังใช้การปิดมุมมองการใช้โมดอล

[self dismissViewControllerAnimated:NO completion:nil];

คำถามนี้ตอบคำถามได้อย่างไร: "ทำไมตัวเลือกแรกถึงดีกว่าทำไม Apple ถึงแนะนำ"
jww

0

บาโลนี่เยอะมาก การมอบสิทธิ์เป็นสิ่งที่ดีเมื่อจำเป็น แต่ถ้ามันทำให้โค้ดซับซ้อนขึ้น - และเป็นเช่นนั้นก็จำเป็นต้องมีเหตุผล

ฉันแน่ใจว่า Apple มีเหตุผล แต่จะชัดเจนและรัดกุมมากขึ้นเพียงแค่ให้ VC ที่นำเสนอทำการเลิกจ้างเว้นแต่จะมีเหตุผลที่แท้จริงในการดำเนินการเป็นอย่างอื่นและไม่มีใครที่นี่ ณ วันนี้ได้นำเสนอสิ่งที่ฉันเห็น

โปรโตคอลนั้นยอดเยี่ยมเมื่อจำเป็น แต่การออกแบบเชิงวัตถุไม่เคยเกี่ยวกับการมีโมดูลที่สื่อสารระหว่างกันโดยไม่จำเป็น

Tom Love (ผู้พัฒนาร่วมของ Objective C) เคยให้ความเห็นว่า Objective C นั้น "สง่างาม" "เล็ก" "คมชัด" และ "กำหนดไว้อย่างดี" (เมื่อเปรียบเทียบกับ C ++) ง่ายสำหรับเขาที่จะพูด การมอบสิทธิ์เป็นคุณลักษณะที่มีประโยชน์ซึ่งดูเหมือนว่าจะถูกใช้มากเกินไป "เพียงเพราะ" และในขณะที่ฉันชอบทำงานในภาษา แต่ฉันก็กลัวความคิดที่จะบังคับให้ใช้ไวยากรณ์ที่ไม่จำเป็นเพื่อทำให้สิ่งต่างๆซับซ้อนกว่าที่ควรจะเป็น


อาจช่วยให้คุณประหยัดรหัสในตอนแรก แต่แนวทางของคุณจะทำให้คุณปวดหัวมากเมื่อฐานรหัสของคุณเติบโตขึ้น คุณควรเข้าใจหลักการเชิงวัตถุเช่นการแยกข้อกังวลมิฉะนั้นคุณอาจเขียนโค้ดแอปพลิเคชันทั้งหมดของคุณลงในไฟล์ขนาดใหญ่ไฟล์เดียว
Werner Altewischer

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.