Bir görünüm denetleyicisinin mod olarak sunulup sunulmadığı veya bir gezinme yığınına aktarılıp aktarılmadığı nasıl kontrol edilir?


126

Görünüm denetleyici kodumda aşağıdakileri nasıl ayırt edebilirim:

  • mod olarak sunulmuştur
  • gezinti yığınına itildi

Her ikisi de presentingViewControllerve isMovingToParentViewControllerher YESiki durumda da, bu yüzden pek yardımcı olmuyor.

İşleri karmaşıklaştıran şey, üst görüntüleme denetleyicimin bazen kipli olması ve kontrol edilecek görünüm denetleyicisinin üzerine basılmasıdır.

Görünüşe göre benim sorunum, kendimi daha sonra sunulan HtmlViewControllerbir UINavigationControlleriçine yerleştirmem . Bu yüzden kendi girişimlerim ve aşağıdaki iyi cevaplar işe yaramadı.

HtmlViewController*     termsViewController = [[HtmlViewController alloc] initWithDictionary:dictionary];
UINavigationController* modalViewController;

modalViewController = [[UINavigationController alloc] initWithRootViewController:termsViewController];
modalViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:modalViewController
                   animated:YES
                 completion:nil];

Sanırım, belirlemeye çalışmak yerine görünüm denetleyicime modal olduğunda söylemeliyim.

Yanıtlar:


125

Bir tuz tanesi ile al, test etmedim.

- (BOOL)isModal {
     if([self presentingViewController])
         return YES;
     if([[[self navigationController] presentingViewController] presentedViewController] == [self navigationController])
         return YES;
     if([[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]])
         return YES;

    return NO;
 }

12
Bunu başka bir SO gönderisinde buldum. Ancak, itilen görünüm denetleyicisinin üst öğesi bir modal ise çalışmaz; sahip olduğum durum bu.
anlam-konular

2
Yazdığım gibi presentingViewController, her zaman YESbenim durumumdadır; yardımcı olmuyor.
anlam-konular

3
presentingViewControllerkök olarak ayarlanmış YESbir UITabBarControllervarlık olduğunda, itilen VC için döner . Yani benim durumuma uygun değil.
Yevhen Dubinin

5
Bu, bir görüntüleme denetleyicisi sunarsanız çalışmaz, sonra başka birine iter.
Lee

3
"Bir görünüm denetleyicisi sunarsanız bu işe yaramaz, sonra başka birini iter" Bunun amacı bu değil, itilen görünüm denetleyicisi sunulmuyor.
Colin Swelin

87

In Swift :

Sınıf türüne göre bir modal olup olmadığını test etmek için bir bayrak ekleyin:

// MARK: - UIViewController implementation

extension UIViewController {

    var isModal: Bool {

        let presentingIsModal = presentingViewController != nil
        let presentingIsNavigation = navigationController?.presentingViewController?.presentedViewController == navigationController
        let presentingIsTabBar = tabBarController?.presentingViewController is UITabBarController

        return presentingIsModal || presentingIsNavigation || presentingIsTabBar
    }
}

4
Bir var isModal: Bool {}
varyasyonda

1
@malinois değiştirildi
YannSteph

İfadedeki son falseparametre ne returnişe yarar?
damjandd

presentingIsNavigation = navigationController? .presentingViewController? .presentedViewController == navigationController && navigationController! = nil
famfamfam

78

Tek bir yöntemi gözardı: isBeingPresented.

isBeingPresented görünüm denetleyicisi sunulduğunda true ve basıldığında yanlıştır.

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if ([self isBeingPresented]) {
        // being presented
    } else if ([self isMovingToParentViewController]) {
        // being pushed
    } else {
        // simply showing again because another VC was dismissed
    }
}

2
Ben de gönderme önce denedim ve işe değil, isBeingPresentedolduğu NO. Ama şimdi nedenini anlıyorum, sunulan görünüm denetleyicimi a'ya yerleştiriyorum UINavigationControllerve bu benim ittiğim şey.
anlam meseleleri

1
Bir gezinme denetleyicisine basamazsınız. Belki de gezinme denetleyicisini sunduğunuzu kastettiniz.
rmaddy

3
@jowie İlkel bir değer yazdırırken pdeğil kullanın po. ponesneleri yazdırmak içindir.
rmaddy

37
Belgeler için isBeingPresented- Bu yöntem, yalnızca viewWillAppear: ve viewDidAppear: yöntemlerinin içinden çağrıldığında YES değerini döndürür.
funct7

4
@Terrence Görünüşe göre son belgeler bu bilgiyi göstermiyor ama eskiden oradaydı. isBeingPresented, isBeingDismissed, isMovingFromParentViewControllerVe isMovingToParentViewController4 içerisinde geçerli olup view[Will|Did][Disa|A]ppearyöntemlerle.
rmaddy

