ভিউকন্ট্রোলারকে মডেল হিসাবে উপস্থাপন করা হয়েছে কিনা তা নির্ধারণ করা সম্ভব?


117

ভিউকন্ট্রোলার শ্রেণীর ভিতরে এটি পরীক্ষা করা সম্ভব যে এটি মডেল ভিউ নিয়ন্ত্রক হিসাবে উপস্থাপিত হয়েছে?

উত্তর:


96

যেহেতু modalViewControllerআইওএস 6 এ অবহেলা করা হয়েছে, তাই এখানে একটি সংস্করণ আইওএস 5+ এর জন্য কাজ করে এবং সতর্কতা ছাড়াই সংকলন করে।

উদ্দেশ্য গ:

- (BOOL)isModal {
    return self.presentingViewController.presentedViewController == self
      || (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController)
      || [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
}

সুইফট:

var isModal: Bool {
    return self.presentingViewController?.presentedViewController == self
        || (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
        || self.tabBarController?.presentingViewController is UITabBarController
}

ফেলির উত্তরের টুপি।


2
ভাল ক্যাচ, আমাকে দীর্ঘ সময় পরে আবার এটি ব্যবহার করতে হয়েছিল এবং লক্ষ্য করা গেছে যে অবমূল্যায়ন হয়েছে ... আমি আমার উত্তরটি সম্পাদনা করেছি যাতে লোকেরা আইওএস 6+ ব্যবহার করার সময় সঠিক কোডটি সন্ধান করতে শুরু করে, ধন্যবাদ
ফিলিপ সাবিনো

10
প্যারেন্ট ভিউ কন্ট্রোলার এমন কোনও মডেল হয় যার উপরে আমাদের ভিউ কন্ট্রোলারটিকে চাপ দেওয়া হয় work
অর্থ-বিষয়গুলি

2
একটি ত্রুটি আছে, আমাদের উভয় পক্ষের শূন্য রয়েছে কিনা তা পরীক্ষা করা উচিত, কারণ এটি nil == nilপ্রত্যাবর্তন করে YES, এবং এটি আমাদের পছন্দ ফলাফল নয়।
কোকোবোবি

1
@ গ্যাব্রিয়েলপেট্রোনেলা এই পদ্ধতির একটি সুইফ্ট বাস্তবায়ন অন্তর্ভুক্ত করার জন্য যদি আমি উত্তরটি আপডেট করি তবে আপনার আপত্তি আছে কি?
মাইকেল জলপ্রপাত 10

1
@ মাইকেল ওয়াটারফলের যে প্রশংসা হবে, ধন্যবাদ
গ্যাব্রিয়েল পেট্রোনেলা

77

আপনি যদি আইওএস 6+ খুঁজছেন, এই উত্তরটি অবচিত হয়ে গেছে এবং আপনার গ্যাব্রিয়েল পেট্রোনেলার ​​উত্তরটি পরীক্ষা করা উচিত


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

সুতরাং, বর্তমান ( selfকোড বেলো হিসাবে উপস্থাপিত) কন্ট্রোলার একটি মডেল উপায়ে উপস্থাপিত হয়েছে কিনা তা যাচাই করার জন্য, আমার কাছে হয় কোনও UIViewControllerবিভাগে ফাংশন বেলো আছে, বা (যদি আপনার প্রকল্পে অন্যান্য ইউআইকিট নিয়ন্ত্রক ব্যবহার করার প্রয়োজন না হয় তবে) UITableViewControllerউদাহরণস্বরূপ) এমন বেস বেস নিয়ামক যা আমার অন্যান্য নিয়ামকরা উত্তরাধিকার সূত্রে প্রাপ্ত

-(BOOL)isModal {

     BOOL isModal = ((self.parentViewController && self.parentViewController.modalViewController == self) || 
            //or if I have a navigation controller, check if its parent modal view controller is self navigation controller
            ( self.navigationController && self.navigationController.parentViewController && self.navigationController.parentViewController.modalViewController == self.navigationController) || 
            //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
            [[[self tabBarController] parentViewController] isKindOfClass:[UITabBarController class]]);

    //iOS 5+
    if (!isModal && [self respondsToSelector:@selector(presentingViewController)]) {

        isModal = ((self.presentingViewController && self.presentingViewController.modalViewController == self) || 
             //or if I have a navigation controller, check if its parent modal view controller is self navigation controller
             (self.navigationController && self.navigationController.presentingViewController && self.navigationController.presentingViewController.modalViewController == self.navigationController) || 
             //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
             [[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]]);

    }

    return isModal;        

}

সম্পাদনা: কোনও ইউআইটিববারকন্ট্রোলার ব্যবহার হচ্ছে কিনা তা দেখার জন্য আমি সর্বশেষ চেকটি যুক্ত করেছি এবং আপনি অন্য একটি ইউআইটিববারকন্ট্রোলারকে মডেল হিসাবে উপস্থাপন করেছেন।

সম্পাদনা 2: যুক্ত করা আইওএস 5+ চেক, যেখানে আর UIViewControllerউত্তর দেয় না parentViewController, presentingViewControllerপরিবর্তে।

সম্পাদনা 3: আমি কেবল https://gist.github.com/3174081 ক্ষেত্রে এটির জন্য একটি বাক্য তৈরি করেছি


মনে রাখবেন যে modalViewControllerসম্পত্তিটি আইওএস 6 হিসাবে অবচিত হয়েছে The ডকুমেন্টেশনটি presentedViewControllerপরিবর্তে ব্যবহার করার পরামর্শ দেয় ।
বার্ট জ্যাকবস

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

NSLog(@"%@", self.navigationController.parentViewController)প্রিন্ট (null)- আপনি দয়া করে কেন ব্যাখ্যা করতে পারেন? আমার ভিউকন্ট্রোলার স্টোরিবোর্ডে নাভ্যাক্ট্রোলারের মাধ্যমে মডেল ভিউ কন্ট্রোলারের সাথে সংযুক্ত।
রোমান

@oyatek আপনি পেস্টবিন বা অনুরূপ কিছু ব্যবহার করতে পারেন এবং কিছু কোড দেখিয়ে দিতে পারেন?
ফিলিপ সাবিনো

@ ফিলিপ আমি সমস্যাটি পেয়েছি - অবমানিত .parentViewController, এর .presentingViewControllerপরিবর্তে অবশ্যই ব্যবহার করা উচিত।
রোমান

35

আইওএস 5+ তে আপনি যেমন ইউআইভিউউকন্ট্রোলার শ্রেণি রেফারেন্সে দেখতে পাচ্ছেন , আপনি এটিকে সম্পত্তি "উপস্থাপনভিউকন্ট্রোলার" থেকে পেতে পারেন।

উপস্থাপনাভিউ কনট্রোলার এমন ভিউ কন্ট্রোলার যা এই দর্শন নিয়ামককে উপস্থাপন করে। (শুধুমাত্র পাঠযোগ্য)

@property (nonatomic, কেবলমাত্র পঠনযোগ্য) UIViewController * presentingViewController
আলোচনা

যদি এই বার্তাটি পেয়েছে এমন ভিউ কন্ট্রোলার যদি অন্য ভিউ কন্ট্রোলার দ্বারা উপস্থাপন করা হয়, তবে এই সম্পত্তিটি উপস্থাপনা করছে এমন দৃশ্য নিয়ন্ত্রণকারীকে ধরে রাখে holds যদি ভিউ কন্ট্রোলার উপস্থাপন না করা হয় তবে এর পূর্বপুরুষদের মধ্যে একটি উপস্থাপিত হচ্ছে, এই সম্পত্তিটি নিকটতম পূর্বপুরুষকে উপস্থাপন করে ভিউ কন্ট্রোলারকে ধারণ করে। যদি ভিউ কন্ট্রোলার বা এর পূর্বপুরুষদের কেউ উপস্থাপিত না হয় তবে এই সম্পত্তিটি শূন্য করে।


আইওএস 5.0 এবং তারপরে উপলভ্যতা উপলব্ধ। ইউআইভিউউকন্ট্রোল.আর
ঘোষণা হয়েছে


3
পুরোপুরি কাজ করে, (স্ব.প্রেসিটিংভিউকন্ট্রোলার) ব্যবহার করুন {// এটি একটি মডেল ভিউ কনটোলার} অন্য {// এটি একটি সাধারণ
ভিউ কন্ট্রোলার

2
আইএমএইচও, এখানে একমাত্র সঠিক উত্তর। শুধু একটি উপস্থিতি জন্য চেক presentingViewController। এটি কনটেইনার ভিউ কন্ট্রোলারগুলিতেও কাজ করবে, কারণ এটি স্বয়ংক্রিয়ভাবে পূর্বপুরুষদের অনুসরণ করে।
ড্যানিয়েল রিন্সার

17

যদি তা না থাকে তবে presentedAsModalআপনি নিজের ইউআইভিউকন্ট্রোলার সাবক্লাসে ( ) এর জন্য একটি সম্পত্তি নির্ধারণ করতে পারেন এবং YESভিডকন্ট্রোলারকে মডেল ভিউ হিসাবে উপস্থাপন করার আগে সেট করতে পারেন ।

childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];

আপনি আপনার viewWillAppearওভাররাইডে এই মানটি পরীক্ষা করতে পারেন ।

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


রিগট এবং এটি আমি যা করেছি তা কিন্তু আমি অন্য কোনও ঝরঝরে সমাধানের সন্ধান করছিলাম। ধন্যবাদ।
lukewar

আপনি যদি কোনও মডেল UINavigationControllerহিসাবে উপস্থাপন করেন তবে এই সমাধানটি কাজ করে না ... যতক্ষণ না আপনি কেবল এই সম্পত্তি যুক্ত করতে একটি কাস্টম নেভিগেশন নিয়ামক তৈরি করেন। এবং তারপরে, কন্ট্রোলারগুলির ভিতরে, নিয়ন্ত্রককে self.navigationControllerমডেল হিসাবে উপস্থাপন করা হয়েছে কিনা তা যাচাই করার জন্য আপনাকে প্রতিবার এই কাস্টম ক্লাসে কাস্টিং চালিয়ে যেতে হবে
ফিলিপ সাবিনো

8

পেট্রোনেল্লার উত্তর কাজ করে না যদি স্ব.নিভিশনকন্ট্রোলারটি আধুনিকভাবে উপস্থাপিত হয় তবে স্ব স্ব-সংক্রান্ত সমান না হয় nav ন্যাভিগেশন কন্ট্রোলআরভিউ কনট্রোলার [0], সেই ক্ষেত্রে স্ব চাপানো হয়।

আপনি কীভাবে সমস্যাটি সমাধান করতে পারেন তা এখানে।

return self.presentingViewController.presentedViewController == self
            || (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController && self == self.navigationController.viewControllers[0])
            || [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];

এবং সুইফটে:

return self.presentingViewController?.presentedViewController == self
        || (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self)
        || self.tabBarController?.presentingViewController is UITabBarController

6

এই কাজ করা উচিত.

if(self.parentViewController.modalViewController == self)…

দুর্ভাগ্যক্রমে এটি কাজ করে না। এটা আমার প্রথম চেষ্টা ছিল। তবে মোডালভিউ কনট্রোলার ফিরে এসেছে :(।
লুকোয়ার

আপনি যদি কেবল 'সেলফ.প্যারেন্টভিউ কনট্রোলার' পান তবে এটি কি সঠিক প্যারেন্ট অবজেক্টটি ফিরিয়ে দেবে?
কুবি

4
সমস্যাটি হতে পারে যে আপনার ইউআইভিউউকন্ট্রোলার সাবক্লাসটি কোনও ইউআইএনএভিগেশন কন্ট্রোলার বা একটি ইউআইটিববারকন্ট্রোলারের (বা উভয়) ভিতরে রয়েছে, সেই ক্ষেত্রে আপনাকে মডেল ভিউ কন্ট্রোলার হিসাবে উপস্থাপিত পিতামাতার সন্ধানের জন্য ভিউ হায়ারার্কিতে আরও কিছুটা খনন করতে হবে।
এইচপিফিক

@hgpc আমার প্রকল্পে আমার এই চকের দরকার ছিল, তাই আমি উভয় UINavigationControllerএবং UITabBarControllerকেস পরীক্ষা করার জন্য একটি উত্তর যুক্ত করেছি । এটি এখন পর্যন্ত বেশ ভালভাবে কাজ করছে
ফিলিপ সাবিনো


2

যদি আপনাকে পূর্ণ-স্ক্রিন মডেল ভিউ এবং নন-মডেল ভিউগুলির মধ্যে পার্থক্য করার প্রয়োজন না হয়, যা আমার প্রকল্পের ক্ষেত্রে (আমি কেবল একটি ফর্ম শীট এবং পৃষ্ঠা শীটগুলির সাথে ঘটে এমন একটি সমস্যা নিয়ে কাজ করছি), আপনি মোডালপ্রেজেন্টেশন স্টাইল ব্যবহার করতে পারেন ইউআইভিউউকন্ট্রোলারের সম্পত্তি:

switch (self.modalPresentationStyle) {
    case 0: NSLog(@"full screen, or not modal"); break;
    case 1: NSLog(@"page sheet"); break;
    case 2: NSLog(@"form sheet"); break;
}

2

ইন সুইফট :

func isUIViewControllerPresentedAsModal() -> Bool {
    if((self.presentingViewController) != nil) {
        return true
    }

    if(self.presentingViewController?.presentedViewController == self) {
        return true
    }

    if(self.navigationController?.presentingViewController?.presentedViewController == self.navigationController) {
        return true
    }

    if((self.tabBarController?.presentingViewController?.isKindOfClass(UITabBarController)) != nil) {
        return true
    }

    return false
}

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

1
প্রথম যদি বিবৃতিটি স্টেটমেন্টে থাকে যা দ্বিতীয়টিতে থাকে তবে দ্বিতীয় বিবৃতিটি রিলান্ড্যান্ট সরবরাহ করে। আমি নিশ্চিত না যে এখানে কী উদ্দেশ্য রয়েছে।
আইসোফোন

1

আমার প্রকল্পে আমার কাছে একটি ভিউ কন্ট্রোলার (বিশদ) রয়েছে যা মডেল উপস্থাপন করা যেতে পারে (কোনও নতুন আইটেম যুক্ত করার সময়) বা মাস্টার ভিউ কন্ট্রোলার দ্বারা ধাক্কা দিয়ে (কোনও বিদ্যমান সম্পাদনা করার সময়)। যখন ব্যবহারকারী ট্যাপ করে [সম্পন্ন করুন] বিশদ ভিউ কন্ট্রোলার মাস্টার ভিউ কন্ট্রোলারের পদ্ধতিটি কল করে যে এটি বন্ধ হওয়ার জন্য প্রস্তুত। কীভাবে এটি বন্ধ করতে হবে তা জানতে মাস্টারকে বিশদটি কীভাবে উপস্থাপন করা হয় তা নির্ধারণ করতে হবে। আমি এটি এইভাবে করি:

UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
    [self dismissViewControllerAnimated:YES completion:NULL];
} else {
    [self.navigationController popViewControllerAnimated:YES];
}

0

এই মত একটি হ্যাক কাজ করতে পারে।

UIViewController* child = self;
UIViewController* parent = child.parentViewController;
while (parent && parent.modalViewController != child) {
    child = parent;
    parent = child.parentViewController;
}
if (parent) {
    // A view controller in the hierarchy was presented as a modal view controller
}

তবে আমি মনে করি আমার পূর্ববর্তী উত্তরটি একটি পরিষ্কার সমাধান।


0

আমার জন্য যা কাজ করেছে তা নিম্নলিখিত:

// this is the trick: set parent view controller as application's window root view controller
UIApplication.sharedApplication.delegate.window.rootViewController = viewController;

// assert no modal view is presented
XCTAssertNil(viewController.presentedViewController);

// simulate button tap which shows modal view controller
[viewController.deleteButton sendActionsForControlEvents:UIControlEventTouchUpInside];

// assert that modal view controller is presented
XCTAssertEqualObjects(viewController.presentedViewController.class, MyModalViewController.class);

যতদূর আমি এটি পরীক্ষা করেছি, এটি iOS7 এবং iOS8 এর জন্য কাজ করে। তবে iOS6 এ চেষ্টা করেননি।


0

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

- (BOOL)isModal {
    BOOL modal = NO;
    if ([self presentingViewController]) { //Some view Controller is presenting the current stack
        UIViewController *presented = [[self presentingViewController] presentedViewController]; // What's been presented
        if ([presented respondsToSelector:@selector(viewControllers)]) { // There's a stack
            NSArray *viewControllers = [presented performSelector:@selector(viewControllers)];
            modal = [viewControllers firstObject] == self; // Current VC is presented modally if it's the first in the stack
        }
        else {
            modal = presented == self; // Don't think this is actually needed. set modal = YES should do the job tho.
        }
    }
    return modal;
}

এই সাহায্য আশা করি।


0

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

var isModal: Bool {
    // If we are a child view controller, we need to check our parent's presentation
    // rather than our own.  So walk up the chain until we don't see any parentViewControllers
    var potentiallyPresentedViewController : UIViewController = self
    while (potentiallyPresentedViewController.parentViewController != nil) {
        potentiallyPresentedViewController = potentiallyPresentedViewController.parentViewController!
    }

    if self.presentingViewController?.presentedViewController == potentiallyPresentedViewController {
        return true
    }

    if let navigationController = potentiallyPresentedViewController.navigationController {
        if navigationController.presentingViewController?.presentedViewController == navigationController {
            return true
        }
    }

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