अगर UIAlertController पहले से ही प्रस्तुत कर रहा है, तो यह जांचने का सबसे अच्छा तरीका क्या है?


109

मेरे पास एक टेबलव्यू है, जिसे जब लोड किया जाता है, तो प्रत्येक सेल संभवतः एक NSError को वापस कर सकता है, जिसे मैंने UIAlertController में प्रदर्शित करने के लिए चुना है। समस्या यह है कि मुझे यह त्रुटि कंसोल में मिलती है यदि एकाधिक त्रुटियां वापस आती हैं।

चेतावनी: UIAlertController: 0x14e64cb00 पर प्रस्तुत करने का प्रयास करें MessageMasterVC: 0x14e53d800 जो पहले से मौजूद है (अशक्त)

आदर्श रूप में, मैं आदर्श रूप से अपने UIAlertController विस्तार विधि में इसे संभालना चाहूंगा।

class func simpleAlertWithMessage(message: String!) -> UIAlertController {

    let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert)
    let cancel = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)

    alertController.addAction(cancel)
    return alertController
}

मैट के जवाब के आधार पर, मैंने एक्सटेंशन को एक UIViewController एक्सटेंशन में बदल दिया, जो कि बहुत अधिक क्लीनर है और बहुत सारे वर्तमान व्यूकोड कोड को बचाता है।

    func showSimpleAlertWithMessage(message: String!) {

    let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert)
    let cancel = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)

    alertController.addAction(cancel)

    if self.presentedViewController == nil {
        self.presentViewController(alertController, animated: true, completion: nil)
    }
}

अपना अपडेटेड कोड पोस्ट करने के लिए धन्यवाद।
djbp

मैंने भी यदि कथन में बाकी कोड (UIAlertController को स्थापित करने के लिए तीन पंक्तियाँ) को स्थानांतरित कर दिया, क्योंकि यह अभी भी निम्नलिखित त्रुटि दे रहा था (यह देखने की नियंत्रक के दृश्य को लोड करने का प्रयास करते हुए, जबकि डीलक्लॉकिंग की अनुमति नहीं है और परिणाम हो सकता है अपरिभाषित व्यवहार)
Kitson

मैं नीचे दिए गए लिंक पर समाधान का संदर्भ देना चाहूंगा, कृपया stackoverflow.com/a/39994115/1872233
iDevAmit

जवाबों:


119

यह UIAlertController नहीं है जो "पहले से ही प्रस्तुत है", यह MessageMasterVC है। एक दृश्य नियंत्रक एक समय में केवल एक अन्य दृश्य नियंत्रक प्रस्तुत कर सकता है। इसलिए त्रुटि संदेश।

दूसरे शब्दों में, यदि आपने किसी व्यू कंट्रोलर को बताया है, तो आप presentViewController:...तब तक दोबारा ऐसा नहीं कर सकते हैं जब तक कि प्रस्तुत व्यू कंट्रोलर खारिज न कर दिया गया हो।

आप MessageMasterVC से पूछ सकते हैं कि क्या यह पहले से ही इसकी जांच करके एक दृश्य नियंत्रक प्रस्तुत कर रहा है presentedViewController। यदि नहीं nil, तो इसे न बताएं presentViewController:...- यह पहले से ही एक दृश्य नियंत्रक पेश कर रहा है।


2
यदि नियंत्रक A, नियंत्रक B को प्रस्तुत करता है, और B तब UIAlertController प्रस्तुत करना चाहता है, तो क्या वह काम करेगा? मुझे एक ही त्रुटि हो रही है और मैं समझ नहीं पा रहा हूं कि क्या B पहले से ही कुछ ऐसा पेश कर रहा है जिसका मुझे पता नहीं है, या यदि समस्या इसलिए है क्योंकि B को A
क्रिस्टोफर फ्रांसिस्को

1
@ChristopherFrancisco एक नए प्रश्न के रूप में पूछें!
मैट

@ChristopherFrancisco हाय, मुझे अब वही समस्या है, क्या आपने इसके लिए एक नया प्रश्न बनाया है? या जहाँ आप इसे हल करने में सक्षम हैं? यदि हाँ, तो कैसे?
अबेद नासरी

