ভিউউইলডিস্পিয়ার: ভিউ কন্ট্রোলার পপড হচ্ছে বা উপ-দর্শন নিয়ামক দেখাচ্ছে কিনা তা নির্ধারণ করুন


134

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

এই মুহুর্তে আমি যেমন পতাকা সেট করছি isShowingChildViewControllerতবে এটি বেশ জটিল হয়ে উঠছে। আমি মনে করি এটির একমাত্র উপায়টি -deallocপদ্ধতিতে রয়েছে।

উত্তর:


228

আপনি নিম্নলিখিত ব্যবহার করতে পারেন।

- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  NSArray *viewControllers = self.navigationController.viewControllers;
  if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
    // View is disappearing because a new view controller was pushed onto the stack
    NSLog(@"New view controller was pushed");
  } else if ([viewControllers indexOfObject:self] == NSNotFound) {
    // View is disappearing because it was popped from the stack
    NSLog(@"View controller was popped");
  }
}

এটি অবশ্যই সম্ভব, কারণ ইউআইএনএভিগেশন কন্ট্রোলারের ভিউ কন্ট্রোলার স্ট্যাক (ভিউকন্ট্রোলার্সের সম্পত্তি দ্বারা উদ্ঘাটিত করা) ভিউ উইলডিস্পায়ার বলা হওয়ার সময় আপডেট হয়েছিল।


2
পারফেক্ট! আমি কেন জানি না কেন জানি না! আমার ধারণা, গায়েব পদ্ধতিগুলি না বলা পর্যন্ত স্ট্যাকটি পরিবর্তিত হবে বলে আমি মনে করি না! ধন্যবাদ :-)
মাইকেল জলপ্রপাত

1
আমি কেবল একই জিনিসটি সম্পাদন করার চেষ্টা করেছি তবে এতে viewWillAppearএবং মনে হবে যে ভিউ কন্ট্রোলারটিকে এটি ধাক্কা দিয়ে প্রকাশ করা হচ্ছে বা এর উপরে কিছু পপ করা হচ্ছে কিনা, ভিউকন্ট্রোলার অ্যারে উভয়ই একই! কোন ধারনা?
মাইকেল জলপ্রপাত

আমার এও লক্ষ্য করা উচিত যে ভিউ কন্ট্রোলার অ্যাপটির জীবদ্দশায় অবিচল থাকে তাই আমি আমার ক্রিয়াকলাপগুলি viewDidLoadকেবল একবার বলা হওয়ার কারণে সম্পাদন করতে পারি না ! হুঁ, কৌতুকময়!
মাইকেল জলপ্রপাত

4
@ শ্রবোটের এমন কোনও কারণ আছে যা আপনি ![viewControllers containsObject:self]পরিবর্তে করেন নি [viewControllers indexOfObject:self] == NSNotFound? স্টাইল পছন্দ?
জেকেল

24
এই উত্তরটি আইওএস 5 সাল থেকে অপ্রচলিত রয়েছে -isMovingFromParentViewControllerনীচের বর্ণিত পদ্ধতিটি আপনাকে পরীক্ষাটি দেখার অনুমতি দেয় যদি দৃশ্যটি স্পষ্টভাবে পপ করা হচ্ছে।
গ্রাহাম্পার্কস

136

আমি মনে করি সবচেয়ে সহজ উপায়:

 - (void)viewWillDisappear:(BOOL)animated
{
    if ([self isMovingFromParentViewController])
    {
        NSLog(@"View controller was popped");
    }
    else
    {
        NSLog(@"New view controller was pushed");
    }
    [super viewWillDisappear:animated];
}

সুইফট:

override func viewWillDisappear(animated: Bool)
{
    if isMovingFromParent
    {
        print("View controller was popped")
    }
    else
    {
        print("New view controller was pushed")
    }
    super.viewWillDisappear(animated)
}

আইওএস 5 এর হিসাবে এটির উত্তর, সম্ভবত এটিও বিজডিজমড পরীক্ষা করে দেখুন
d370urn3ur

