আইওএসে শীর্ষস্থানীয় ভিউ কন্ট্রোলার কীভাবে সন্ধান করবেন


253

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

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

বা, এটি ব্যর্থ হয়ে, শীর্ষস্থানীয় দর্শনটি পাওয়া কি সম্ভব?


সুতরাং আপনি বলছেন যে এটি সম্ভব নয়।
হট লিকস

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

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

ভাল, আসুন এটি একটি নির্দিষ্ট ক্ষেত্রে সহজ করুন। আমি যদি ইউআইএলআর্টভিউয়ের ক্লোন লিখতে চাইতাম তবে আমি কীভাবে এটি করব? নোট করুন যে এটি অন্য নিয়ন্ত্রণকারী বা মতামতের কোনও ঠিকানাবোধ ছাড়াই ভাল কাজ করতে পারে।
হট লিক্স

4
@ ড্যানিয়েল: দ্বিতীয় ইউআইওয়াইন্ডো যুক্ত করা সতর্কতা দর্শনের মতো ওভারলেগুলির জন্য ভাল কাজ করে।
উইলবার ভ্যানডারস্মিথ

উত্তর:


75

আইওএস 4 ইউআইওয়াইন্ডোতে রুটভিউ নিয়ন্ত্রণকারী বৈশিষ্ট্যটি প্রবর্তন করেছে:

[UIApplication sharedApplication].keyWindow.rootViewController;

আপনি যদিও ভিউ কন্ট্রোলার তৈরি করার পরে এটি নিজে সেট করতে হবে।


155
উইলবার, এটি আপনাকে যা চেয়েছিল তার বিপরীতে দেবে। রুটভিউ কনট্রোলারটি শীর্ষ সর্বাধিকের চেয়ে বেস ভিউ নিয়ন্ত্রণকারী।
m4rkk

3
m4rkk: "শীর্ষ-সর্বাধিক" নির্ভর করে আপনি কোন দিক থেকে সন্ধান করছেন on নতুন কন্ট্রোলাররা কি শীর্ষে (স্ট্যাকের মতো) বা নীচে (গাছের মতো) যুক্ত হয়? যাইহোক, ওপি নেভিগেশন নিয়ামককে শীর্ষে থাকার কথা উল্লেখ করেছে, যা গ্রোস-ডাউন-ভিউ বোঝায়।
উইলবার ভান্ডারসমিথ