महान उत्तर, यह एक सूक्ष्म अंतर है।
स्कॉट्टीब्लाड्स

29
if ([self.navigationController.visibleViewController isKindOfClass:[UIAlertController class]]) {

      // UIAlertController is presenting.Here

}

22
यह हमेशा एक अच्छा विचार है कि आप क्या कर रहे हैं, यह समझाने के लिए अपने उत्तर में कुछ पाठ डालें। एक अच्छा उत्तर लिखने का तरीका पढ़ें ।
जोर्जेन आर

1
स्पष्टीकरण की कमी के कारण एक महान जवाब नहीं है, लेकिन विधि ने मुझे बहुत मदद की - समस्या यह थी कि मेरे पास एक से अधिक घटनाएँ थीं जो मेरे कोड को UIAlertControllerकम उत्तराधिकार में गोलीबारी पेश करने के लिए बुलाती थीं । यदि आपको इसी तरह की समस्या है तो इसके लिए जाँच करें।
चिदग

10

ठीक है, ऊपर दिए गए सुझाए गए समाधानों में मेरे दृष्टिकोण से एक आवश्यक समस्या है:

यदि आप अपने ViewController से पूछते हैं, क्या विशेषता 'प्रस्तुत ViewController' शून्य है और जवाब गलत है, तो आप इस निष्कर्ष पर नहीं आ सकते हैं, कि आपका UIAlertController पहले से ही प्रस्तुत है। यह किसी भी प्रस्तुत ViewController, उदाहरण के लिए एक पॉपओवर हो सकता है। तो मेरा सुझाव निश्चित रूप से जाँच करने के लिए, कि क्या अलर्ट पहले से ही स्क्रीन पर है, निम्नलिखित है (प्रस्तुत यू कॉन्ट्रोलर को यूआईएलर्टकंट्रोलर के रूप में डालें):

if self.presentedViewController == nil {
   // do your presentation of the UIAlertController
   // ...
} else {
   // either the Alert is already presented, or any other view controller
   // is active (e.g. a PopOver)
   // ...

   let thePresentedVC : UIViewController? = self.presentedViewController as UIViewController?

   if thePresentedVC != nil {
      if let thePresentedVCAsAlertController : UIAlertController = thePresentedVC as? UIAlertController {
         // nothing to do , AlertController already active
         // ...
         print("Alert not necessary, already on the screen !")

      } else {
         // there is another ViewController presented
         // but it is not an UIAlertController, so do 
         // your UIAlertController-Presentation with 
         // this (presented) ViewController
         // ...
         thePresentedVC!.presentViewController(...)

         print("Alert comes up via another presented VC, e.g. a PopOver")
      }
  }

}


5

यहाँ एक समाधान है जो मैं स्विफ्ट 3 में उपयोग करता हूं। यह एक ऐसा कार्य है जो उपयोगकर्ता को अलर्ट दिखाता है, और यदि आप उपयोगकर्ता द्वारा अलर्ट को खारिज करने से पहले इसे कई बार कॉल करते हैं, तो यह नए अलर्ट टेक्स्ट को अलर्ट में जोड़ देगा जो पहले से ही प्रस्तुत किया जा रहा है। । यदि कुछ अन्य दृश्य प्रस्तुत किया जा रहा है, तो अलर्ट दिखाई नहीं देगा। सभी उस व्यवहार से सहमत नहीं होंगे, लेकिन यह सरल परिस्थितियों के लिए अच्छी तरह से काम करता है।

extension UIViewController {
    func showAlert(_ msg: String, title: String = "") {
        if let currentAlert = self.presentedViewController as? UIAlertController {
            currentAlert.message = (currentAlert.message ?? "") + "\n\nUpdate:\(title): \(msg)"
            return
        }

        // create the alert
        let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert)
        alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))

        // show the alert
        self.present(alert, animated: true, completion: nil)
    }
}

ठीक है, यह वही है जो मुझे चाहिए था। यह iOS 13 में भी काम करता है।
ज़ोल्टन विंकलर

3

हम केवल यह देख सकते हैं कि कोई दृश्य नियंत्रक प्रस्तुत किया गया है या नहीं।

