AppDelegate.m তে স্ক্রিনে বর্তমান প্রদর্শিত ইউআইভিউকন্ট্রোলারটি পান


126

UIViewControllerপর্দার বর্তমানটির জন্য কিছু ব্যাজ মতামত সেট করে, APN গুলি থেকে পুশ-বিজ্ঞপ্তিগুলির প্রতিক্রিয়া জানানো দরকার। কিন্তু কিভাবে আমি পেতে পারে UIViewControllerপদ্ধতিতে application:didReceiveRemoteNotification: এর AppDelegate.m?

আমি self.window.rootViewControllerবর্তমান প্রদর্শনের জন্য ব্যবহারের চেষ্টা করেছি UIViewController, এটি এক UINavigationViewControllerবা অন্য কোনও ধরণের ভিউ কন্ট্রোলার হতে পারে। এবং আমি খুঁজে পেয়েছি যে এর visibleViewControllerসম্পত্তিটি স্ক্রিনে UINavigationViewControllerপেতে ব্যবহার করা যেতে পারে UIViewController। তবে এটি না হলে আমি কী করতে পারি UINavigationViewController?

কোন সাহায্য প্রশংসা করা হয়! সম্পর্কিত কোডটি নিম্নরূপ:

AppDelegate.m

...
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    //I would like to find out which view controller is on the screen here.

    UIViewController *vc = [(UINavigationViewController *)self.window.rootViewController visibleViewController];
    [vc performSelector:@selector(handleThePushNotification:) withObject:userInfo];
}
...

ViewControllerA.m

- (void)handleThePushNotification:(NSDictionary *)userInfo{

    //set some badge view here

}

উত্তর:


99

rootViewControllerআপনার নিয়ামক যখন না হয় তখন আপনি এটিও ব্যবহার করতে পারেন UINavigationController:

UIViewController *vc = self.window.rootViewController;

একবার আপনি রুট ভিউ কন্ট্রোলারটি জানলে, তারপরে আপনি কীভাবে আপনার ইউআই তৈরি করেছেন তার উপর নির্ভর করে তবে আপনি নিয়ন্ত্রকদের স্তরক্রমের মাধ্যমে নেভিগেটের কোনও উপায় খুঁজে পেতে পারেন।

আপনি নিজের অ্যাপটি যেভাবে সংজ্ঞায়িত করেছেন সে সম্পর্কে যদি আপনি আরও কিছু বিবরণ দেন তবে আমি আরও কিছু ইঙ্গিত দিতে পারি।

সম্পাদনা করুন:

আপনি যদি শীর্ষস্থানীয় দর্শন চান (নিয়ন্ত্রক দেখেন না), আপনি পরীক্ষা করতে পারেন