50
শব্দ "শীর্ষ "টি ভিউ কন্ট্রোলারের জন্য ব্যবহৃত হয়, এটি শীর্ষে (যেমন -[UINavigationController topViewController]) দৃশ্যমান । তারপরে "রুট" শব্দটি রয়েছে যা গাছের মূল (যেমন -[UIWindow rootViewController]
ট্রাইকার্টপস

13
@ ইম্পুরস্টক্লাব আমি ডকুমেন্টেশনে সন্ধান করতে পারছি না, এক্সকোড এটি খুঁজে পাবে না বলে মনে হয়।
ড্রাক্স

4
@ আদিব না, এটি ইউআইএনএভিগেশন কন্ট্রোলারের অন্তর্ভুক্ত
ডেভিড এইচ

428

আমি মনে করি আপনার গৃহীত উত্তর এবং @ ফিশস্টিক্সের সংমিশ্রণ দরকার

+ (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
}

4
উপরন্তু, আপনি যাচাই করতে পারে UINavigationControllerএবং তার জন্য অনুরোধ topViewControllerবা এমনকি জন্য চেক UITabBarControllerএবং জন্য অনুরোধ selectedViewController। এটি আপনাকে ব্যবহারকারীর কাছে দৃশ্যমান এমন দৃশ্যের নিয়ামকটি পাবে।
ট্রাইসার্টপস

33
এটি একটি অসম্পূর্ণ সমাধান, যেহেতু এটি কেবলমাত্র উপস্থাপিত ভিউ কন্ট্রোলারদের শ্রেণিবিন্যাসকে অনুসরণ করে, চাইল্ডভিউকন্ট্রোলারদের হায়ারার্কি নয় (ইউআইএনএভিগেশন কন্ট্রোলার, ইউআইটিববারকন্ট্রোলার, ইত্যাদি ব্যবহার করে)।
অ্যালগাল

3
বর্তমান অ্যাপ্লিকেশন স্থিতিতে পুনরায় শুরু হওয়া মডেল ভিউ কন্ট্রোলারের উপস্থাপনা থেকে বেরিয়ে আসার এই দুর্দান্ত উপায়, ধন্যবাদ!
erversteeg

11
@algal: সত্যিই না: UITabBarController, UINavigationController হয় ইতিমধ্যে শ্রেণীবিন্যাসে আগ দৃশ্য কন্ট্রোলার। "শীর্ষস্থানীয় নিয়ন্ত্রক" দিয়ে আপনি কী করতে চান তার উপর নির্ভর করে আপনি এগুলি মোটেও ট্র্যাভার করতে এবং তাদের সামগ্রীতে ফ্রিডল করতে চান না । আমার ক্ষেত্রে এটি ছিল প্রতিটি কিছুর শীর্ষে একটি মডেল কন্ট্রোলার উপস্থাপন করা, এবং তার জন্য আমার ইউআইএনএভিএইচসিএন্ট্রোলার বা ইউআইটিববারকন্ট্রোলার পাওয়া দরকার, তাদের বিষয়বস্তু নয় !
রিক 77

1
@ রিক ,77, যদি এটি সত্য হয় তবে আপনার এখানে দেওয়া একটি ছোট্ট মন্তব্য অপ্রয়োজনীয় অন্যান্য উত্তরগুলিতে জটিল সংশোধন করে। যেহেতু অন্য কারও কাছে এটি মোটেও উল্লেখ করা হয়নি, আমি অনুভব করি যে আমি আপনাকে এটি সত্য তা নিশ্চিত করতে বলতে চাই। এবং যদি এটি হয় তবে এটি এত গুরুত্বপূর্ণ যে এটি তার নিজের উত্তর হিসাবে প্রাপ্য। কারণ অন্যান্য উত্তরগুলির সিংহভাগই এই সমস্যাটি সমাধান করার চেষ্টা করছে back আপনি জীবন বাঁচানো হবে!
লে মোট জুসেড

150

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

- (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;
    }
}

2
ভাল, হ্যাঁ আমি ট্যাববার নিয়ন্ত্রণকারীদের সম্পর্কে ভুলে গেছি: পি
জোনাসজি

9
এতে অন্তর্ভুক্ত নেইchildViewControllers
অসাধারণ-ও

নীচে আমার উত্তরটি দেখুন যা উপরে উত্তরগুলি উন্নত করে যেমন ক্লিওগুলি যেমন পপওভারগুলি ছেড়ে দেওয়া হয়েছে তা পরিচালনা করে দেখুন, নিয়ন্ত্রণকারীরা ট্র্যাভার করার সময় কিছু অন্যান্য ভিউ কন্ট্রোলারের সাথে পূর্বরূপ হিসাবে যুক্ত হয়েছে
রাজেশ

আপনি যদি রিটার্ন [স্ব টপভিউ কনট্রোলারউইথরूटভিউ কনট্রোলার: নেভিগেশনকন্ট্রোলারআরভিসিবলভিউ কনট্রোলার] ব্যবহার করছেন, দৃশ্যমান ভিউকন্ট্রোলার নিজেই উপস্থাপনিত ভিউ কন্ট্রোলার (যদি কোনও) ফিরিয়ে দেয় তবে তা যদি কোনও ইউআইএলআর্টকন্ট্রোলার হয়ও। যাকে ইউআই সতর্কতা নিয়ন্ত্রক এড়াতে হবে তার জন্য দৃশ্যমান ভিউ কনট্রোলারের পরিবর্তে টপভিউ কনট্রোলার ব্যবহার করুন
Johnykutty

