Loại bỏ bộ điều khiển dạng xem được trình bày


116

Tôi có một câu hỏi lý thuyết. Bây giờ tôi đang đọc hướng dẫn ViewController của Apple .

Họ viết:

Khi đến lúc loại bỏ bộ điều khiển dạng xem đã trình bày, phương pháp ưu tiên là để bộ điều khiển dạng xem trình bày loại bỏ nó. Nói cách khác, bất cứ khi nào có thể, bộ điều khiển chế độ xem tương tự đã trình bày bộ điều khiển chế độ xem cũng phải chịu trách nhiệm loại bỏ nó. Mặc dù có một số kỹ thuật để thông báo cho bộ điều khiển chế độ xem trình bày rằng bộ điều khiển chế độ xem đã trình bày của nó nên bị loại bỏ, kỹ thuật được ưu tiên là ủy quyền.

Nhưng tôi không thể giải thích, tại sao tôi phải tạo một giao thức trong VC được trình bày và thêm biến thể ủy quyền, tạo phương thức ủy quyền trong trình bày VC để loại bỏ VC đã trình bày, thay vì một lệnh gọi đơn giản trong phương thức trình điều khiển chế độ xem được trình bày

[self dismissViewControllerAnimated:NO completion:nil]?

Tại sao lựa chọn đầu tiên tốt hơn? Tại sao Apple lại giới thiệu nó?

Câu trả lời:


122

Tôi nghĩ rằng Apple đang hỗ trợ họ một chút ở đây cho một phần API có tiềm năng.

  [self dismissViewControllerAnimated:NO completion:nil]

Thực sự là một chút khó khăn. Mặc dù bạn có thể - một cách hợp pháp - gọi điều này trên bộ điều khiển chế độ xem được trình bày, tất cả những gì nó làm là chuyển tiếp thông báo đến bộ điều khiển chế độ xem trình bày. Nếu bạn muốn làm bất cứ điều gì và ở trên, chỉ cần loại bỏ VC, bạn sẽ cần biết điều này và bạn cần phải xử lý nó theo cách giống như phương pháp ủy quyền - vì đó là khá nhiều điều, một phương pháp nướng có phần không linh hoạt phương pháp ủy quyền.

Có lẽ họ đã gặp phải vô số mã xấu do mọi người không thực sự hiểu cách kết hợp điều này với nhau, do đó họ cần thận trọng.

Nhưng tất nhiên, nếu tất cả những gì bạn cần làm là gạt bỏ điều đó, hãy tiếp tục.

Cách tiếp cận của riêng tôi là một sự thỏa hiệp, ít nhất nó nhắc nhở tôi những gì đang diễn ra:

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

[Nhanh]

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

26
Cần lưu ý rằng việc sử dụng presentingViewControllerhầu hết là vô ích vì nó sẽ tham chiếu đến UINavigationControllerif selfđược nhúng trong một. Trong trường hợp đó, bạn sẽ không thể nhận được presentingViewControllertất cả. Tuy nhiên, [self dismissViewControllerAnimated:completion]vẫn hoạt động trong trường hợp đó. Đề xuất của tôi là tiếp tục sử dụng nó cho đến khi Apple sửa nó.
memmons

4
Tôi thích rằng câu trả lời này vẫn hoàn toàn phù hợp 3 năm sau.
user1021430

1
Một điều khác cần xem xét là bộ điều khiển chế độ xem không biết nó được hiển thị như thế nào. Nó có thể đã được trình bày, được đẩy vào bộ điều khiển điều hướng, một phần của bộ điều khiển thanh tab, v.v. Sử dụng ủy quyền cho phép bộ điều khiển chế độ xem "trình bày" "loại bỏ" bộ điều khiển chế độ xem bằng cách sử dụng nghịch đảo của bất kỳ phương pháp nào được sử dụng để trình bày nó.
David Smith

51

Đã cập nhật cho Swift 3

Tôi đến đây chỉ muốn loại bỏ View Controller hiện tại (đã trình bày). Tôi đang đưa ra câu trả lời này cho bất kỳ ai đến đây với cùng mục đích.

Bộ điều khiển điều hướng

Nếu bạn đang sử dụng bộ điều khiển điều hướng, thì điều đó khá dễ dàng.

Quay lại bộ điều khiển chế độ xem trước đó:

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

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

Quay lại bộ điều khiển chế độ xem gốc:

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

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

(Cảm ơn câu trả lời này cho Objective-C.)

Bộ điều khiển chế độ xem phương thức

Khi Bộ điều khiển dạng xem được trình bày theo phương thức, bạn có thể loại bỏ nó (từ bộ điều khiển dạng xem thứ hai) bằng cách gọi

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

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