[[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];

যদিও এই দৃশ্যটি অদৃশ্য হতে পারে বা এমনকি এর কয়েকটি উপদর্শন দ্বারা কভার করা হয়েছে ...

আবার এটি আপনার ইউআই এর উপর নির্ভর করে তবে এটি সাহায্য করতে পারে ...


19
এর সাথে সমস্যাটি যদি দৃশ্যমান দর্শনটি রুট ভিউ নিয়ন্ত্রকের অন্তর্ভুক্ত না হয় (মডেল ভিউ এবং এ জাতীয় ক্ষেত্রে)।
দিমা

হ্যাঁ আমি কি. তবে এটি সম্ভবত কোনও ইউআইটিবভিউ কনট্রোলার। স্ক্রিনে ইউআইভিউউকন্ট্রোলার পাওয়ার জন্য কোনও সরাসরি পদ্ধতি নেই?
লু ইউয়ান

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

1
যতক্ষণ মানটি আপ টু ডেট থাকে ততক্ষণ আমার কাছে যাওয়ার ভাল উপায় বলে মনে হয়।
ডিমা

4
কোনও UIViewউদাহরণ থেকে নিয়ামকের কাছে যাওয়ার সরাসরি কোনও উপায় নেই । rootViewControllerহয় না অগত্যা বর্তমানে দেখানো নিয়ামক। এটি দেখুন শ্রেণিবিন্যাসের শীর্ষে।
জিঙ্গি

101

আমি সর্বদা সমাধানগুলিতে পছন্দ করি যা বিভাগগুলিতে জড়িত থাকে কারণ সেগুলি বোল্ট হয় এবং সহজেই পুনরায় ব্যবহার করা যায়।

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

UIWindow + PazLabs.h (শিরোনাম ফাইল)

#import <UIKit/UIKit.h>

@interface UIWindow (PazLabs)

- (UIViewController *) visibleViewController;

@end

UIWindow + PazLabs.m (বাস্তবায়ন ফাইল)

#import "UIWindow+PazLabs.h"

@implementation UIWindow (PazLabs)

- (UIViewController *)visibleViewController {
    UIViewController *rootViewController = self.rootViewController;
    return [UIWindow getVisibleViewControllerFrom:rootViewController];
}

+ (UIViewController *) getVisibleViewControllerFrom:(UIViewController *) vc {
    if ([vc isKindOfClass:[UINavigationController class]]) {
        return [UIWindow getVisibleViewControllerFrom:[((UINavigationController *) vc) visibleViewController]];
    } else if ([vc isKindOfClass:[UITabBarController class]]) {
        return [UIWindow getVisibleViewControllerFrom:[((UITabBarController *) vc) selectedViewController]];
    } else {
        if (vc.presentedViewController) {
            return [UIWindow getVisibleViewControllerFrom:vc.presentedViewController];
        } else {
            return vc;
        }
    }
}

@end

সুইফট সংস্করণ

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

2
আমি কীভাবে এটি সুইফ্ট সংস্করণে ব্যবহার করতে পারি?
বিজয় সিং রানা

2
আমি আপনার প্রশ্ন বুঝতে পারি না। আপনার কোডের ভিতরে অনুলিপি করুন এবং আটকান।
zirinisp

কাস্টম ধারক উপাচার্য সম্পর্কে কি?
মিজিং

@ মিং মেশিং এটি অতিরিক্ত কাস্টম কনটেইনার ভিসি (getVisibielController পদ্ধতিতে) আছে কিনা তা যাচাই করে নেওয়া এবং এটি যদি "দৃশ্যমান" নিয়ামকটি ফিরিয়ে দেয় তবে অতিরিক্ত সংযোজন করা শক্ত হওয়া উচিত নয়, যা বেশিরভাগ কাস্টমের জন্য সাধারণত vc.childControllers.lastObject ধারক ভিসি বাস্তবায়ন (আমি মনে করি), তবে এটি কীভাবে বাস্তবায়িত হয় তার উপর নির্ভর করবে।
গাডু

1
আমি শুধু একটি আপডেট সিনট্যাক্স ছাড়া এই উত্তর একই পদ্ধতির সঙ্গে একটি উত্তর পোস্ট: এটা একটি সুইচ-কেস ব্যবহার করে এবং সুইফট 3 নামকরণ নিয়মাবলী অনুসরণ করে আছে: stackoverflow.com/a/42486823/3451975
Jeehut

43

সুইফটে ইউআইএ অ্যাপ্লিকেশনটির জন্য সহজ বর্ধন ( UITabBarControllerআইফোনের মধ্যে নেভিগেশন নিয়ন্ত্রণকারীকে আরও বেশি যত্ন করে) :

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

        if let nav = base as? UINavigationController {
            return topViewController(base: nav.visibleViewController)
        }

        if let tab = base as? UITabBarController {
            let moreNavigationController = tab.moreNavigationController

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

        if let presented = base?.presentedViewController {
            return topViewController(base: presented)
        }

        return base
    }
}

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

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

নিখুঁত কাজ করে :-)

পরিষ্কার কোডের জন্য আপডেট করুন:

extension UIViewController {
    var top: UIViewController? {
        if let controller = self as? UINavigationController {
            return controller.topViewController?.top
        }
        if let controller = self as? UISplitViewController {
            return controller.viewControllers.last?.top
        }
        if let controller = self as? UITabBarController {
            return controller.selectedViewController?.top
        }
        if let controller = presentedViewController {
            return controller.top
        }
        return self
    }
}