এটিতে আমার 50 শতাংশ যোগ করার জন্য - আমি আমার ভিউকন্ট্রোলারে এই কাজটি পাওয়ার জন্য লড়াই করছিলাম যা একটি ওয়েব ভিউ লোড করে দেয় .. কারণ কেন আমি এই কাজটি করতে পারছিলাম না কারণ দৃশ্যটি এখনও প্রস্তুত ছিল না (লোডিং শেষ হয়নি) এবং তাই এটি দৃশ্যমান ছিল না। এটি এমন পরিস্থিতিতে পরিচালিত করে যেখানে শীর্ষ ভিউ কনটোলার পাওয়া ব্যর্থ হয়েছিল, কারণ ইউআইএনএভিগেশন কন্ট্রোলার একটি দৃশ্যমান ভিউকন্ট্রোলার পাওয়ার চেষ্টা করছিল যদিও সেখানে এখনও কোনও দৃশ্যমান ভিউকন্ট্রোলার নেই। সুতরাং যদি কেউ এই সমস্যার মুখোমুখি হন, আপনি উপরের শীর্ষস্থানীয় ভিউকন্ট্রোলার পদ্ধতিতে কল করার আগে আপনার দৃষ্টিভঙ্গি লোড করা শেষ হয়েছে তা নিশ্চিত করুন।
mbuster

52

বিভিন্ন দৃশ্যের যত্ন নিয়ে একটি সম্পূর্ণ নন-রিকারসিভ সংস্করণ:

  • ভিউ কন্ট্রোলার অন্য দর্শন উপস্থাপন করছে
  • ভিউ কন্ট্রোলার একটি UINavigationController
  • ভিউ কন্ট্রোলার একটি UITabBarController

উদ্দেশ্য গ

 UIViewController *topViewController = self.window.rootViewController;
 while (true)
 {
     if (topViewController.presentedViewController) {
         topViewController = topViewController.presentedViewController;
     } else if ([topViewController isKindOfClass:[UINavigationController class]]) {
         UINavigationController *nav = (UINavigationController *)topViewController;
         topViewController = nav.topViewController;
     } else if ([topViewController isKindOfClass:[UITabBarController class]]) {
         UITabBarController *tab = (UITabBarController *)topViewController;
         topViewController = tab.selectedViewController;
     } else {
         break;
     }
 }

সুইফট 4+

extension UIWindow {
    func topViewController() -> UIViewController? {
        var top = self.rootViewController
        while true {
            if let presented = top?.presentedViewController {
                top = presented
            } else if let nav = top as? UINavigationController {
                top = nav.visibleViewController
            } else if let tab = top as? UITabBarController {
                top = tab.selectedViewController
            } else {
                break
            }
        }
        return top
    }
}

2
visibleViewControllerএটি কী করে তা পরিষ্কার করে দেওয়ার জন্য আমি নাম রেখেছি ।
জনি

31

এক্সটেনশানগুলি ব্যবহার করে সুইফ্টের জন্য শীর্ষ সর্বাধিক দেখার নিয়ামক পাচ্ছেন

কোড:

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()

চমৎকার - এই সমাধানের জন্য আপনাকে অনেক ধন্যবাদ। সাবউজটিস্ট্রিকের প্রয়োজন ছিল! আবার অনেক ধন্যবাদ, আপনি আমার দিনটি বাঁচিয়েছিলেন।
আইকেকে

25

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

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

- (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];

স্প্লিটভিউ নিয়ন্ত্রণকারীও কি অনুপস্থিত?
আপিনহো

21

এই উত্তরে 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;
}

কিছু কোড আপডেট হয়েছে, যথাযথভাবে এটি কমানোর মাধ্যমে এবং এটিকে পুনরুদ্ধার করে কী নিয়ন্ত্রণকারী তা দেখান show nik-kov-ios-developer.blogspot.ru/2016/12/…
নিক কোভ

আরে, আসুন, আপনার "শীর্ষস্থানীয়ভিউ নিয়ন্ত্রণকারী" কোথায়?
জান্নাত

12

আমি সম্প্রতি আমার এক প্রকল্পে এই পরিস্থিতি পেয়েছি, যার ফলে নেটওয়ার্কের স্থিতি পরিবর্তিত হওয়ার পরে নিয়ন্ত্রণকারী প্রদর্শিত যাই হোক না কেন এবং প্রকারের (ইউআইএনএভিগেশন কন্ট্রোলার, ক্লাসিক নিয়ন্ত্রক বা কাস্টম ভিউ নিয়ন্ত্রক) যা কিছু ছিল তার একটি বিজ্ঞপ্তি ভিউ প্রদর্শন করা দরকার।

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

আপনি কোডটি এখানে দখল করতে পারেন: পিপিটপমস্টকন্ট্রোলার