यदि प्रस्तुत किया गया है, तो जांचें कि क्या यह UIAlertController की तरह है।

    id alert = self.presentedViewController;

    if (alert && [alert isKindOfClass:[UIAlertController class]]) 
      {
           *// YES UIAlertController is already presented*
      }
    else
       {
        // UIAlertController is not presented OR visible.
       }

1

आप परीक्षण कर सकते हैं - एक पंक्ति में - यदि कोई चेतावनी पहले से ही प्रस्तुत की गई है:

if self.presentedViewController as? UIAlertController != nil {
    print ("alert already presented")
}

आप अपने उत्तर में कोड की व्याख्या कर सकते हैं। या यह कैसे प्रासंगिक जानकारी जोड़ता है जब पहले से ही एक स्वीकृत या उच्च श्रेणी निर्धारण उत्तर है एक अच्छा उत्तर लिखने का तरीका
Léa Gris


0

मैंने इसका उपयोग किया और पता लगाने और सतर्क करने के लिए।

पहले हम निम्नलिखित फंक्शन के साथ एक अलर्ट बनाते हैं।

 var yourAlert :UIAlertController!

 func useYouAlert (header: String, info:String){


    yourAlert = UIAlertController(title:header as String, message: info as String, preferredStyle: UIAlertControllerStyle.alert)



    let okAction = UIAlertAction(title: self.langText[62]as String, style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
        print("OK") 

    }


    yourAlert.addAction(okAction)
    self.present(yourAlert.addAction, animated: true, completion: nil)

}

और आपके कोड के किसी अन्य भाग में

    if yourAlert != nil {

      yourAlert.dismiss(animated: true, completion: nil)

    }

0

नवीनतम स्विफ्ट भाषा के लिए आप निम्नलिखित का उपयोग कर सकते हैं:

var alert = presentedViewController

if alert != nil && (alert is UIAlertController) {
    // YES UIAlertController is already presented*
} else {
    // UIAlertController is not presented OR visible.
}

0

वर्तमान कंट्रोलर को डिसमिस करें और अलर्ट कंट्रोलर को पेश करें

 func alert(_ message:String) {
  let alert = UIAlertController(title: "Error!", message: message, preferredStyle: .alert)
  alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
  self.dismiss(animated: false, completion: nil)
  self.present(alert, animated: true,completion: nil)
    }

0

स्विफ्ट 4.2+ उत्तर

if UIApplication.topViewController()!.isKind(of: UIAlertController.self) { 
            print("UIAlertController is presented")}

उन लोगों के लिए जो टॉप व्यू व्यूकंट्रोलर प्राप्त करना नहीं जानते हैं

extension UIApplication {


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

स्विफ्ट 5+ उत्तर 'keyWindow' को iOS 13.0 में सुझाए गए एडिट में चित्रित किया गया था

if UIApplication.topViewController()!.isKind(of: UIAlertController.self) { 
            print("UIAlertController is presented")}

उन लोगों के लिए जो टॉप व्यू व्यूकंट्रोलर प्राप्त करना नहीं जानते हैं

extension UIApplication {


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

0

मैंने पाया कि मुझे UIAlertController अनुरोध को स्टैक करने के लिए एक कतार बनाने की आवश्यकता है।

NSMutableArray *errorMessagesToShow; // in @interface
errorMessagesToShow=[[NSMutableArray alloc] init];  // in init

-(void)showError:(NSString *)theErrorMessage{
    if(theErrorMessage.length>0){
        [errorMessagesToShow addObject:theErrorMessage];
        [self showError1];
    }
}
-(void)showError1{
    NSString *theErrorMessage;
    if([errorMessagesToShow count]==0)return; // queue finished

    UIViewController* parentController =[[UIApplication sharedApplication]keyWindow].rootViewController;
    while( parentController.presentedViewController &&
      parentController != parentController.presentedViewController ){
        parentController = parentController.presentedViewController;
    }
    if([parentController isKindOfClass:[UIAlertController class]])return;  // busy

    // construct the alert using [errorMessagesToShow objectAtIndex:0]
    //  add to each UIAlertAction completionHandler [self showError1];
    //   then

    [errorMessagesToShow removeObjectAtIndex:0];
    [parentController presentViewController:alert animated:YES completion:nil]; 
}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.