1
এটি সুইফট ২.x এর কোড বলে মনে হচ্ছে। সুইফট 3.x এর আর "কোথায়" নেই। এছাড়াও, "শেয়ারড অ্যাপ্লিকেশন ()" এখন "শেয়ার করা"। তেমন কিছু না. এটি আপডেট হতে কেবল এক মিনিট সময় নেয়। এটি পুনরাবৃত্তি ব্যবহার করে তা উল্লেখ করা ভাল। এছাড়াও, শীর্ষে ভিউকন্ট্রোলারের প্রতিটি কলের "বেস:" উপসর্গের প্রয়োজন।
জেফ মুইর

37

আপনি এনএসএনটিফিকেশন সেন্টারের মাধ্যমেও একটি বিজ্ঞপ্তি পোস্ট করতে পারেন। এটি আপনাকে বেশ কয়েকটি পরিস্থিতিতে মোকাবিলা করতে দেয় যেখানে ভিউ কন্ট্রোলার হায়ারার্কি ট্র্যাভার করা জটিল হতে পারে - উদাহরণস্বরূপ যখন মডেলগুলি উপস্থাপন করা হয় ইত্যাদি etc.

যেমন,

// MyAppDelegate.h
NSString * const UIApplicationDidReceiveRemoteNotification;

// MyAppDelegate.m
NSString * const UIApplicationDidReceiveRemoteNotification = @"UIApplicationDidReceiveRemoteNotification";

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    [[NSNotificationCenter defaultCenter]
     postNotificationName:UIApplicationDidReceiveRemoteNotification
     object:self
     userInfo:userInfo];
}

আপনার প্রতিটি ভিউ কন্ট্রোলারে:

-(void)viewDidLoad {
    [[NSNotificationCenter defaultCenter] 
      addObserver:self
      selector:@selector(didReceiveRemoteNotification:)                                                  
      name:UIApplicationDidReceiveRemoteNotification
      object:nil];
}

-(void)viewDidUnload {
    [[NSNotificationCenter defaultCenter] 
      removeObserver:self
      name:UIApplicationDidReceiveRemoteNotification
      object:nil];
}

-(void)didReceiveRemoteNotification:(NSDictionary *)userInfo {
    // see http://stackoverflow.com/a/2777460/305149
   if (self.isViewLoaded && self.view.window) {
      // handle the notification
   }
}

আপনি ইনস্ট্রুমেন্ট কন্ট্রোলগুলিতেও এই পদ্ধতির ব্যবহার করতে পারেন যা কোনও নোটিফিকেশন পাওয়ার পরে আপডেট হওয়া দরকার এবং বেশ কয়েকটি ভিউ কন্ট্রোলার ব্যবহার করেন। সেক্ষেত্রে যথাক্রমে আর ডি এবং ডালোক পদ্ধতিতে পর্যবেক্ষকদের অ্যাড / রিমুভাল পরিচালনা করুন।


1
addObserver:barভিতরে কি আছে viewDidLoad? আমার সাথে selfকি প্রতিস্থাপন করতে হবে ?
কায়নাসুজা

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

ইউজারআইএনফো থেকে সমস্ত কীগুলি পেয়ে যাওয়ার সময় ক্র্যাশ .. কোনও ধারণা? [এনএস কনক্রিটনোটিকেশন অলকিজ]: অবিজ্ঞাত নির্বাচক 0x1fd87480 2013-07-05 16: 10: 36.469 প্রভিডেন্স [2961: 907] *** অব্যাহত ব্যতিক্রমের কারণে 'এনএসআইটিওয়েডআরগমেন্টএক্সেপশন', কারণ: '- [এনএসসিক্রিটনিটিকেশন অলঙ্করণ নির্বাচক উদাহরণ হিসাবে 0x1fd87480 'পাঠিয়েছেন
আওস তারিক

@ আওসতরীক - হুম্ম - আমার ধারণা হ'ল আইওএসের দ্বারা ডিগ্রিভিউরমিটনিটিফিকেশন পাস করা বস্তুটি আসলে কোনও এনএসডোরিয়ানো নয়, কারণ ইন্টারফেসটি নির্দিষ্ট করে।
আনিল মল্লালাপাড়ু