এবং ব্যবহার করে শীর্ষ সর্বাধিক নিয়ামক পেয়েছেন

UIViewController *c = [UIViewController topMostController];

10

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

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()এবং শীর্ষস্থানীয় সর্বাধিক ইউআইভিউকন্ট্রোলারকে ফিরিয়ে দেওয়া উচিত!


7
1983 সাল থেকে আমি বলব। মনে রাখবেন যে অবজেক্টিভ-সিতে সি রয়েছে ... সি ফাংশনে ওবিজেসি কোড মোড়ানো একটি সাধারণ অনুশীলন, তাই হ্যাঁ, এটি উদ্দেশ্য-সি কোড।
জোনাসজি

@ জোনাসজি হাই জোনাস, আপনি কোন পরিস্থিতিতে সিটিতে ওবজেসি কোড মোড়ানো পছন্দ করেন? কারণ, আমি মাঝে মাঝে সি ফাংশন দেখতে পাই এবং ব্যবহারের পার্থক্য করতে পারি না। সি এর মোড়ক কোড কোনও কর্মক্ষমতা সুবিধা প্রদান করে?
ওজবোজ

1
@ ওজবোজ এমন পরিস্থিতিতে যেখানে কোন শ্রেণীর অন্তর্ভুক্ত হওয়া selfউচিত তা অবিলম্বে পরিষ্কার নয় ।
আদিব 16'15

8

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

-(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;
}

getSomething:উদ্দেশ্য নামক পদ্ধতিতে নামকরণের পদ্ধতিগুলি এড়ানো উচিত । এর একটি বিশেষ অর্থ রয়েছে (আরও: কোকোএডেভেন্ট্রাল.com / articles / 000082.php ) এবং আপনি আপনার কোডগুলিতে এই প্রয়োজনীয়তাগুলি পূরণ করেন না।
লাইভ

7
@ বাস্তবায়ন ইউআইওয়াইন্ডো (এক্সটেনশনগুলি)

- (ইউআইভিউকন্ট্রোলার *) শীর্ষমোস্টকন্ট্রোলার
{
    ইউআইভিউকন্ট্রোলার * শীর্ষকন্ট্রোলার = [স্ব রুটভিউকন্ট্রোলার];

    যখন (শীর্ষকন্ট্রোলআর.প্রেজডভিউকন্ট্রোলার) {
        শীর্ষকন্ট্রোলার = শীর্ষকন্ট্রোলআর.প্রেজডভিউকন্ট্রোলার;
    }

    রিটার্ন শীর্ষকন্ট্রোলার;
}

@শেষ

আমি মনে করি না আপনি মূল পোস্টে বর্ণিত শর্তটি সন্তুষ্ট করেছেন।
হট লিক্স

7
- (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;
    }
}

আমি এটি ব্যবহার করেছি, তবে মনে রাখবেন যে যখন সেখানে একাধিক উপস্থাপিত নিয়ন্ত্রক উপস্থিত থাকে তখন তা ভেঙে যায়
চক বরিস

7

সর্বশেষতম সুইফ্ট সংস্করণের জন্য:
একটি ফাইল তৈরি করুন, নাম দিন UIWindowExtension.swiftএবং নীচের স্নিপেটটি পেস্ট করুন:

import UIKit

public extension UIWindow {
    public var visibleViewController: UIViewController? {
        return UIWindow.getVisibleViewControllerFrom(self.rootViewController)
    }

    public static func getVisibleViewControllerFrom(vc: UIViewController?) -> UIViewController? {
        if let nc = vc as? UINavigationController {
            return UIWindow.getVisibleViewControllerFrom(nc.visibleViewController)
        } else if let tc = vc as? UITabBarController {
            return UIWindow.getVisibleViewControllerFrom(tc.selectedViewController)
        } else {
            if let pvc = vc?.presentedViewController {
                return UIWindow.getVisibleViewControllerFrom(pvc)
            } else {
                return vc
            }
        }
    }
}

func getTopViewController() -> UIViewController? {
    let appDelegate = UIApplication.sharedApplication().delegate
    if let window = appDelegate!.window {
        return window?.visibleViewController
    }
    return nil
}

এটি যে কোনও জায়গায় যেমন ব্যবহার করুন:

if let topVC = getTopViewController() {

}