4
আইওএস For এর জন্য আমাকে [স্ব। নেভিগেশন কন্ট্রোলআরভিউ কন্ট্রোলার্স সূচিপত্র: স্ব]] == এনএসএনটফাউন্ড আবার পরীক্ষা করতে হবে কারণ অ্যাপ্লিকেশনটির ব্যাকগ্রাউন্ডিংও এই পরীক্ষায় উত্তীর্ণ হবে তবে নেভিগেশন স্ট্যাক থেকে নিজেকে সরিয়ে ফেলবে না।
এরিক চেন

3
অ্যাপল এটি করার জন্য একটি নথিভুক্ত উপায় সরবরাহ করেছে - stackoverflow.com/a/33478133/385708
শ্যাম ভাট

ভিউউইলডিস্পায়ার ব্যবহার করে সমস্যাটি হ'ল এটি সম্ভব যে ভিউ ইতিমধ্যে অদৃশ্য হওয়ার পরে কন্ট্রোলারটি স্ট্যাক থেকে পপ করা হয়। উদাহরণস্বরূপ, অন্য ভিউকন্ট্রোলারটিকে স্ট্যাকের শীর্ষে ঠেলাঠেলি করা যেতে পারে এবং তারপরে মাঝখানে অবস্থিত ভিউইলডিস্পায়ারকে বাইপাস করে পপটোরআরটভিউ কনট্রোলারঅ্যানিমেটেড কল করতে পারে।
জন কে

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

61

ইউআইভিউউকন্ট্রোল.আরে অ্যাপলের ডকুমেন্টেশন থেকে:

"এই চারটি পদ্ধতি একটি ভিউ কন্ট্রোলারের উপস্থিতি কলব্যাকগুলিতে এটি চাইল্ড ভিউ কন্ট্রোলার হিসাবে উপস্থাপিত, বরখাস্ত করা, বা যুক্ত করা বা অপসারণ করা হচ্ছে কিনা তা নির্ধারণের জন্য ব্যবহার করা যেতে পারে For উদাহরণস্বরূপ, একটি ভিউ কন্ট্রোলার এটি অদৃশ্য হয়ে গেছে কিনা তা খারিজ করা হয়েছে কিনা তা যাচাই করতে পারে বা নিজেকে তার ভিউতে জিজ্ঞাসা করে পপড উইলডিস্পায়ার: পদ্ধতিটি পরীক্ষা করে ([স্বতঃবজিংডিজমসড] || [সেল্ফ মজিংফ্র্যাম্পিয়ারভিউ কনট্রোলার])) "

- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);

- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);

সুতরাং হ্যাঁ, এটি করার একমাত্র নথিযুক্ত উপায় হ'ল নিম্নলিখিত উপায়:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if ([self isBeingDismissed] || [self isMovingFromParentViewController]) {
    }
}

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

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    
    if self.isBeingDismissed || self.isMovingFromParentViewController { 
    }
}

18

আপনি শুধু জানতে আপনার ভিউ popped হচ্ছে কিনা চান, আমি শুধু আবিষ্কার করেছি যে self.navigationControllerহয় nilমধ্যে viewDidDisappear, যখন এটি কন্ট্রোলার স্ট্যাক থেকে মুছে ফেলা হবে। সুতরাং এটি একটি সহজ বিকল্প পরীক্ষা।

