ios - আইফোন ৭




আইফোন-শীর্ষস্থানীয় ভিউ কন্ট্রোলার খুঁজে কিভাবে (20)

আমি এখন কয়েকটি ক্ষেত্রে যাচ্ছি যেখানে এটি "সর্বাধিক" দৃশ্য নিয়ামক (বর্তমান দৃশ্যের জন্য দায়ী) খুঁজে পেতে সক্ষম হওয়া সুবিধাজনক হবে, তবে এটি করার উপায় খুঁজে পাওয়া যায় নি।

মূলত চ্যালেঞ্জটি হল: প্রদত্ত যে কোনও শ্রেণীতে নির্বাহ করা হচ্ছে যা কোনও দৃশ্য নিয়ামক (বা একটি দৃশ্য) নয় [এবং একটি সক্রিয় দৃশ্যের ঠিকানা নেই] এবং শীর্ষস্থানীয় ভিউ কন্ট্রোলারের ঠিকানাটি প্রেরণ করা হয়নি। বা, বলুন, ন্যাভিগেশন নিয়ামক ঠিকানা), এটা দেখুন কন্ট্রোলার খুঁজে পাওয়া সম্ভব? (এবং যদি তাই হয়, কিভাবে?)

অথবা, যে ব্যর্থ, শীর্ষতম দেখুন এটি সম্ভব?


@ এরিকের উত্তরটি প্রসারিত করার জন্য, আপনাকে সতর্কতা অবলম্বন করতে হবে যে কী উইণ্ডো আসলে আপনার পছন্দের উইন্ডো। উদাহরণস্বরূপ, সতর্কতা দর্শনে কোনও জিনিস আলতো চাপানোর পরে আপনি এই পদ্ধতিটি ব্যবহার করার চেষ্টা করছেন তবে কী-উইণ্ডো প্রকৃতপক্ষে সতর্কতার উইন্ডো হবে এবং এতে আপনার কোন সন্দেহ নেই। সতর্কতার মাধ্যমে গভীর লিঙ্কগুলি পরিচালনা করার সময় এটি আমার সাথে ঘটেছে এবং SIGABRT কে কোন স্ট্যাক ট্র্যাক দিয়ে সৃষ্টি করেছে। ডিবাগ মোট দুশ্চরিত্রা।

আমি এখন ব্যবহার করছি কোড এখানে:

- (UIViewController *)getTopMostViewController {
    UIWindow *topWindow = [UIApplication sharedApplication].keyWindow;
    if (topWindow.windowLevel != UIWindowLevelNormal) {
        NSArray *windows = [UIApplication sharedApplication].windows;
        for(topWindow in windows)
        {
            if (topWindow.windowLevel == UIWindowLevelNormal)
                break;
        }
    }

    UIViewController *topViewController = topWindow.rootViewController;

    while (topViewController.presentedViewController) {
        topViewController = topViewController.presentedViewController;
    }

    return topViewController;
}

আপনি এই প্রশ্নের অন্যান্য উত্তর থেকে পছন্দ শীর্ষ দৃশ্য নিয়ামক পুনরুদ্ধারের যে কোন গন্ধ সঙ্গে এই মিশ্রিত করা বিনা দ্বিধায়।


JonasG এর answer সম্পূর্ণ করতে (যারা ট্র্যাওয়ারিংয়ের সময় ট্যাব বার কন্ট্রোলারগুলি ছেড়ে গেছে), বর্তমানে দৃশ্যমান দৃশ্য নিয়ামকটি ফেরত দেওয়ার আমার সংস্করণ এখানে রয়েছে:

- (UIViewController*)topViewController {
    return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
}

আমার মনে হয় বেশিরভাগ উত্তরই UINavigationViewController সম্পূর্ণভাবে উপেক্ষা UINavigationViewController , তাই আমি নিম্নলিখিত প্রয়োগের সাথে এই ব্যবহার ক্ষেত্রে পরিচালনা করেছি।

+ (UIViewController *)topMostController {
    UIViewController * topController = [UIApplication sharedApplication].keyWindow.rootViewController;
    while (topController.presentedViewController || [topController isMemberOfClass:[UINavigationController class]]) {
        if([topController isMemberOfClass:[UINavigationController class]]) {
            topController = [topController childViewControllers].lastObject;
        } else {
            topController = topController.presentedViewController;
        }
    }

    return topController;
}