Các tài liệu cho biết,

Bộ điều khiển chế độ xem trình bày chịu trách nhiệm loại bỏ bộ điều khiển chế độ xem mà nó đã trình bày. Nếu bạn gọi phương thức này trên chính bộ điều khiển chế độ xem được trình bày, UIKit sẽ yêu cầu bộ điều khiển chế độ xem trình bày xử lý việc loại bỏ.

Vì vậy, nó hoạt động để bộ điều khiển chế độ xem được trình bày tự gọi nó. Đây là một ví dụ đầy đủ.

Đại biểu

Câu hỏi của OP là về sự phức tạp của việc sử dụng các đại biểu để bác bỏ một quan điểm.

Tại thời điểm này, tôi không cần sử dụng đại biểu vì tôi thường có bộ điều khiển điều hướng hoặc bộ điều khiển chế độ xem phương thức, nhưng nếu tôi cần sử dụng mẫu đại biểu trong tương lai, tôi sẽ thêm bản cập nhật.


50

Điều này là để tái sử dụng bộ điều khiển chế độ xem.

Bộ điều khiển chế độ xem của bạn không nên quan tâm nếu nó đang được trình bày dưới dạng phương thức, được đẩy trên bộ điều khiển điều hướng hay bất cứ điều gì. Nếu bộ điều khiển chế độ xem của bạn tự loại bỏ, thì bạn đang cho rằng nó đang được trình bày theo phương thức. Bạn sẽ không thể đẩy bộ điều khiển chế độ xem đó lên bộ điều khiển điều hướng.

Bằng cách triển khai một giao thức, bạn cho phép bộ điều khiển chế độ xem chính quyết định cách nó nên được trình bày / đẩy và loại bỏ / bật lên.



6

Theo kinh nghiệm của tôi, nó rất hữu ích khi bạn cần loại bỏ nó khỏi bất kỳ ViewController nào bạn muốn và thực hiện các tác vụ khác nhau cho mỗi viewcontroller loại bỏ nó. Bất kỳ viewController nào sử dụng giao thức đều có thể loại bỏ chế độ xem theo cách riêng của nó. (ipad và iphone hoặc truyền dữ liệu khác nhau khi loại bỏ từ các chế độ xem khác nhau, gọi các phương thức khác nhau khi loại bỏ, v.v.)

Biên tập:

Vì vậy, để làm rõ, nếu tất cả những gì bạn muốn làm là loại bỏ chế độ xem, tôi thấy không cần thiết lập giao thức ủy quyền. Nếu bạn cần làm những việc khác nhau sau khi loại bỏ nó khỏi các bộ điều khiển chế độ xem trình bày khác nhau, thì đó sẽ là cách tốt nhất để sử dụng ủy quyền.


nhưng nếu tôi không cần "truyền dữ liệu khác nhau khi loại bỏ từ các chế độ xem khác nhau, gọi các phương thức khác nhau khi loại bỏ, v.v." thì tôi có thể thực hiện một lệnh nhỏ trong phương thức trình điều khiển chế độ xem đã trình bày - [selfmissViewControllerAnimated: NO complete: nil] không?
nikitahils

Việc để người trình bày loại bỏ chế độ xem đã trình bày, cho thấy rõ ràng rằng người trình bày trên thực tế đã sẵn sàng và xử lý việc quay trở lại nền trước: trình tự thực thi dễ theo dõi và trách nhiệm của bất kỳ bản cập nhật giao diện người dùng nào là hoàn toàn rõ ràng.
Johan

2

Trích dẫn từ Hướng dẫn lập trình bộ điều khiển dạng xem , "Cách bộ điều khiển dạng xem trình bày bộ điều khiển dạng xem khác".

Mỗi bộ điều khiển chế độ xem trong một chuỗi bộ điều khiển chế độ xem được trình bày có các con trỏ đến các đối tượng khác xung quanh nó trong chuỗi. Nói cách khác, một bộ điều khiển chế độ xem được trình bày trình bày bộ điều khiển chế độ xem khác có các đối tượng hợp lệ trong cả thuộc tính PresentationViewController và presentViewController của nó. Bạn có thể sử dụng các mối quan hệ này để theo dõi thông qua chuỗi bộ điều khiển chế độ xem nếu cần. Ví dụ: nếu người dùng hủy thao tác hiện tại, bạn có thể xóa tất cả các đối tượng trong chuỗi bằng cách loại bỏ bộ điều khiển dạng xem được trình bày đầu tiên. Loại bỏ bộ điều khiển chế độ xem sẽ loại bỏ không chỉ bộ điều khiển chế độ xem đó mà còn bất kỳ bộ điều khiển chế độ xem nào mà nó trình bày.