যদি ব্যবহারকারী এখনও আপনার পর্যবেক্ষক শ্রেণিতে নেভিগেট না করে থাকে? : /
হালবানো

15

কোড

এখানে মহান ব্যবহার করে একটি প্রবেশপথ সুইচ-কেস সিনট্যাক্স মধ্যে সুইফট 3/4/5 :

extension UIWindow {
    /// Returns the currently visible view controller if any reachable within the window.
    public var visibleViewController: UIViewController? {
        return UIWindow.visibleViewController(from: rootViewController)
    }

    /// Recursively follows navigation controllers, tab bar controllers and modal presented view controllers starting
    /// from the given view controller to find the currently visible view controller.
    ///
    /// - Parameters:
    ///   - viewController: The view controller to start the recursive search from.
    /// - Returns: The view controller that is most probably visible on screen right now.
    public static func visibleViewController(from viewController: UIViewController?) -> UIViewController? {
        switch viewController {
        case let navigationController as UINavigationController:
            return UIWindow.visibleViewController(from: navigationController.visibleViewController ?? navigationController.topViewController)

        case let tabBarController as UITabBarController:
            return UIWindow.visibleViewController(from: tabBarController.selectedViewController)

        case let presentingViewController where viewController?.presentedViewController != nil:
            return UIWindow.visibleViewController(from: presentingViewController?.presentedViewController)

        default:
            return viewController
        }
    }
}

মূল ধারণাটি জিরিনিস্পের উত্তরের মতো, এটি সিনট্যাক্সের মতো আরও বেশি সুইফ্ট 3+ ব্যবহার করছে।


ব্যবহার

আপনি সম্ভবত একটি ফাইল তৈরি করতে চান UIWindowExtension.swift। নিশ্চিত করুন যে এতে import UIKitবিবৃতি রয়েছে , এখন উপরের এক্সটেনশন কোডটি অনুলিপি করুন

কল সাইডে এটি হয় কোনও নির্দিষ্ট ভিউ নিয়ন্ত্রক ছাড়াই ব্যবহার করা যেতে পারে :

if let visibleViewCtrl = UIApplication.shared.keyWindow?.visibleViewController {
    // do whatever you want with your `visibleViewCtrl`
}

বা যদি আপনি জানেন যে আপনার দৃশ্যমান দৃশ্যের নিয়ামকটি একটি নির্দিষ্ট দর্শন নিয়ামক থেকে পৌঁছতে পারে :

if let visibleViewCtrl = UIWindow.visibleViewController(from: specificViewCtrl) {
    // do whatever you want with your `visibleViewCtrl`
}

আমি আসা করি এটা সাহায্য করবে!


অসীম পুনরাবৃত্তির কারণে তৃতীয় কেস ক্রাশ হবে। ফিক্সটি হ'ল ভিসিটির নাম পরিবর্তন করা presentingViewControllerএবং presentingViewController.presentedViewControllerপরামিতি হিসাবে পুনরাবৃত্ত পদ্ধতিতে পাস করা।
ইখসান আসআত

দুঃখিত, আমি এটি বেশ পেলাম না। আপনার মানে এর UIWindow.visibleViewController(from: presentedViewController)পরিবর্তে হওয়া উচিত UIWindow.visibleViewController(from: presentingViewController.presentedViewController)?
জেহুত

সঠিক, presentedViewControllerএবং viewControllerএকই বস্তু এবং এটি স্ট্যাকটি ওভারফ্লো না হওয়া অবধি পদ্ধতিটিকে নিজের সাথে কল করবে (পাং উদ্দেশ্যে)। সুতরাং এটি হবে case let presentingViewController where viewController?.presentedViewController != nil: return UIWindow.visibleViewController(from: presentingViewController.presentedViewController)
ইখসান আসআআত

1
এই সমাধানটি কাজ করেছিল যখন অন্যরা না করে। আপনার সুইফট 5 এ আপডেট করা উচিত মূলত কোনও পরিবর্তন নেই। আপনার উত্তরের জন্য কেবল শিরোনাম আপডেট করুন।
টিএম লঞ্চ

14