29

Swift 5
İşte adresler önceki cevapları ile dile getirilen konu, bu çözüm isModal()döner trueeğer itilmiş UIViewControllerbir takdim olduğunu UINavigationControlleryığını.

extension UIViewController {
    var isModal: Bool {
        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            return true
        } else if navigationController?.presentingViewController?.presentedViewController == navigationController {
            return true
        } else if tabBarController?.presentingViewController is UITabBarController {
            return true
        } else {
            return false
        }
    }
}

Şimdiye kadar benim için çalışıyor. Bazı optimizasyonlar varsa lütfen paylaşın.


Neden kontrol etmeniz gerekiyor tabBarController?.presentingViewController is UITabBarController ? Bunun presentingViewControllerda bir UITabBarController olması önemli mi?
Hlung

Ve eğer navigationController nil isModalise geri dönecektir true. Bu kasıtlı mı?
Hlung

28

self.navigationController! = nil, bir gezinti yığınında olduğu anlamına gelir.

Gezinme denetleyicisi modsal olarak sunulurken geçerli görünüm denetleyicisine basılma durumunu işlemek için, geçerli görünüm denetleyicisinin gezinme yığınındaki kök denetleyici olup olmadığını kontrol etmek için bazı kod satırları ekledim.

extension UIViewController {
    var isModal: Bool {
        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            return true
        } else if let navigationController = navigationController, navigationController.presentingViewController?.presentedViewController == navigationController {
            return true
        } else if let tabBarController = tabBarController, tabBarController.presentingViewController is UITabBarController {
            return true
        } else {
            return false
        }
    }
}

Genel olarak modsal sunum yaptığınızda, viewController'ı bir navigationController'a koyarsınız ve sunarsınız. Bu durumda, ifadeniz yanlış olur, ancak kodda bu durum ele alınmaktadır. Lütfen cevabınızı iyileştirin :)
E-Riddie

tüm kullanım durumlarıyla ilgilenen iyi bir iş. muhtemelen yeniden düzenleme biraz için oda ama yine de olumlu oy!
Jean Raymond Daher

12

Swift 4

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

Swift 4.2 / iOS 12. Hala iyi çalışıyor, ancak navigationController? .PresentingViewController? .PresentedViewController === navigationController'ın her ikisi de sıfırsa doğru olarak değerlendirileceğini unutmayın (örneğin, henüz yapılmamış bir görünüm denetleyicisinde çağırırsanız) sunulan).
Eli Burke

7

Hızlı 5. Temiz ve basit.

if navigationController.presentingViewController != nil {
    // Navigation controller is being presented modally
}

1
bu benim için hile yaptı
Radu Ursache

3

Buradaki birçok kişinin önerdiği gibi, "kontrol etme" yöntemlerinin her durumda işe yaramadığını, projemde bunu manuel olarak yönetmek için bir çözüm buldum. Mesele şu ki, sunumu genellikle kendi başımıza yönetiyoruz - sahne arkasında olan bu değil ve iç gözlem yapmalıyız.

DEViewController.h dosya:

#import <UIKit/UIKit.h>

// it is a base class for all view controllers within a project
@interface DEViewController : UIViewController 

// specify a way viewcontroller, is presented  by another viewcontroller
// the presented view controller should manually assign the value to it
typedef NS_ENUM(NSUInteger, SSViewControllerPresentationMethod) {
    SSViewControllerPresentationMethodUnspecified = 0,
    SSViewControllerPresentationMethodPush,
    SSViewControllerPresentationMethodModal,
};
@property (nonatomic) SSViewControllerPresentationMethod viewControllerPresentationMethod;

// other properties/methods...
@end

Sunumlar artık şu şekilde yönetilebilir:

gezinti yığınına itildi:

// DETestViewController inherits from DEViewController
DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodPush;
[self.navigationController pushViewController:vc animated:YES];

mod olarak navigasyonla sunulur:

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
UINavigationController *nav = [[UINavigationController alloc]
                               initWithRootViewController:vc];
[self presentViewController:nav animated:YES completion:nil];

mod olarak sunulmuştur:

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
[self presentViewController:vc animated:YES completion:nil];

Ayrıca, DEViewControlleryukarıda belirtilen mülkün şuna eşit olup olmadığını "kontrol etmek" için bir yedek ekleyebiliriz SSViewControllerPresentationMethodUnspecified:

- (BOOL)isViewControllerPushed
{
    if (self.viewControllerPresentationMethod != SSViewControllerPresentationMethodUnspecified) {
        return (BOOL)(self.viewControllerPresentationMethod == SSViewControllerPresentationMethodPush);
    }

    else {
        // fallback to default determination method
        return (BOOL)self.navigationController.viewControllers.count > 1;
    }
}