আমি আপনাকে গ্রহণযোগ্য উত্তর এবং @ Fishstix এর একটি সমন্বয় প্রয়োজন মনে হয়

+ (UIViewController*) topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }

    return topController;
}

সুইফ্ট 3.0+

func topMostController() -> UIViewController? {
    guard let window = UIApplication.shared.keyWindow, let rootViewController = window.rootViewController else {
        return nil
    }

    var topController = rootViewController

    while let newTopController = topController.presentedViewController {
        topController = newTopController
    }

    return topController
}

এই উত্তরটি childViewControllers অন্তর্ভুক্ত childViewControllers এবং একটি পরিচ্ছন্ন এবং পঠনযোগ্য বাস্তবায়ন বজায় রাখে।

+ (UIViewController *)topViewController
{
    UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

    return [rootViewController topVisibleViewController];
}

- (UIViewController *)topVisibleViewController
{
    if ([self isKindOfClass:[UITabBarController class]])
    {
        UITabBarController *tabBarController = (UITabBarController *)self;
        return [tabBarController.selectedViewController topVisibleViewController];
    }
    else if ([self isKindOfClass:[UINavigationController class]])
    {
        UINavigationController *navigationController = (UINavigationController *)self;
        return [navigationController.visibleViewController topVisibleViewController];
    }
    else if (self.presentedViewController)
    {
        return [self.presentedViewController topVisibleViewController];
    }
    else if (self.childViewControllers.count > 0)
    {
        return [self.childViewControllers.lastObject topVisibleViewController];
    }

    return self;
}

এই সমাধান সবচেয়ে সম্পূর্ণ। এটি বিবেচনায় নেয়: UINavigationController UIPageViewController UITabBarController এবং শীর্ষ দৃশ্য কন্ট্রোলার থেকে সর্বাধিক উপস্থাপিত দৃশ্য নিয়ামক

উদাহরণ সুইফ্ট 3 হয়।

3 overloads আছে

//Get the topmost view controller for the current application.
public func MGGetTopMostViewController() -> UIViewController?  {

    if let currentWindow:UIWindow = UIApplication.shared.keyWindow {
        return MGGetTopMostViewController(fromWindow: currentWindow)
    }

    return nil
}

//Gets the topmost view controller from a specific window.
public func MGGetTopMostViewController(fromWindow window:UIWindow) -> UIViewController? {

    if let rootViewController:UIViewController = window.rootViewController
    {
        return MGGetTopMostViewController(fromViewController:  rootViewController)
    }

    return nil
}


//Gets the topmost view controller starting from a specific UIViewController
//Pass the rootViewController into this to get the apps top most view controller
public func MGGetTopMostViewController(fromViewController viewController:UIViewController) -> UIViewController {

    //UINavigationController
    if let navigationViewController:UINavigationController = viewController as? UINavigationController {
        let viewControllers:[UIViewController] = navigationViewController.viewControllers
        if navigationViewController.viewControllers.count >= 1 {
            return MGGetTopMostViewController(fromViewController: viewControllers[viewControllers.count - 1])
        }
    }

    //UIPageViewController
    if let pageViewController:UIPageViewController = viewController as? UIPageViewController {
        if let viewControllers:[UIViewController] = pageViewController.viewControllers {
            if viewControllers.count >= 1 {
                return MGGetTopMostViewController(fromViewController: viewControllers[0])
            }
        }
    }

    //UITabViewController
    if let tabBarController:UITabBarController = viewController as? UITabBarController {
        if let selectedViewController:UIViewController = tabBarController.selectedViewController {
            return MGGetTopMostViewController(fromViewController: selectedViewController)
        }
    }

    //Lastly, Attempt to get the topmost presented view controller
    var presentedViewController:UIViewController! = viewController.presentedViewController
    var nextPresentedViewController:UIViewController! = presentedViewController?.presentedViewController

    //If there is a presented view controller, get the top most prensentedViewController and return it.
    if presentedViewController != nil {
        while nextPresentedViewController != nil {

            //Set the presented view controller as the next one.
            presentedViewController = nextPresentedViewController

            //Attempt to get the next presented view controller
            nextPresentedViewController = presentedViewController.presentedViewController
        }
        return presentedViewController
    }

    //If there is no topmost presented view controller, return the view controller itself.
    return viewController
}

এক্সটেনশন ব্যবহার করে সুইফ্ট জন্য শীর্ষ সর্বাধিক ভিউ কন্ট্রোলার পেয়ে

