2013-04-12 55 views
18

Có cách nào để trình bày một bộ điều khiển xem một cách bình thường mà không biết chế độ xem bộ điều khiển xem hiển thị là gì không? Về cơ bản loại như bạn sẽ hiển thị một cái nhìn cảnh báo tại bất kỳ điểm nào trong thời gian.Trình bày một bộ điều khiển phương thức mà không biết bộ điều khiển xem hiện tại?

Tôi muốn để có thể làm điều gì đó như:

MyViewController *myVC = [[MyViewController alloc] init]; 
[myVC showModally]; 

Tôi muốn để có thể gọi đây là từ bất cứ nơi nào trong ứng dụng, và có nó xuất hiện trên đầu trang. Tôi không muốn quan tâm đến bộ điều khiển xem hiện tại là gì.

Tôi định sử dụng điều này để hiển thị lời nhắc đăng nhập. Tôi không muốn sử dụng chế độ xem cảnh báo và tôi cũng không muốn có mã trình bày đăng nhập trong suốt ứng dụng.

Bất kỳ suy nghĩ nào về điều này? Hay có cách nào tốt hơn để đạt được điều này? Tôi có nên chỉ cần thực hiện cơ chế của riêng tôi và chỉ cần đặt một cái nhìn trên đầu trang của cửa sổ?

+0

làm bạn sử dụng cốt truyện? –

+0

@SpaceDust nope – nebs

Trả lời

27

Vâng, bạn có thể theo dõi chuỗi.

Bắt đầu tại [UIApplication sharedApplication].delegate.window.rootViewController.

Tại mỗi bộ điều khiển chế độ xem, hãy thực hiện chuỗi kiểm tra sau.

Nếu [viewController isKindOfClass:[UINavigationController class]], sau đó chuyển đến [(UINavigationController *)viewController topViewController].

Nếu [viewController isKindOfClass:[UITabBarController class]], sau đó tiếp tục đến [(UITabBarController *)viewController selectedViewController].

Nếu [viewController presentedViewController], sau đó tiếp tục đến [viewController presentedViewController].

+3

Đây là câu trả lời đúng nhất. –

+1

Tôi đã tạo một phương pháp đệ quy bằng ý tưởng của bạn: https://gist.github.com/MartinMoizard/6537467. Làm việc như một nét duyên dáng :) – MartinMoizard

+0

Đây là câu trả lời đúng. –

7

Bạn có thể mã này thực hiện trong ứng dụng của đại biểu của bạn:

AppDelegate.m

-(void)presentViewControllerFromVisibleController:(UIViewController *)toPresent 
{ 
    UIViewController *vc = self.window.rootViewController; 
    [vc presentViewController:toPresent animated:YES]; 
} 

AppDelegate.h

-(void)presentViewControllerFromVisibleViewController:(UIViewController *)toPresent; 

Từ Bất cứ nơi nào

#import "AppDelegate.h" 
... 
AppDelegate *delegate = [UIApplication sharedApplication].delegate; 
[delegate presentViewControllerFromVisibleViewController:myViewControllerToPresent]; 

Trong đại biểu, bạn sẽ nhận được rootViewController của số window. Điều này sẽ luôn được hiển thị - đó là bộ điều khiển 'cha mẹ' của mọi thứ.

+7

Tôi nghĩ rằng điều này thường sẽ hoạt động, nhưng không đúng là bộ điều khiển chế độ xem gốc luôn hiển thị. Có thể có một bộ điều khiển chế độ xem trên màn hình và tôi không chắc chắn điều gì sẽ xảy ra nếu bạn chạy mã này trong trường hợp đó. – rdelmar

+0

@rdelmar Trong trường hợp đó, VC gốc của bạn sẽ vẫn là gốc trình bày VC phương thức. – Undo

+4

Vâng, nó vẫn là gốc nhưng nó sẽ không hoạt động - nếu một bộ điều khiển xem phương thức trên màn hình, và bạn cố gắng trình bày một cái khác từ gốc vc, bạn sẽ nhận được cảnh báo và bộ điều khiển không được hiển thị (để trình bày ... trên mà khung nhìn của nó không nằm trong hệ thống phân cấp cửa sổ!). – rdelmar

2