(এটি আমি অন্যান্য ধরণের সমস্ত কন্ট্রোলশনের চেষ্টা করেও আবিষ্কার করেছি I'm আমি অবাক হয়েছি যে পপগুলিতে অবহিত করার জন্য একটি ভিউ কন্ট্রোলার নিবন্ধকরণ করার জন্য নেভিগেশন কন্ট্রোলার প্রোটোকল নেই You আপনি ব্যবহার করতে পারবেন না UINavigationControllerDelegateকারণ এটি প্রকৃত প্রদর্শন কাজ করে))


16

সুইফট 4

override func viewWillDisappear(_ animated: Bool)
    {
        super.viewWillDisappear(animated)
        if self.isMovingFromParent
        {
            //View Controller Popped
        }
        else
        {
            //New view controller pushed
        }
    }

6

সুইফটে:

 override func viewWillDisappear(animated: Bool) {
    if let navigationController = self.navigationController {
        if !contains(navigationController.viewControllers as! Array<UIViewController>, self) {
        }
    }

    super.viewWillDisappear(animated)

}

হিসাবে ব্যবহার নিশ্চিত করুন! পরিবর্তে হিসাবে
dfmuir

2

আমি এ সম্পর্কে অ্যাপলের ডকুমেন্টেশনগুলি বোঝা শক্ত। এই এক্সটেনশনটি প্রতিটি নেভিগেশনে রাজ্যগুলি দেখতে সহায়তা করে।

extension UIViewController {
    public func printTransitionStates() {
        print("isBeingPresented=\(isBeingPresented)")
        print("isBeingDismissed=\(isBeingDismissed)")
        print("isMovingToParentViewController=\(isMovingToParentViewController)")
        print("isMovingFromParentViewController=\(isMovingFromParentViewController)")
    }
}

1

এই প্রশ্নটি বেশ পুরানো তবে আমি এটি দুর্ঘটনার দ্বারা দেখেছি তাই আমি সেরা অনুশীলন পোস্ট করতে চাই (আফাইক)

আপনি ঠিক করতে পারেন

if([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
 // view controller popped
}

1

এটি আইওএস 7- এ প্রযোজ্য , এটি অন্য কোনও ক্ষেত্রে প্রযোজ্য কিনা তা ধারণা নেই। আমি যা জানি viewDidDisappearতা থেকে ভিউটিতে ইতিমধ্যে পপ করা হয়েছে। যার অর্থ আপনি যখন জিজ্ঞাসা self.navigationController.viewControllersকরবেন তখন আপনি একটি পাবেন nil। সুতরাং শূন্য কিনা তা পরীক্ষা করুন।

টি এল; ডিআর

 - (void)viewDidDisappear:(BOOL)animated
 {
    [super viewDidDisappear:animated];
    if (self.navigationController.viewControllers == nil) {
        // It has been popped!
        NSLog(@"Popped and Gone");
    }
 }

1

আইওএস 6+ এ এই সমস্যাগুলি পরিচালনা করার জন্য সেগগুলি খুব কার্যকর উপায় হতে পারে। আপনি যদি ইন্টারফেস বিল্ডারে নির্দিষ্ট সেগটিকে একটি সনাক্তকারী দিয়ে থাকেন তবে আপনি এটি পরীক্ষা করতে পারেন prepareForSegue

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"LoginSegue"]) {
       NSLog(@"Push");
       // Do something specific here, or set a BOOL indicating
       // a push has occurred that will be checked later
    }
}

1

ধন্যবাদ ব্রায়ান হেনরি, তবুও সুইফট 5-এ কাজ করে

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if let controllers = navigationController?.children{
            if controllers.count > 1, controllers[controllers.count - 2] == self{
                // View is disappearing because a new view controller was pushed onto the stack
                print("New view controller was pushed")
            }
            else if controllers.firstIndex(of: self) == nil{
                // View is disappearing because it was popped from the stack
                print("View controller was popped")
            }
        }

    }

-1

আমি মনে করি আপনার অর্থ হ'ল আপনি যখন স্ট্যাকের দিকে ধাক্কা দিয়ে বলছেন তখন আপনার দৃষ্টিভঙ্গিটি ন্যাভিগেশন কন্ট্রোলারের স্ট্যাকটি নীচে সরানো হচ্ছে view কনসোলে কিছু লিখতে viewDidUnloadএকটি NSLogবিবৃতি যুক্ত করার জন্য আমি পদ্ধতিটি ব্যবহার করার পরামর্শ দেব যাতে আপনি কী দেখতে যাচ্ছেন তা দেখতে পারেন, আপনি এতে যুক্ত করতে চাইতে NSLogপারেন viewWillDissappeer


-1

এসব্রকেটের উত্তরের মতো একই জিনিসটি সম্পাদন করার জন্য এখানে একটি বিভাগ:

শিরোলেখ:

#import <UIKit/UIKit.h>

@interface UIViewController (isBeingPopped)

- (BOOL) isBeingPopped;

@end

উৎস:

#import "UIViewController+isBeingPopped.h"

@implementation UIViewController (isBeingPopped)

- (BOOL) isBeingPopped {
    NSArray *viewControllers = self.navigationController.viewControllers;
    if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
        return NO;
    } else if ([viewControllers indexOfObject:self] == NSNotFound) {
        return YES;
    }
    return NO;
}

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