আমি আপনার উত্তরটি খুব বেশি পরিবর্তন করতে চাই না তবে কয়েকটি বিষয় প্রস্তাব করব। 1. ইউআইএসপ্লিটভিউ কনট্রোলারের জন্য সমর্থন যুক্ত করুন। 2. switchঅন্যটি ব্যবহার না করে ব্যবহার করুন। ৩. নিশ্চিত না যে আপনার পাশাপাশি একটি স্ট্যাটিক ফাংশনও দরকার, আমি মনে করি আপনি এটি প্রথম বারের স্তর হিসাবে ঘোষণা করেছেন যাতে আপনি এটি সহজেই করতে পারেন। ৪. অনেকগুলি বিশ্বব্যাপী ফাংশন তৈরি না করা সম্ভবত সেরা তবে এটি স্বাদের বিষয়। আপনি বিশ্বব্যাপী ফাংশনটির প্রভাব অর্জন করতে কোডের একটি লাইন ব্যবহার করতে পারেন:UIApplication.sharedApplication().delegate?.window?.visibleViewController
জর্ডান স্মিথ

7

UIApplicationসুইফ্টের জন্য সাধারণ এক্সটেনশন :

বিঃদ্রঃ:

এটা তোলে বজায় রাখে moreNavigationControllerমধ্যেUITabBarController

extension UIApplication {

    class func topViewController(baseViewController: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {

        if let navigationController = baseViewController as? UINavigationController {
            return topViewController(navigationController.visibleViewController)
        }

        if let tabBarViewController = baseViewController as? UITabBarController {

            let moreNavigationController = tabBarViewController.moreNavigationController

            if let topViewController = moreNavigationController.topViewController where topViewController.view.window != nil {
                return topViewController(topViewController)
            } else if let selectedViewController = tabBarViewController.selectedViewController {
                return topViewController(selectedViewController)
            }
        }

        if let splitViewController = baseViewController as? UISplitViewController where splitViewController.viewControllers.count == 1 {
            return topViewController(splitViewController.viewControllers[0])
        }

        if let presentedViewController = baseViewController?.presentedViewController {
            return topViewController(presentedViewController)
        }

        return baseViewController
    }
}

সাধারণ ব্যবহার:

if let topViewController = UIApplication.topViewController() {
    //do sth with top view controller
}

হ্যাঁ হ্যাঁ - টপমাস্টভিউ কনট্রোলার সন্ধানের জন্য ওয়েবে চারপাশে অনেকগুলি সমাধান রয়েছে তবে আপনি যদি অ্যাপ্লিকেশনটিতে আরও একটি ট্যাব সহ ট্যাব বার রাখেন তবে আপনাকে এটি অন্যরকমভাবে পরিচালনা করতে হবে।
অ্যান্ডি ওবুসেক

7

বর্তমান দৃশ্যমান দখল করতে নীচে এক্সটেনশন ব্যবহার করুন UIViewController। সুইফট ৪.০ এবং তারপরে কাজ করেছেন

সুইফট ৪.০ এবং তারপরে:

extension UIApplication {
    
    class func topViewController(_ viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let nav = viewController as? UINavigationController {
            return topViewController(nav.visibleViewController)
        }
        if let tab = viewController as? UITabBarController {
            if let selected = tab.selectedViewController {
                return topViewController(selected)
            }
        }
        if let presented = viewController?.presentedViewController {
            return topViewController(presented)
        }
        return viewController
    }
}

ব্যবহারবিধি?

let objViewcontroller = UIApplication.topViewController()

করা উচিত নয় জন্য এই পরীক্ষাটি presentedViewControllerপ্রথম, আগে UINavigationControllerএবং UITabBarControllerমামলা? অন্যথায়, যদি কোনও ভিউ কন্ট্রোলার মডেলরূপে একটি UINavigationControllerবা থেকে উপস্থাপন করা হয় UITabBarController, তবে এটি দৃশ্যমান দৃশ্যত নিয়ন্ত্রক সত্ত্বেও এটি শীর্ষ ভিউ নিয়ন্ত্রক হিসাবে ফিরে আসবে না।
ড্র হয়েছে

4

তবুও অন্য সুইফট সমাধান

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)

}

4

সুইফট 4.2 এক্সটেনশন