কোড:

extension UIViewController {
    @objc func topMostViewController() -> UIViewController {
        // Handling Modal views
        if let presentedViewController = self.presentedViewController {
            return presentedViewController.topMostViewController()
        }
        // Handling UIViewController's added as subviews to some other views.
        else {
            for view in self.view.subviews
            {
                // Key property which most of us are unaware of / rarely use.
                if let subViewController = view.next {
                    if subViewController is UIViewController {
                        let viewController = subViewController as! UIViewController
                        return viewController.topMostViewController()
                    }
                }
            }
            return self
        }
    }
}

extension UITabBarController {
    override func topMostViewController() -> UIViewController {
        return self.selectedViewController!.topMostViewController()
    }
}

extension UINavigationController {
    override func topMostViewController() -> UIViewController {
        return self.visibleViewController!.topMostViewController()
    }
}

ব্যবহার:

UIApplication.sharedApplication().keyWindow!.rootViewController!.topMostViewController()

এখনো আরেকটি সুইফট সমাধান

func topController() -> UIViewController? {

    // recursive follow
    func follow(from:UIViewController?) -> UIViewController? {
        if let to = (from as? UITabBarController)?.selectedViewController {
            return follow(to)
        } else if let to = (from as? UINavigationController)?.visibleViewController {
            return follow(to)
        } else if let to = from?.presentedViewController {
            return follow(to)
        }
        return from
    }

    let root = UIApplication.sharedApplication().keyWindow?.rootViewController

    return follow(root)

}

এখানে এই আমার গ্রহণ করা হয়। শীর্ষস্থানীয় কন্ট্রোলার হিসাবে UIAlertView পাওয়ার ছাড়ার উপায়টি নির্দেশ করার জন্য @ স্টেকেনবার্গের ধন্যবাদ

-(UIWindow *) returnWindowWithWindowLevelNormal
{
    NSArray *windows = [UIApplication sharedApplication].windows;
    for(UIWindow *topWindow in windows)
    {
        if (topWindow.windowLevel == UIWindowLevelNormal)
            return topWindow;
    }
    return [UIApplication sharedApplication].keyWindow;
}

-(UIViewController *) getTopMostController
{
    UIWindow *topWindow = [UIApplication sharedApplication].keyWindow;
    if (topWindow.windowLevel != UIWindowLevelNormal)
    {
        topWindow = [self returnWindowWithWindowLevelNormal];
    }

    UIViewController *topController = topWindow.rootViewController;
    if(topController == nil)
    {
        topWindow = [UIApplication sharedApplication].delegate.window;
        if (topWindow.windowLevel != UIWindowLevelNormal)
        {
            topWindow = [self returnWindowWithWindowLevelNormal];
        }
        topController = topWindow.rootViewController;
    }

    while(topController.presentedViewController)
    {
        topController = topController.presentedViewController;
    }

    if([topController isKindOfClass:[UINavigationController class]])
    {
        UINavigationController *nav = (UINavigationController*)topController;
        topController = [nav.viewControllers lastObject];

        while(topController.presentedViewController)
        {
            topController = topController.presentedViewController;
        }
    }

    return topController;
}

এটি এরিকের উত্তরের একটি উন্নতি:

UIViewController *_topMostController(UIViewController *cont) {
    UIViewController *topController = cont;

    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }

    if ([topController isKindOfClass:[UINavigationController class]]) {
        UIViewController *visible = ((UINavigationController *)topController).visibleViewController;
        if (visible) {
            topController = visible;
        }
    }

    return (topController != cont ? topController : nil);
}

UIViewController *topMostController() {
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

    UIViewController *next = nil;

    while ((next = _topMostController(topController)) != nil) {
        topController = next;
    }

    return topController;
}

_topMostController(UIViewController *cont) একটি সহায়ক ফাংশন।

এখন আপনাকে যা করতে হবে তা হল কল topMostController() এবং শীর্ষস্থানীয় বেশিরভাগ UIViewController টি ফেরত দেওয়া উচিত!


এরিকের answer সম্পূর্ণ করার জন্য (যারা পপোভার্স, নেভিগেশান কন্ট্রোলার, ট্যাববার কন্ট্রোলারগুলি বাদ দিয়ে, ট্র্যাকারিংয়ের সময় অন্য কোন ভিউ কন্ট্রোলারকে কন্ট্রোলার হিসাবে যোগ করা কন্ট্রোলারগুলি দেখুন), বর্তমানে দৃশ্যমান দৃশ্য নিয়ামকটি ফেরত দেওয়ার আমার সংস্করণ এখানে রয়েছে:

================================================== ===================

- (UIViewController*)topViewController {
    return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)viewController {
    if ([viewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)viewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([viewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navContObj = (UINavigationController*)viewController;
        return [self topViewControllerWithRootViewController:navContObj.visibleViewController];
    } else if (viewController.presentedViewController && !viewController.presentedViewController.isBeingDismissed) {
        UIViewController* presentedViewController = viewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    }
    else {
        for (UIView *view in [viewController.view subviews])
        {
            id subViewController = [view nextResponder];
            if ( subViewController && [subViewController isKindOfClass:[UIViewController class]])
            {
                if ([(UIViewController *)subViewController presentedViewController]  && ![subViewController presentedViewController].isBeingDismissed) {
                    return [self topViewControllerWithRootViewController:[(UIViewController *)subViewController presentedViewController]];
                }
            }
        }
        return viewController;
    }
}

================================================== ===================

এবং এখন সর্বাধিক ভিউ কন্ট্রোলার পেতে আপনাকে যা করতে হবে তা নিম্নোক্ত পদ্ধতিতে নিম্নোক্ত পদ্ধতিতে কল করুন:

UIViewController *topMostViewControllerObj = [self topViewController];

বিকল্প সুইফট সমাধান:

static func topMostController() -> UIViewController {
    var topController = UIApplication.sharedApplication().keyWindow?.rootViewController
    while (topController?.presentedViewController != nil) {
        topController = topController?.presentedViewController
    }

    return topController!
}

সুইফট:

extension UIWindow {

func visibleViewController() -> UIViewController? {
    if let rootViewController: UIViewController  = self.rootViewController {
        return UIWindow.getVisibleViewControllerFrom(rootViewController)
    }
    return nil
}

class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
if vc.isKindOfClass(UINavigationController.self) {

    let navigationController = vc as UINavigationController
    return UIWindow.getVisibleViewControllerFrom( navigationController.visibleViewController)

} else if vc.isKindOfClass(UITabBarController.self) {

    let tabBarController = vc as UITabBarController
    return UIWindow.getVisibleViewControllerFrom(tabBarController.selectedViewController!)

} else {

    if let presentedViewController = vc.presentedViewController {

        return UIWindow.getVisibleViewControllerFrom(presentedViewController.presentedViewController!)

    } else {

        return vc;
    }
}
}

ব্যবহার:

 if let topController = window.visibleViewController() {
            println(topController)
        }

সুইফ্ট গ্রেট সমাধান, AppDelegate বাস্তবায়ন

func getTopViewController()->UIViewController{
    return topViewControllerWithRootViewController(UIApplication.sharedApplication().keyWindow!.rootViewController!)
}
func topViewControllerWithRootViewController(rootViewController:UIViewController)->UIViewController{
    if rootViewController is UITabBarController{
        let tabBarController = rootViewController as! UITabBarController
        return topViewControllerWithRootViewController(tabBarController.selectedViewController!)
    }
    if rootViewController is UINavigationController{
        let navBarController = rootViewController as! UINavigationController
        return topViewControllerWithRootViewController(navBarController.visibleViewController)
    }
    if let presentedViewController = rootViewController.presentedViewController {
        return topViewControllerWithRootViewController(presentedViewController)
    }
    return rootViewController
}

আপনি ব্যবহার করে শীর্ষ সবচেয়ে দেখুন কন্ট্রোলার খুঁজে পেতে পারে

NSArray *arrViewControllers=[[self navigationController] viewControllers];
UIViewController *topMostViewController=(UIViewController *)[arrViewControllers objectAtIndex:[arrViewControllers count]-1];

আরেকটি সমাধান প্রতিক্রিয়া শৃঙ্খলে নির্ভর করে, যা প্রথম প্রতিক্রিয়াকারীর উপর নির্ভর করে কাজ করতে পারে বা পারে না:

  1. প্রথম উত্তরদাতা পান ।
  2. যে প্রথম প্রতিক্রিয়া সঙ্গে যুক্ত UIViewController পান ।

উদাহরণ ছদ্ম কোড:

+ (UIViewController *)currentViewController {
    UIView *firstResponder = [self firstResponder]; // from the first link above, but not guaranteed to return a UIView, so this should be handled more appropriately.
    UIViewController *viewController = [firstResponder viewController]; // from the second link above
    return viewController;
}

রুট কন্ট্রোলার যদি একটি ন্যাভিগেশন কন্ট্রোলার হয়, উপরের দৃশ্যমান নিয়ামকটি খুঁজে পেতে সঠিক উপায়টি হল:

UIViewController *rootVC = [[UIApplication sharedApplication] keyWindow].rootViewController;
if ([rootVC respondsToSelector:@selector(visibleViewController)])
{
    UIViewController *topVC = [(UINavigationController *)rootVC visibleViewController];
    // do your thing with topVC
}

এখানে UINavigationController থেকে একটি উদ্ধৃতাংশ।

@property(nonatomic,readonly,retain) UIViewController *topViewController; // The top view controller on the stack.
@property(nonatomic,readonly,retain) UIViewController *visibleViewController; // Return modal view controller if it exists. Otherwise the top view controller.

এই উত্তর অনেক অসম্পূর্ণ। যদিও এটি উদ্দেশ্য-সি-তে রয়েছে, এটি তাদের সকলের সেরা সংকলন যা আমি এই মুহূর্তে একত্রিত করতে পারি, একটি অ-পুনরুদ্ধারকারী ব্লক হিসাবে:

UIViewController *(^topmostViewControllerForFrontmostNormalLevelWindow)(void) = ^UIViewController *{
    // NOTE: Adapted from various stray answers here:
    //   https://.com/questions/6131205/iphone-how-to-find-topmost-view-controller/20515681

    UIViewController *viewController;

    for (UIWindow *window in UIApplication.sharedApplication.windows.reverseObjectEnumerator.allObjects) {
        if (window.windowLevel == UIWindowLevelNormal) {
            viewController = window.rootViewController;
            break;
        }
    }

    while (viewController != nil) {
        if ([viewController isKindOfClass:[UITabBarController class]]) {
            viewController = ((UITabBarController *)viewController).selectedViewController;
        } else if ([viewController isKindOfClass:[UINavigationController class]]) {
            viewController = ((UINavigationController *)viewController).visibleViewController;
        } else if (viewController.presentedViewController != nil && !viewController.presentedViewController.isBeingDismissed) {
            viewController = viewController.presentedViewController;
        } else if (viewController.childViewControllers.count > 0) {
            viewController = viewController.childViewControllers.lastObject;
        } else {
            BOOL repeat = NO;

            for (UIView *view in viewController.view.subviews.reverseObjectEnumerator.allObjects) {
                if ([view.nextResponder isKindOfClass:[UIViewController class]]) {
                    viewController = (UIViewController *)view.nextResponder;

                    repeat = YES;
                    break;
                }
            }

            if (!repeat) {
                break;
            }
        }
    }

    return viewController;
};

দুটি ফাংশন নীচে দেখুন কন্ট্রোলার স্ট্যাকের উপরে শীর্ষ ভিউ কন্ট্রোলার খুঁজে পেতে সহায়তা করতে পারে। আপনি পরে কাস্টমাইজেশন প্রয়োজন হতে পারে, কিন্তু এই কোড জন্য শীর্ষ ভিউ কন্ট্রোলার ধারণা বা দেখুন কন্ট্রোলার ধারণা স্ট্যাক দুর্দান্ত।

- (UIViewController*)findTopViewController {

  id  topControler  = [self topMostController];

  UIViewController* topViewController;
  if([topControler isKindOfClass:[UINavigationController class]]) {
        topViewController = [[(UINavigationController*)topControler viewControllers] lastObject];
   } else if ([topControler isKindOfClass:[UITabBarController class]]) {
        //Here you can get reference of top viewcontroller from stack of viewcontrollers on UITabBarController
  } else {
        //topController is a preented viewController
        topViewController = (UIViewController*)topControler;
  }
    //NSLog(@"Top ViewController is: %@",NSStringFromClass([topController class]));
    return topViewController;
}

- (UIViewController*)topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }
    //NSLog(@"Top View is: %@",NSStringFromClass([topController class]));
    return topController;
}

আপনি একটি কন্ট্রোলার ক্লাসের ধরন খুঁজে বের করতে [ভিউ কন্ট্রোলার ক্লাস] পদ্ধতিটি ব্যবহার করতে পারেন।


- (UIViewController*)topViewController {
    return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
}




uiviewcontroller