আমি খুঁজে পেয়েছি যে আইওএস 8 সমস্ত কিছু ছড়িয়ে দিয়েছে। আইওএস 7-এ UITransitionViewযখনই আপনি কোনও মডেল উপস্থাপন করেন তখন ভিউ হায়ারার্কিতে একটি নতুন রয়েছে UINavigationController। যাইহোক, এখানে আমার কোড যা সন্ধান করে সর্বাধিকতম ভিসি পায়। কলিংয়ের মাধ্যমে getTopMostViewControllerএমন কোনও উপাচার্য ফিরে পাওয়া উচিত যা আপনার মতো বার্তা প্রেরণে সক্ষম হবে presentViewController:animated:completion। এর উদ্দেশ্য হ'ল আপনাকে এমন একটি ভিসি দেওয়া যা আপনি কোনও মডেল ভিসি উপস্থাপন করতে ব্যবহার করতে পারেন, সুতরাং এটি সম্ভবত থামবে এবং UINavigationControllerতাদের মধ্যে থাকা ভিসির মতো নয় এবং ধারক শ্রেণিতে ফিরে আসবে । এটি করার জন্য কোডটি মানিয়ে নেওয়া কঠিন হওয়া উচিত নয়। আমি এই কোডটি আইওএস 6, 7 এবং 8 এ বিভিন্ন পরিস্থিতিতে পরীক্ষা করেছি Please দয়া করে আপনি বাগগুলি খুঁজে পান কিনা তা আমাকে জানান।

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

    for (UIView *subView in [window subviews])
    {
        UIResponder *responder = [subView nextResponder];

        //added this block of code for iOS 8 which puts a UITransitionView in between the UIWindow and the UILayoutContainerView
        if ([responder isEqual:window])
        {
            //this is a UITransitionView
            if ([[subView subviews] count])
            {
                UIView *subSubView = [subView subviews][0]; //this should be the UILayoutContainerView
                responder = [subSubView nextResponder];
            }
        }

        if([responder isKindOfClass:[UIViewController class]]) {
            return [self topViewController: (UIViewController *) responder];
        }
    }

    return nil;
}

+ (UIViewController *) topViewController: (UIViewController *) controller
{
    BOOL isPresenting = NO;
    do {
        // this path is called only on iOS 6+, so -presentedViewController is fine here.
        UIViewController *presented = [controller presentedViewController];
        isPresenting = presented != nil;
        if(presented != nil) {
            controller = presented;
        }

    } while (isPresenting);

    return controller;
}

দয়া করে সদৃশ জবাবগুলি দেবেন না - হয় প্রশ্নগুলি হ'ল ডুপ্লিকেট হিসাবে চিহ্নিত করুন বা স্বতন্ত্র প্রশ্নের যথাযথ উত্তর দিয়ে উত্তর দিন যদি তারা সদৃশ না হয় তবে।
ফ্লেক্সো

13

অন্যান্য সমস্ত সমাধানের চেয়ে কম কোড:

উদ্দেশ্য-সি সংস্করণ:

- (UIViewController *)getTopViewController {
    UIViewController *topViewController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
    while (topViewController.presentedViewController) topViewController = topViewController.presentedViewController;

    return topViewController;
}

সুইফট ২.০ সংস্করণ: (ক্রেডিট স্টিভ.বি তে যায়)

func getTopViewController() -> UIViewController {
    var topViewController = UIApplication.sharedApplication().delegate!.window!!.rootViewController!
    while (topViewController.presentedViewController != nil) {
        topViewController = topViewController.presentedViewController!
    }
    return topViewController
}

এমনকি মডেলগুলি সহ আপনার অ্যাপ্লিকেশনটিতে যে কোনও জায়গায় কাজ করে।


1
এটি এমন পরিস্থিতি পরিচালনা করে না যেখানে উপস্থাপিত ভিউ কন্ট্রোলার UINavigationControllerযার নিজস্ব সন্তান রয়েছে has
লেভিগ্রোকার

@ লিভিগ্রোকার, সম্ভবত আপনি নিজের দৃষ্টিভঙ্গিটিই এভাবেই স্থির করেছেন? এটি একটি নাভির সাথে ব্যবহার করা আমার পক্ষে ঠিক কাজ করে। (এইভাবে আমি এটি ব্যবহার করছি)
জাংলেদেভ