3

Modsal olarak sunduğunuz tüm viewControllers'ın yeni bir navigationController içine sarıldığını varsayarsak (ki bunu her zaman yapmalısınız), bu özelliği VC'nize ekleyebilirsiniz.

private var wasPushed: Bool {
    guard let vc = navigationController?.viewControllers.first where vc == self else {
        return true
    }

    return false
}

1
bunu her zaman yapmalısınız - lütfen nedenini açıklayın?
Alexander Abakumov

Alexander, yapmamalısın, gerçekten.
nickdnk

2

Denetleyicinizin basıldığını tespit etmek veya istediğiniz yerde sadece aşağıdaki kodu kullanmayın:

if ([[[self.parentViewController childViewControllers] firstObject] isKindOfClass:[self class]]) {

    // Not pushed
}
else {

    // Pushed
}

Umarım bu kod herkese yardımcı olabilir ...


1
Bu yöntem, aynı görünüm denetleyicisi sınıfını birden çok yerde kullandığınızda çalışmaz, çünkü yalnızca sınıfını kontrol eder. Bunun yerine eşitliği açıkça kontrol edebilirsiniz.
gklka

1

self.navigationController != nil bir gezinme yığınında olduğu anlamına gelir.


25
Hala modsal gezinme denetleyicisinde olabilir
ColdLogic

Dolayısıyla, 'modal' ve 'gezinti yığınında itilen' birbirini dışlamaz. Bunun bağlama bağlı olduğunu düşünmek, ancak self.navigationController'ın nil olmadığını kontrol etmek, bir gezinti denetleyicisinin bir görünüm denetleyicisi olup olmadığını yanıtlamaz.
Daniel

@Daniel Fark "itilmiş" ve "sunulan" arasındadır. "Modal" ın bununla hiçbir ilgisi yok. "ColdLogic" in "modal" dediklerinde "sunulan" anlamına geldiğine inanıyorum.
rmaddy

1
if let navigationController = self.navigationController, navigationController.isBeingPresented {
    // being presented
}else{
    // being pushed
}

1

Swift 5
Bu kullanışlı uzantı, önceki yanıtlardan birkaç vakayı daha ele alır. Bu durumlar VC'dir (görünüm denetleyicisi), uygulama penceresinin kök VC'sidir, VC, ana VC'ye alt öğe olarak eklenir. Yalnızca viewcontroller modsal olarak sunuluyorsa true döndürmeye çalışır.

extension UIViewController {
    /**
      returns true only if the viewcontroller is presented.
    */
    var isModal: Bool {
        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            if let parent = parent, !(parent is UINavigationController || parent is UITabBarController) {
                return false
            }
            return true
        } else if let navController = navigationController, navController.presentingViewController?.presentedViewController == navController {
            return true
        } else if tabBarController?.presentingViewController is UITabBarController {
            return true
        }
        return false
    }
}

Jonauz'un cevabına teşekkürler . Yine daha fazla optimizasyon için alan var. Lütfen yorum bölümünde ele alınması gereken vakayı tartışın.


0

İos 5.0 veya daha sonraki bir sürümünü kullanıyorsanız lütfen bu kodu kullanın

-(BOOL)isPresented
{
    if ([self isBeingPresented]) {
        // being presented
         return YES;
    } else if ([self isMovingToParentViewController]) {
        // being pushed
         return NO;
    } else {
        // simply showing again because another VC was dismissed
         return NO;
    }
}

-1

Merak eden biri için, ViewController'a bunun sunulduğunu nasıl anlarsınız?

eğer Asunuyor / itmeB

  1. Bir enumve propertyiçinde tanımlaB

    enum ViewPresentationStyle {
        case Push
        case Present
    }
    
    //and write property 
    
    var vcPresentationStyle : ViewPresentationStyle = .Push //default value, considering that B is pushed 
  2. Şimdi Agörünüm denetleyicisinde, Batanarak sunulup sunulmadığını söyleyinpresentationStyle

    func presentBViewController() {
        let bViewController = B()
        bViewController.vcPresentationStyle = .Present //telling B that it is being presented
        self.presentViewController(bViewController, animated: true, completion: nil)
    }
  3. BView Controller'da Kullanım

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if self.vcPresentationStyle == .Present {
            //is being presented 
        }
        else {
            //is being pushed
        }
    
    }

-2
id presentedController = self.navigationController.modalViewController;
if (presentedController) {
     // Some view is Presented
} else {
     // Some view is Pushed
}

Bu, viewController'ın sunulup sunulmadığını size bildirir


4
Bu mülk kullanımdan kaldırılmıştır.
Morkrom
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.