Câu trả lời:
Vì modalViewController
đã không được dùng nữa trong iOS 6, đây là phiên bản hoạt động cho iOS 5+ và biên dịch mà không có cảnh báo.
Mục tiêu-C:
- (BOOL)isModal {
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController)
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
}
Nhanh:
var isModal: Bool {
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
|| self.tabBarController?.presentingViewController is UITabBarController
}
Lời khuyên cho câu trả lời của Felipe.
nil == nil
trả về YES
và nó không phải là kết quả chúng ta muốn.
Nếu bạn đang tìm kiếm iOS 6+, câu trả lời này không được dùng nữa và bạn nên kiểm tra câu trả lời của Gabriele Petronella
Không có cách nào gọn gàng để làm điều đó, vì một thuộc tính hoặc phương thức có nguồn gốc từ UIKit. Những gì bạn có thể làm là kiểm tra một số khía cạnh của bộ điều khiển để đảm bảo nó được trình bày dưới dạng phương thức.
Vì vậy, để kiểm tra xem bộ điều khiển hiện tại (được biểu thị như self
trong mã bên dưới) có được trình bày theo cách thức hay không, tôi có chức năng bên dưới hoặc trong một UIViewController
danh mục hoặc (nếu dự án của bạn không cần sử dụng các bộ điều khiển UIKit khác, như UITableViewController
ví dụ) trong bộ điều khiển cơ sở mà các bộ điều khiển khác của tôi kế thừa
-(BOOL)isModal {
BOOL isModal = ((self.parentViewController && self.parentViewController.modalViewController == self) ||
//or if I have a navigation controller, check if its parent modal view controller is self navigation controller
( self.navigationController && self.navigationController.parentViewController && self.navigationController.parentViewController.modalViewController == self.navigationController) ||
//or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
[[[self tabBarController] parentViewController] isKindOfClass:[UITabBarController class]]);
//iOS 5+
if (!isModal && [self respondsToSelector:@selector(presentingViewController)]) {
isModal = ((self.presentingViewController && self.presentingViewController.modalViewController == self) ||
//or if I have a navigation controller, check if its parent modal view controller is self navigation controller
(self.navigationController && self.navigationController.presentingViewController && self.navigationController.presentingViewController.modalViewController == self.navigationController) ||
//or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
[[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]]);
}
return isModal;
}
CHỈNH SỬA: Tôi đã thêm lần kiểm tra cuối cùng để xem liệu một UITabBarController có đang được sử dụng hay không và bạn trình bày một UITabBarController khác dưới dạng phương thức.
EDIT 2: đã thêm kiểm tra iOS 5+, nơi UIViewController
không trả lời cho parentViewController
nữa mà presentingViewController
thay vào đó.
CHỈNH SỬA 3: Tôi đã tạo ý chính cho nó chỉ trong trường hợp https://gist.github.com/3174081
modalViewController
tính không được chấp nhận kể từ iOS 6. Tài liệu đề xuất sử dụng presentedViewController
thay thế.
NSLog(@"%@", self.navigationController.parentViewController)
bản in (null)
- bạn có thể vui lòng giải thích tại sao không? ViewController của tôi được kết nối với bộ điều khiển chế độ xem phương thức thông qua navController trong bảng phân cảnh.
.parentViewController
không được dùng nữa, .presentingViewController
phải được sử dụng thay thế.
Trong iOS5 +, Như bạn có thể thấy trong Tham chiếu lớp UIViewController , bạn có thể lấy nó từ thuộc tính "PresentationViewController".
PresentationViewController Bộ điều khiển chế độ xem đã trình bày bộ điều khiển chế độ xem này. (chỉ đọc)
@property (nonatomic, chỉ đọc) UIViewController * PresentationViewController
Discussion
Nếu bộ điều khiển dạng xem đã nhận được thông báo này được trình bày bởi bộ điều khiển dạng xem khác, thì thuộc tính này giữ bộ điều khiển dạng xem đang trình bày nó. Nếu bộ điều khiển chế độ xem không được trình bày, nhưng một trong những tổ tiên của nó đang được trình bày, thuộc tính này giữ bộ điều khiển chế độ xem trình bày tổ tiên gần nhất. Nếu không có bộ điều khiển chế độ xem hoặc bất kỳ tổ tiên nào của nó đang được hiển thị, thì thuộc tính này là nil.
Tính khả dụng
Có sẵn trong iOS 5.0 trở lên.
Được khai báo trong
UIViewController.h
presentingViewController
. Nó cũng sẽ hoạt động trong bộ điều khiển chế độ xem vùng chứa, vì nó tự động chuyển qua tổ tiên.
Nếu không có, bạn có thể xác định một thuộc tính cho this ( presentedAsModal
) trong lớp con UIViewController của bạn và đặt nó thành YES
trước khi trình bày ViewController dưới dạng một chế độ xem phương thức.
childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];
Bạn có thể kiểm tra giá trị này trong viewWillAppear
ghi đè của mình .
Tôi tin rằng không có thuộc tính chính thức nào cho biết cách hiển thị chế độ xem, nhưng không có gì ngăn cản bạn tạo chế độ xem của riêng mình.
UINavigationController
dưới dạng phương thức ... trừ khi bạn tạo bộ điều khiển điều hướng tùy chỉnh chỉ để thêm thuộc tính này. Và sau đó, bên trong bộ điều khiển, bạn sẽ phải tiếp tục đúc self.navigationController
vào lớp tùy chỉnh này mỗi khi bạn cần phải kiểm tra nếu bộ điều khiển được trình bày như modal
Câu trả lời của Petronella không hoạt động nếu self.navigationController được trình bày theo phương thức nhưng self không bằng self.navigationController.viewControllers [0], trong trường hợp đó, self được đẩy.
Đây là cách bạn có thể khắc phục sự cố.
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController && self == self.navigationController.viewControllers[0])
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
Và trong Swift:
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self)
|| self.tabBarController?.presentingViewController is UITabBarController
Điều này sẽ hoạt động.
if(self.parentViewController.modalViewController == self)…
UINavigationController
và UITabBarController
trường hợp. Nó đang hoạt động khá tốt cho đến nay
Cách tốt nhất để kiểm tra
if (self.navigationController.presentingViewController) {
NSLog(@"Model Present");
}
Nếu bạn không cần phân biệt giữa chế độ xem toàn màn hình theo phương thức và chế độ xem không theo phương thức, đó là trường hợp trong dự án của tôi (tôi đang giải quyết vấn đề chỉ xảy ra với biểu mẫu và trang tính), bạn có thể sử dụng modalPresentationStyle thuộc tính của UIViewController:
switch (self.modalPresentationStyle) {
case 0: NSLog(@"full screen, or not modal"); break;
case 1: NSLog(@"page sheet"); break;
case 2: NSLog(@"form sheet"); break;
}
Trong Swift :
func isUIViewControllerPresentedAsModal() -> Bool {
if((self.presentingViewController) != nil) {
return true
}
if(self.presentingViewController?.presentedViewController == self) {
return true
}
if(self.navigationController?.presentingViewController?.presentedViewController == self.navigationController) {
return true
}
if((self.tabBarController?.presentingViewController?.isKindOfClass(UITabBarController)) != nil) {
return true
}
return false
}
Trong dự án của tôi, tôi có một bộ điều khiển chế độ xem (Chi tiết) có thể được trình bày theo phương thức (khi thêm một mục mới) hoặc đẩy (khi chỉnh sửa một cái hiện có) bằng bộ điều khiển chế độ xem Chính. Khi người dùng chạm vào [Xong], bộ điều khiển chế độ xem Chi tiết gọi phương thức của bộ điều khiển chế độ xem Chính để thông báo rằng nó đã sẵn sàng để đóng. Master phải xác định cách trình bày Chi tiết để biết cách đóng nó. Đây là cách tôi làm điều này:
UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
[self dismissViewControllerAnimated:YES completion:NULL];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
Một bản hack như thế này có thể hoạt động.
UIViewController* child = self;
UIViewController* parent = child.parentViewController;
while (parent && parent.modalViewController != child) {
child = parent;
parent = child.parentViewController;
}
if (parent) {
// A view controller in the hierarchy was presented as a modal view controller
}
Tuy nhiên, tôi nghĩ câu trả lời trước đây của tôi là một giải pháp sạch hơn.
Những gì làm việc cho tôi là sau:
// this is the trick: set parent view controller as application's window root view controller
UIApplication.sharedApplication.delegate.window.rootViewController = viewController;
// assert no modal view is presented
XCTAssertNil(viewController.presentedViewController);
// simulate button tap which shows modal view controller
[viewController.deleteButton sendActionsForControlEvents:UIControlEventTouchUpInside];
// assert that modal view controller is presented
XCTAssertEqualObjects(viewController.presentedViewController.class, MyModalViewController.class);
Theo như tôi đã thử nghiệm, điều này hoạt động cho iOS7 và iOS8. Tuy nhiên, đã không thử trên iOS6.
Tôi đã xem xét một chút để tìm câu trả lời phù hợp cho câu hỏi này và tôi không thể tìm thấy câu trả lời nào bao gồm tất cả các trường hợp có thể xảy ra. Tôi đã viết vài dòng mã này dường như thực hiện công việc. Bạn có thể tìm thấy một vài nhận xét nội dòng để tìm ra những gì đã được kiểm tra.
- (BOOL)isModal {
BOOL modal = NO;
if ([self presentingViewController]) { //Some view Controller is presenting the current stack
UIViewController *presented = [[self presentingViewController] presentedViewController]; // What's been presented
if ([presented respondsToSelector:@selector(viewControllers)]) { // There's a stack
NSArray *viewControllers = [presented performSelector:@selector(viewControllers)];
modal = [viewControllers firstObject] == self; // Current VC is presented modally if it's the first in the stack
}
else {
modal = presented == self; // Don't think this is actually needed. set modal = YES should do the job tho.
}
}
return modal;
}
Hy vọng điều này giúp đỡ.
Đây là phiên bản đã sửa đổi của tôi về @ GabrielePetronella's isModal
, phiên bản này hoạt động với các bộ điều khiển chế độ xem được chứa trong đó nó đi lên hệ thống phân cấp parentViewController trước tiên. Cũng kéo mã ra thành nhiều dòng để rõ ràng nó đang làm gì.
var isModal: Bool {
// If we are a child view controller, we need to check our parent's presentation
// rather than our own. So walk up the chain until we don't see any parentViewControllers
var potentiallyPresentedViewController : UIViewController = self
while (potentiallyPresentedViewController.parentViewController != nil) {
potentiallyPresentedViewController = potentiallyPresentedViewController.parentViewController!
}
if self.presentingViewController?.presentedViewController == potentiallyPresentedViewController {
return true
}
if let navigationController = potentiallyPresentedViewController.navigationController {
if navigationController.presentingViewController?.presentedViewController == navigationController {
return true
}
}
return potentiallyPresentedViewController.tabBarController?.presentingViewController is UITabBarController
}