@ জাংলেদেভ আমি নিশ্চিত আপনি ঠিক আছেন এটি বলেছে যে সমস্ত দ্রষ্টব্য নিয়ামক কনফিগারেশনে কাজ করে এমন একটি সমাধান যা প্রয়োজন।
লেভিগ্রোকার

@levigroker এটা করে সব মান ভিসি কাজ configurations- সত্যিই একটি জটিল স্থাপত্য রয়েছে অ্যাপ্লিকেশান আমি কাজ, 500K বেশি ব্যবহারকারীদের দ্বারা ব্যবহৃত হয়, এবং অ্যাপ্লিকেশান সর্বত্র এই কাজ করে। কোডের উদাহরণ সহ আপনার দৃষ্টিভঙ্গি কেন কাজ করে না এমন প্রশ্ন করে আপনার একটি পোস্ট পোস্ট করা উচিত?
জংলেদেব

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

8

সুইফটে জিরিনিস্পের উত্তর:

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

এটি as!এবং navigationController.visibleViewController!সুইফট ২.০ এর জন্য
লিনাসেফার্থ

7

প্রতিটি ভিউকন্ট্রোলারের শিরোনাম নির্দিষ্ট করুন এবং তারপরে নীচে দেওয়া কোড দিয়ে বর্তমান ভিউকন্ট্রোলারের শিরোনাম পান।

-(void)viewDidUnload {
  NSString *currentController = self.navigationController.visibleViewController.title;

তারপরে এটি আপনার শিরোনাম দ্বারা এটি পরীক্ষা করুন

  if([currentController isEqualToString:@"myViewControllerTitle"]){
    //write your code according to View controller.
  }
}

খুব ভাল উত্তর, আপনি নিজের ভিউ কনট্রোলারের সাথে নামও লিখে রাখতে পারেন:self.title = myPhotoView
রেস্টি

5

আমার টা ভালো! :)

extension UIApplication {
    var visibleViewController : UIViewController? {
        return keyWindow?.rootViewController?.topViewController
    }
}

extension UIViewController {
    fileprivate var topViewController: UIViewController {
        switch self {
        case is UINavigationController:
            return (self as! UINavigationController).visibleViewController?.topViewController ?? self
        case is UITabBarController:
            return (self as! UITabBarController).selectedViewController?.topViewController ?? self
        default:
            return presentedViewController?.topViewController ?? self
        }
    }
}

4

অ্যাপের প্রতিনিধিটিতে কেবল পুশ বিজ্ঞপ্তি কোডটি হ্যান্ডেল করবেন না কেন? এটি সরাসরি কোনও দৃশ্যের সাথে সম্পর্কিত?

কোনও ইউআইভিউকন্ট্রোলারের দৃশ্য বর্তমানে দৃশ্যমান কিনা তা খতিয়ে দেখলে এর দর্শকের windowসম্পত্তির কোনও মূল্য আছে কিনা তা পরীক্ষা করে দেখতে পারেন । আরও এখানে দেখুন ।


হ্যাঁ, এটি একটি দৃশ্যের সাথে সম্পর্কিত, কারণ আমাকে ব্যাজ ভিউটি দেখাতে হবে। আমাকে লিঙ্কটি পরীক্ষা করতে দিন। আপনাকে ধন্যবাদ :)
লু ইউয়ান

4

@ জিরিনিস্প উত্তরের সাথে কেবল যোগ করুন।

একটি ফাইল তৈরি করুন, নাম দিন 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() {

}

@ জিরিনিস্পকে ধন্যবাদ।


3

উপরের এনএসএনটিফিকেশন সেন্টার পোস্ট সম্পর্কে (দুঃখিত এটির অধীনে কোনও মন্তব্য কোথায় পোস্ট করা যায় তা জানতে পারি না ...)

কিছু লোক যদি এরকম - [এনএসকনক্রিটনোটিকেশন অলকিজ] ত্রুটি পেয়ে থাকে। এই পরিবর্তন:

-(void)didReceiveRemoteNotification:(NSDictionary *)userInfo

এটি:

-(void)didReceiveRemoteNotification:(NSNotification*)notif {
NSDictionary *dict = notif.userInfo;
}

3

এটি আমার পক্ষে কাজ করেছে। আমার অনেক টার্গেট রয়েছে যার বিভিন্ন কন্ট্রোলার রয়েছে তাই আগের উত্তরগুলি কাজ করে বলে মনে হয় নি।

প্রথমে আপনি এটি আপনার অ্যাপডেলিগেট ক্লাসের মধ্যে চান:

var window: UIWindow?

তারপরে, আপনার ফাংশনে

let navigationController = window?.rootViewController as? UINavigationController
if let activeController = navigationController!.visibleViewController {
    if activeController.isKindOfClass( MyViewController )  {
        println("I have found my controller!")    
   }
}

2

এটি আমি চেষ্টা করেছি সবচেয়ে ভাল উপায়। এটি যদি কারও সাহায্য করে ...

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

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

    return topController;
}

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

এটির সাহায্যে আপনি সহজেই শীর্ষ পোস্ট দেখার নিয়ামকটি পেতে পারেন

let viewController = UIApplication.topMostViewController

একটি বিষয় লক্ষণীয় হ'ল যদি বর্তমানে কোনও ইউআইএলার্টকন্ট্রোলার প্রদর্শিত হচ্ছে তবে এটি UIApplication.topMostViewControllerএকটি ফিরে আসবে UIAlertController


1

জঙ্গলেদেবের উত্তরের সুইফট ২.০ সংস্করণ

func getTopViewController() -> UIViewController {
    var topViewController = UIApplication.sharedApplication().delegate!.window!!.rootViewController!
    while (topViewController.presentedViewController != nil) {
        topViewController = topViewController.presentedViewController!
    }
    return topViewController
}

1

সম্পত্তি UIApplicationসহ আমি একটি বিভাগ তৈরি করেছি visibleViewControllers। মূল ধারণাটি বেশ সহজ। আমি swizzled viewDidAppearএবং viewDidDisappearপদ্ধতি মধ্যে UIViewController। ইন viewDidAppearপদ্ধতি viewController স্ট্যাক যোগ করা হয়। ইন viewDidDisappearপদ্ধতি viewController স্ট্যাক থেকে মুছে ফেলা হবে। দুর্বল উল্লেখগুলি সংরক্ষণ করার NSPointerArrayপরিবর্তে ব্যবহৃত হয় । এই পদ্ধতির কোনও ভিউকন্ট্রোলারদের শ্রেণিবিন্যাসের জন্য কাজ করে।NSArrayUIViewController

UIApplication + + VisibleViewControllers.h

#import <UIKit/UIKit.h>

@interface UIApplication (VisibleViewControllers)

@property (nonatomic, readonly) NSArray<__kindof UIViewController *> *visibleViewControllers;

@end

UIApplication + + VisibleViewControllers.m

#import "UIApplication+VisibleViewControllers.h"
#import <objc/runtime.h>

@interface UIApplication ()

@property (nonatomic, readonly) NSPointerArray *visibleViewControllersPointers;

@end

@implementation UIApplication (VisibleViewControllers)

- (NSArray<__kindof UIViewController *> *)visibleViewControllers {
    return self.visibleViewControllersPointers.allObjects;
}