Tôi không nghĩ bạn nhất thiết cần biết bộ điều khiển chế độ xem nào hiển thị. Bạn có thể truy cập vào keyWindow của ứng dụng và thêm chế độ xem của bộ điều khiển chế độ xem ở đầu danh sách chế độ xem. Sau đó, bạn có thể làm cho nó hoạt động giống như UIAlertView.

tập tin Interface: MyModalViewController.h

#import <UIKit/UIKit.h> 

@interface MyModalViewController : UIViewController 
- (void) show; 
@end 

tập tin thực hiện: MyModalViewController.m

#import "MyModalViewController.h" 


@implementation MyModalViewController 

- (void) show { 
    UIWindow *window = [[UIApplication sharedApplication] keyWindow]; 
    // Configure the frame of your modal's view. 
    [window addSubview: self.view]; 
} 

@end 
19

Giải pháp của tôi trong Swift (lấy cảm hứng từ ý chính của MartinMoizard)

extension UIViewController { 
    func presentViewControllerFromVisibleViewController(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)?) { 
     if let navigationController = self as? UINavigationController { 
      navigationController.topViewController?.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: flag, completion: completion) 
     } else if let tabBarController = self as? UITabBarController { 
      tabBarController.selectedViewController?.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: flag, completion: completion) 
     } else if let presentedViewController = presentedViewController { 
      presentedViewController.presentViewControllerFromVisibleViewController(viewControllerToPresent, animated: flag, completion: completion) 
     } else { 
      present(viewControllerToPresent, animated: flag, completion: completion) 
     } 
    } 
} 
5

Giải pháp này cung cấp cho bạn hầu hết các bộ điều khiển nhìn từ trên xuống để bạn có thể xử lý bất kỳ điều kiện đặc biệt trước khi trình bày từ nó. Ví dụ, có thể bạn muốn trình bày bộ điều khiển xem của bạn chỉ khi bộ điều khiển xem nhiều nhất không phải là một bộ điều khiển xem cụ thể.

extension UIApplication { 
    /// The top most view controller 
    static var topMostViewController: UIViewController? { 
     return UIApplication.shared.keyWindow?.rootViewController?.visibleViewController 
    } 
} 

extension UIViewController { 
    /// The visible view controller from a given view controller 
    var visibleViewController: UIViewController? { 
     if let navigationController = self as? UINavigationController { 
      return navigationController.topViewController?.visibleViewController 
     } else if let tabBarController = self as? UITabBarController { 
      return tabBarController.selectedViewController?.visibleViewController 
     } else if let presentedViewController = presentedViewController { 
      return presentedViewController.visibleViewController 
     } else { 
      return self 
     } 
    } 
} 

Với điều này bạn có thể trình bày điều khiển xem của bạn từ bất cứ nơi nào mà không cần phải biết những gì hầu hết các bộ điều khiển nhìn từ trên xuống là

UIApplication.topMostViewController?.present(viewController, animated: true, completion: nil) 

Hoặc trình bày điều khiển xem của bạn chỉ khi hầu hết các bộ điều khiển nhìn từ trên không phải là một cái nhìn cụ thể điều khiển

if let topVC = UIApplication.topMostViewController, !(topVC is FullScreenAlertVC) { 
    topVC.present(viewController, animated: true, completion: nil) 
} 

một điều cần lưu ý là nếu có một UIAlertController hiện đang được hiển thị, UIApplication.topMostViewController sẽ trả về một UIAlertController. Trình bày trên đầu trang của một UIAlertController có hành vi kỳ lạ và nên tránh. Như vậy, bạn nên kiểm tra bằng tay mà !(UIApplication.topMostViewController is UIAlertController) trước khi trình bày, hoặc thêm một trường hợp else if trở về con số không nếu self is UIAlertController

extension UIViewController { 
    /// The visible view controller from a given view controller 
    var visibleViewController: UIViewController? { 
     if let navigationController = self as? UINavigationController { 
      return navigationController.topViewController?.visibleViewController 
     } else if let tabBarController = self as? UITabBarController { 
      return tabBarController.selectedViewController?.visibleViewController 
     } else if let presentedViewController = presentedViewController { 
      return presentedViewController.visibleViewController 
     } else if self is UIAlertController { 
      return nil 
     } else { 
      return self 
     } 
    } 
} 
Các vấn đề liên quan