Vì vậy, một mặt nó tạo ra một thiết kế cân bằng đẹp mắt, khử khớp nối tốt, v.v. Nhưng mặt khác, nó rất thực tế, vì bạn có thể nhanh chóng quay lại một điểm nhất định trong điều hướng.

Mặc dù, cá nhân tôi muốn sử dụng các chuỗi nối dài hơn là cố gắng duyệt ngược cây bộ điều khiển chế độ xem trình bày , đó là những gì Apple nói đến trong chương này, nơi trích dẫn từ đó.


2

Một điểm là đây là một cách tiếp cận mã hóa tốt. Nó đáp ứng nhiều OOPnguyên tắc, ví dụ: SRP, Phân tách các mối quan tâm, v.v.

Vì vậy, bộ điều khiển chế độ xem trình bày chế độ xem phải là người loại bỏ nó.

Giống như, một công ty bất động sản cho thuê một căn nhà nên có thẩm quyền lấy lại.


2

Swift 3.0 // Bỏ qua View Controller nhanh chóng

self.navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)

1

Ngoài câu trả lời của Michael Enriquez, tôi có thể nghĩ đến một lý do khác tại sao đây có thể là một cách tốt để bảo vệ bản thân khỏi trạng thái không xác định:

Giả sử ViewControllerA trình bày ViewControllerB theo phương thức. Tuy nhiên, vì bạn có thể chưa viết mã cho ViewControllerA nên bạn không biết về vòng đời của ViewControllerA. Nó có thể loại bỏ 5 giây (giả sử) sau khi trình bày bộ điều khiển chế độ xem của bạn, ViewControllerB.

Trong trường hợp này, nếu bạn chỉ sử dụng dismissViewControllertừ ViewControllerB để loại bỏ chính nó, bạn sẽ ở trạng thái không xác định - có thể không phải là sự cố hoặc màn hình đen mà là trạng thái không xác định theo quan điểm của bạn.

Thay vào đó, nếu bạn đang sử dụng mẫu đại biểu, bạn sẽ biết trạng thái của ViewControllerB và bạn có thể lập trình cho một trường hợp như tôi đã mô tả.


1

Nhanh

let rootViewController:UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!

        if (rootViewController.presentedViewController != nil) {
            rootViewController.dismiss(animated: true, completion: {
                //completion block.
            })
        }

0

Nếu bạn đang sử dụng loại bỏ chế độ xem sử dụng phương thức.

[self dismissViewControllerAnimated:NO completion:nil];

Điều này trả lời như thế nào cho câu hỏi: "Tại sao lựa chọn đầu tiên lại tốt hơn? Tại sao Apple lại khuyên dùng nó?"
jww 20/02/17

0

Đây là rất nhiều tiền. Việc ủy ​​quyền là tốt khi cần thiết nhưng nếu nó làm cho mã phức tạp hơn - và đúng như vậy - thì cần phải có lý do.

Tôi chắc rằng Apple có lý do của nó. Nhưng rõ ràng hơn và ngắn gọn hơn là chỉ cần để VC đã trình bày thực hiện việc sa thải trừ khi có lý do thực sự để làm khác và không ai ở đây cho đến ngày hôm nay đã trình bày một điều mà tôi có thể thấy.

Các giao thức là tuyệt vời khi chúng cần thiết nhưng thiết kế hướng đối tượng không bao giờ là để các mô-đun giao tiếp với nhau một cách không cần thiết.

Tom Love (đồng phát triển Objective C) từng nhận xét rằng Objective C là "thanh lịch", "nhỏ", "sắc nét" và "rõ ràng" (khi so sánh với C ++). Anh ta dễ nói. Ủy quyền là một tính năng hữu ích dường như đã được sử dụng quá mức "chỉ vì", và trong khi tôi thích làm việc bằng ngôn ngữ, tôi sợ ý tưởng bắt buộc phải sử dụng các cú pháp không cần thiết để làm cho mọi thứ phức tạp hơn chúng phải có.


Nó có thể giúp bạn tiết kiệm một số mã ban đầu, nhưng cách tiếp cận của bạn sẽ khiến bạn đau đầu khi cơ sở mã của bạn phát triển. Bạn nên hiểu các nguyên tắc hướng đối tượng chẳng hạn như tách các mối quan tâm, nếu không, bạn cũng có thể viết mã toàn bộ ứng dụng của mình thành một tệp lớn.
Werner Altewischer

-2

Bạn có thể Đóng cửa sổ chế độ xem siêu cao của mình

self.view.superview?.window?.close()

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.