extension UIApplication {

    class func topViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }
        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }
        if let presented = controller?.presentedViewController {


            return topViewController(controller: presented)
        }
        return controller
    }
}

এটিকে যে কোনও জায়গা থেকে ব্যবহার করুন,

 UIApplication.topViewController()?.present(yourController, animated: true, completion: nil)

বা মত,

 UIApplication.topViewController()?
                    .navigationController?
                    .popToViewController(yourController,
                                         animated: true)

ইউআইএনএভিগেশন কন্ট্রোলার, ইউআইটিববারকন্ট্রোলারের মতো যেকোন ক্লাসে ফিট করুন

উপভোগ করুন!


1
@ বিলালবাখরোম বলেছেন "আপভোটড। আমি মনে করি আপনার উত্তরটি সবচেয়ে ভাল। আপনি সরাসরি শীর্ষ ভিউকন্ট্রোলার () পদ্ধতিতে কল করতে পারবেন না। ইউআইএপ্লিকেশন ক্লাসটি সিঙ্গলটন," শেয়ারড "নামে একটি উদাহরণ ব্যবহার করুন।" এমন একটি সম্পাদনায় যা আমি প্রত্যাখ্যান করার পক্ষে ভোট দিয়েছি। যদি এটি প্রকৃতপক্ষে সঠিক হয় তবে দয়া করে একটি মেনুতে নিয়ে যেতে এখানে ক্লিক করুন যেখানে আপনি সেই সম্পাদনাটি অনুমোদন করতে পারেন।
wizzwizz4

3

আমার জন্য যা কাজ করেছে তা এখানে।

আমি দেখতে পেলাম যে কখনও কখনও কন্ট্রোলার কী উইন্ডোতে শূন্য থাকে, কারণ কী উইন্ডো কিছু ওএস জিনিস যেমন একটি সতর্কতা ইত্যাদি etc.

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

     if (topController == nil)
     {
         // The windows in the array are ordered from back to front by window level; thus,
         // the last window in the array is on top of all other app windows.
         for (UIWindow *aWndow in [[UIApplication sharedApplication].windows reverseObjectEnumerator])
         {
             topController = aWndow.rootViewController;
             if (topController)
                 break;
         }
     }

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

     return topController;
 }

3

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

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

- (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;
}

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


আপনি কি এটি একটি সম্পূর্ণ সমাধান হিসাবে খুঁজে পেয়েছেন? সুতরাং অন্যান্য উত্তরগুলির মধ্যে অনেকগুলি অত্যন্ত জটিল, এতগুলি প্রান্তের ক্ষেত্রে অ্যাকাউন্ট দেওয়ার চেষ্টা করছে। আমি এটি সত্য হতে চাই , এটি এত সহজ এবং মার্জিত।
লে মোট জুসেড

আমি এটি নিয়ে কখনও সমস্যা করি নি। যদি আপনি আপনার এনএভি স্ট্যাকের সাথে অস্বাভাবিক কিছু না করে থাকেন তবে এটি কাজ করা উচিত, অন্যথায় কিছু অন্যান্য সমাধান আরও জটিল ক্ষেত্রে পরিচালনা করে।
স্টেকেনবার্গ

3

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

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

    return topController!
}

3

এই সমাধানটি সবচেয়ে সম্পূর্ণ। এটি বিবেচনায় নেওয়া হয়: ইউআইএনএভিগেশন কন্ট্রোলার ইউআইপিএজভিউ কনট্রোলার ইউআইটিববারকন্ট্রোলার এবং শীর্ষ প্রদর্শনী নিয়ন্ত্রক থেকে শীর্ষতম উপস্থাপিত ভিউ কন্ট্রোলার

উদাহরণটি সুইফট 3-এ।

3 টি ওভারলোড রয়েছে

//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
}

3

সুইফট ৪.২-তে একটি সংক্ষিপ্ত এবং বিস্তৃত সমাধান ইউআইএনএভিগেশন কন্ট্রোলারস , ইউআইটিববারকন্ট্রোলারগণ , উপস্থাপিত এবং শিশু দর্শন নিয়ন্ত্রকদের বিবেচনা করে:

extension UIViewController {
  func topmostViewController() -> UIViewController {
    if let navigationVC = self as? UINavigationController,
      let topVC = navigationVC.topViewController {
      return topVC.topmostViewController()
    }
    if let tabBarVC = self as? UITabBarController,
      let selectedVC = tabBarVC.selectedViewController {
      return selectedVC.topmostViewController()
    }
    if let presentedVC = presentedViewController {
      return presentedVC.topmostViewController()
    }
    if let childVC = children.last {
      return childVC.topmostViewController()
    }
    return self
  }
}

extension UIApplication {
  func topmostViewController() -> UIViewController? {
    return keyWindow?.rootViewController?.topmostViewController()
  }
}

ব্যবহার:

let viewController = UIApplication.shared.topmostViewController()

2

সুইফটে দুর্দান্ত সমাধান, অ্যাপডেলিগেটে প্রয়োগ করুন

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
}

1

আমি মনে করি বেশিরভাগ উত্তর সম্পূর্ণরূপে উপেক্ষা করেছে 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;
}

1

আমি জানি এটির খুব দেরী এবং এটি অতিরিক্ত কাজ হতে পারে। তবে নীচে আমি যে স্নিপেট নিয়ে এসেছি যা আমার জন্য কাজ করছে:

    static func topViewController() -> UIViewController? {
        return topViewController(vc: UIApplication.shared.keyWindow?.rootViewController)
    }

    private static func topViewController(vc:UIViewController?) -> UIViewController? {
        if let rootVC = vc {
            guard let presentedVC = rootVC.presentedViewController else {
                return rootVC
            }
            if let presentedNavVC = presentedVC as? UINavigationController {
                let lastVC = presentedNavVC.viewControllers.last
                return topViewController(vc: lastVC)
            }
            return topViewController(vc: presentedVC)
        }
        return nil
    }

0

এটি যে কোনও রুট ভিউ নিয়ন্ত্রণ থেকে শীর্ষ ভিউ কনট্রোলার 1 সন্ধানের জন্য দুর্দান্ত কাজ করে

+ (UIViewController *)topViewControllerFor:(UIViewController *)viewController
{
    if(!viewController.presentedViewController)
        return viewController;
    return [MF5AppDelegate topViewControllerFor:viewController.presentedViewController];
}

/* View Controller for Visible View */

AppDelegate *app = [UIApplication sharedApplication].delegate;
UIViewController *visibleViewController = [AppDelegate topViewControllerFor:app.window.rootViewController]; 

0

এটি শীর্ষস্থানীয় দর্শনীয় নিয়ামক সন্ধান করে আপনি যা অর্জন করতে চাইছেন তাতে সহায়তা করবে কিনা তা নিশ্চিত নই, তবে আমি একটি নতুন দর্শন নিয়ামক উপস্থাপনের চেষ্টা করছিলাম তবে আমার রুট ভিউ কন্ট্রোলারটির যদি ইতিমধ্যে একটি মডেল ডায়ালগ থাকে তবে এটি অবরুদ্ধ হয়ে যাবে, তাই আমি এই কোডটি ব্যবহার করে সমস্ত মডেল ভিউ কন্ট্রোলারের শীর্ষে চক্রটি প্রবেশ করবে:

UIViewController* parentController =[UIApplication sharedApplication].keyWindow.rootViewController;

while( parentController.presentedViewController &&
       parentController != parentController.presentedViewController )
{
    parentController = parentController.presentedViewController;
}

0

আপনি ব্যবহার করে শীর্ষ সর্বাধিক দেখার নিয়ামক খুঁজে পেতে পারেন

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

তা বাদে, আপনি যদি আসলে প্রশ্নটি পড়ে থাকেন তবে selfকোনও navigationControllerসম্পত্তি নেই।
হট লিক্স

0

আর একটি সমাধান প্রতিক্রিয়াশীল চেইনের উপর নির্ভর করে, যা প্রথম উত্তরদাতা কী তার উপর নির্ভর করে কাজ করতে পারে বা নাও করতে পারে:

  1. প্রথম উত্তরদাতা পান Get
  2. সেই প্রথম প্রতিক্রিয়াকারীর সাথে যুক্ত ইউআইভিউকন্ট্রোলার পান

সিউডো কোড উদাহরণ:

+ (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;
}

0

সুইফট:

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)
        }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.