- (NSPointerArray *)visibleViewControllersPointers {
    NSPointerArray *pointers = objc_getAssociatedObject(self, @selector(visibleViewControllersPointers));
    if (!pointers) {
        pointers = [NSPointerArray weakObjectsPointerArray];
        objc_setAssociatedObject(self, @selector(visibleViewControllersPointers), pointers, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return pointers;
}

@end

@implementation UIViewController (UIApplication_VisibleViewControllers)

+ (void)swizzleMethodWithOriginalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector {
    Method originalMethod = class_getInstanceMethod(self, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
    BOOL didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    if (didAddMethod) {
        class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self swizzleMethodWithOriginalSelector:@selector(viewDidAppear:)
                               swizzledSelector:@selector(uiapplication_visibleviewcontrollers_viewDidAppear:)];
        [self swizzleMethodWithOriginalSelector:@selector(viewDidDisappear:)
                               swizzledSelector:@selector(uiapplication_visibleviewcontrollers_viewDidDisappear:)];
    });
}

- (void)uiapplication_visibleviewcontrollers_viewDidAppear:(BOOL)animated {
    [[UIApplication sharedApplication].visibleViewControllersPointers addPointer:(__bridge void * _Nullable)self];
    [self uiapplication_visibleviewcontrollers_viewDidAppear:animated];
}

- (void)uiapplication_visibleviewcontrollers_viewDidDisappear:(BOOL)animated {
    NSPointerArray *pointers = [UIApplication sharedApplication].visibleViewControllersPointers;
    for (int i = 0; i < pointers.count; i++) {
        UIViewController *viewController = [pointers pointerAtIndex:i];
        if ([viewController isEqual:self]) {
            [pointers removePointerAtIndex:i];
            break;
        }
    }
    [self uiapplication_visibleviewcontrollers_viewDidDisappear:animated];
}

@end

https://gist.github.com/medvedzzz/e6287b99011f2437ac0beb5a72a897f0

সুইফট 3 সংস্করণ

UIApplication + + VisibleViewControllers.swift

import UIKit

extension UIApplication {

    private struct AssociatedObjectsKeys {
        static var visibleViewControllersPointers = "UIApplication_visibleViewControllersPointers"
    }

    fileprivate var visibleViewControllersPointers: NSPointerArray {
        var pointers = objc_getAssociatedObject(self, &AssociatedObjectsKeys.visibleViewControllersPointers) as! NSPointerArray?
        if (pointers == nil) {
            pointers = NSPointerArray.weakObjects()
            objc_setAssociatedObject(self, &AssociatedObjectsKeys.visibleViewControllersPointers, pointers, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        return pointers!
    }

    var visibleViewControllers: [UIViewController] {
        return visibleViewControllersPointers.allObjects as! [UIViewController]
    }
}

extension UIViewController {

    private static func swizzleFunc(withOriginalSelector originalSelector: Selector, swizzledSelector: Selector) {
        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
        let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
        if didAddMethod {
            class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }

    override open class func initialize() {
        if self != UIViewController.self {
            return
        }
        let swizzlingClosure: () = {
            UIViewController.swizzleFunc(withOriginalSelector: #selector(UIViewController.viewDidAppear(_:)),
                                         swizzledSelector: #selector(uiapplication_visibleviewcontrollers_viewDidAppear(_:)))
            UIViewController.swizzleFunc(withOriginalSelector: #selector(UIViewController.viewDidDisappear(_:)),
                                         swizzledSelector: #selector(uiapplication_visibleviewcontrollers_viewDidDisappear(_:)))
        }()
        swizzlingClosure
    }

    @objc private func uiapplication_visibleviewcontrollers_viewDidAppear(_ animated: Bool) {
        UIApplication.shared.visibleViewControllersPointers.addPointer(Unmanaged.passUnretained(self).toOpaque())
        uiapplication_visibleviewcontrollers_viewDidAppear(animated)
    }

    @objc private func uiapplication_visibleviewcontrollers_viewDidDisappear(_ animated: Bool) {
        let pointers = UIApplication.shared.visibleViewControllersPointers
        for i in 0..<pointers.count {
            if let pointer = pointers.pointer(at: i) {
                let viewController = Unmanaged<AnyObject>.fromOpaque(pointer).takeUnretainedValue() as? UIViewController
                if viewController.isEqual(self) {
                    pointers.removePointer(at: i)
                    break
                }
            }
        }
        uiapplication_visibleviewcontrollers_viewDidDisappear(animated)
    }
}

https://gist.github.com/medvedzzz/ee6f4071639d987793977dba04e11399


1

আপনি যদি নিজের অ্যাপটি ডিবাগ বা প্রকাশের সাথে চালাচ্ছেন তবে সর্বদা আপনার বিল্ড কনফিগারেশনটি পরীক্ষা করুন।

গুরুত্বপূর্ণ দ্রষ্টব্য: আপনি নিজের অ্যাপটি ডিবাগ মোডে না চালিয়ে পরীক্ষা করতে পারবেন না

এটি আমার সমাধান ছিল

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