IOS 8 का उपयोग करते हुए एक iPad पर ठीक से UIAlertController पेश करना


194

आईओएस 8.0 के साथ, एप्पल की शुरुआत की UIAlertController को बदलने के लिए UIActionSheet । दुर्भाग्य से, Apple ने इसे प्रस्तुत करने के बारे में कोई जानकारी नहीं जोड़ी। मुझे इसके बारे में hayaGeek के ब्लॉग पर एक प्रविष्टि मिली , हालाँकि, यह iPad पर काम नहीं करता है। दृश्य पूरी तरह से गलत है:

गलत: गलत छवि

सही बात: यहां छवि विवरण दर्ज करें

मैं इंटरफ़ेस पर इसे दिखाने के लिए निम्न कोड का उपयोग करता हूं:

    let alert = UIAlertController()
    // setting buttons
    self.presentModalViewController(alert, animated: true)

क्या आईपैड के लिए इसे जोड़ने का एक और तरीका है? या क्या Apple अभी iPad भूल गया, या लागू नहीं हुआ, अभी तक?

जवाबों:


284

आप UIAlertControllerएक पॉपओवर से उपयोग करके प्रस्तुत कर सकते हैं UIPopoverPresentationController

ओब्ज-सी में:

UIViewController *self; // code assumes you're in a view controller
UIButton *button; // the button you want to show the popup sheet from

UIAlertController *alertController;
UIAlertAction *destroyAction;
UIAlertAction *otherAction;

alertController = [UIAlertController alertControllerWithTitle:nil
                                                      message:nil
                           preferredStyle:UIAlertControllerStyleActionSheet];
destroyAction = [UIAlertAction actionWithTitle:@"Remove All Data"
                                         style:UIAlertActionStyleDestructive
                                       handler:^(UIAlertAction *action) {
                                           // do destructive stuff here
                                       }];
otherAction = [UIAlertAction actionWithTitle:@"Blah"
                                       style:UIAlertActionStyleDefault
                                     handler:^(UIAlertAction *action) {
                                         // do something here
                                     }];
// note: you can control the order buttons are shown, unlike UIActionSheet
[alertController addAction:destroyAction];
[alertController addAction:otherAction];
[alertController setModalPresentationStyle:UIModalPresentationPopover];

UIPopoverPresentationController *popPresenter = [alertController 
                                              popoverPresentationController];
popPresenter.sourceView = button;
popPresenter.sourceRect = button.bounds;
[self presentViewController:alertController animated:YES completion:nil];

स्विफ्ट 4.2 के लिए संपादन, हालांकि उसी के लिए कई ब्लॉग उपलब्ध हैं, लेकिन यह जाने और उन्हें खोजने के लिए आपके समय को बचा सकता है।

 if let popoverController = yourAlert.popoverPresentationController {
                popoverController.sourceView = self.view //to set the source of your alert
                popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0) // you can set this as per your requirement.
                popoverController.permittedArrowDirections = [] //to hide the arrow of any particular direction
            }

उपयोग करें [alertController.view setTintColor: [UIColor blackColor]]; यदि आप पाठ नहीं देखते हैं। UIAlertController डिफ़ॉल्ट रूप से विंडो के टिंट रंग का उपयोग करता है, जो इस उदाहरण में सफेद और अदृश्य हो सकता है।
Whyoz

2
रद्द करें बटन iPad में प्रदर्शित नहीं हो रहा है
भाविन रमानी

14
@BhavinRamani रद्द करें बटन स्वचालित रूप से पॉपओवर से हटा दिए जाते हैं, क्योंकि पॉपओवर के बाहर टैपिंग एक पॉपिंग संदर्भ में "रद्द" का प्रतिनिधित्व करता है।
क्रिस्टोफरड्रम

यह बहुत बढ़िया है, मेरी समस्या हल हो गई है! आपको बहुत - बहुत धन्यवाद!
माहिर तयिर

109

IPad पर अलर्ट को नए UIPopoverPresentationController का उपयोग करते हुए एक पॉपओवर के रूप में प्रदर्शित किया जाएगा , इसके लिए आवश्यक है कि आप पॉपऑवर की प्रस्तुति के लिए एक एंकर पॉइंट निर्दिष्ट करें जो किसी sourceView और sourceRect या barButorItem का उपयोग कर रहा हो

  • barButtonItem
  • sourceView
  • sourceRect

लंगर बिंदु को निर्दिष्ट करने के लिए आपको UIAlertController के UIPopoverPresentationController का संदर्भ प्राप्त करना होगा और निम्न में से कोई एक गुण सेट करना होगा:

alertController.popoverPresentationController.barButtonItem = button;

नमूना कोड:

UIAlertAction *actionDelete = nil;
UIAlertAction *actionCancel = nil;

// create action sheet
UIAlertController *alertController = [UIAlertController
                                      alertControllerWithTitle:actionTitle message:nil
                                      preferredStyle:UIAlertControllerStyleActionSheet];

// Delete Button
actionDelete = [UIAlertAction
                actionWithTitle:NSLocalizedString(@"IDS_LABEL_DELETE", nil)
                style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {

                    // Delete
                    // [self deleteFileAtCurrentIndexPath];
                }];

// Cancel Button
actionCancel = [UIAlertAction
                actionWithTitle:NSLocalizedString(@"IDS_LABEL_CANCEL", nil)
                style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
                    // cancel
                    // Cancel code
                }];

// Add Cancel action
[alertController addAction:actionCancel];
[alertController addAction:actionDelete];

// show action sheet
alertController.popoverPresentationController.barButtonItem = button;
alertController.popoverPresentationController.sourceView = self.view;

[self presentViewController:alertController animated:YES
                 completion:nil];

28
यह "तीन में से एक" लंगर बिंदु गुण नहीं है; यह है: "या तो एक sourceView और sourceRect या एक barButtonItem"।
रोलिक

2
रोलरिक के लिए +1। Apple के दस्तावेज़ीकरण में sourceRect के बारे में बताया गया है: "पॉपओवर के लिए लंगर स्थान को निर्दिष्ट करने के लिए sourceView संपत्ति के साथ संयोजन में इस संपत्ति का उपयोग करें। वैकल्पिक रूप से, आप barButtonItem संपत्ति का उपयोग करके पॉपओवर के लिए लंगर स्थान निर्दिष्ट कर सकते हैं।" - developer.apple.com/library/prerelease/ios/documentation/UIKit/…
बेन पैच

ओह यार। यह बिना किसी लॉग संदेश के दुर्घटनाग्रस्त हो गया। कम से कम संकलन-समय की चेतावनी (सार्वभौमिक ऐप्स के लिए) क्यों नहीं दी जाएगी?
माइक केसिनकोव

85

Swift 2 में, आप iPhone और iPad पर इसे ठीक से दिखाने के लिए ऐसा कुछ करना चाहते हैं:

func confirmAndDelete(sender: AnyObject) {
    guard let button = sender as? UIView else {
        return
    }

    let alert = UIAlertController(title: NSLocalizedString("Delete Contact?", comment: ""), message: NSLocalizedString("This action will delete all downloaded audio files.", comment: ""), preferredStyle: .ActionSheet)
    alert.modalPresentationStyle = .Popover

    let action = UIAlertAction(title: NSLocalizedString("Delete", comment: ""), style: .Destructive) { action in
        EarPlaySDK.deleteAllResources()
    }
    let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel) { action in

    }
    alert.addAction(cancel)
    alert.addAction(action)

    if let presenter = alert.popoverPresentationController {
        presenter.sourceView = button
        presenter.sourceRect = button.bounds
    }
    presentViewController(alert, animated: true, completion: nil)
}

यदि आप प्रस्तुतकर्ता सेट नहीं करते हैं, तो आप -[UIPopoverPresentationController presentationTransitionWillBegin]निम्नलिखित संदेश के साथ iPad पर एक अपवाद के साथ समाप्त करेंगे :

घातक अपवाद: NSGenericException आपके एप्लिकेशन ने शैली UIAlertControllerStyleActionleheet पर UIAlertController (<UIAlertController: 0x17858a00>) प्रस्तुत किया है। इस शैली के साथ एक UIAlertController की modalPresentationStyle UIModalPresentationPopover है। आपको इस जानकारी के लिए अलर्ट नियंत्रक के popoverPresentationController के माध्यम से जानकारी प्रदान करनी होगी। आपको या तो एक sourceView और sourceRect या एक barButtonItem प्रदान करना होगा। यदि यह जानकारी ज्ञात नहीं है जब आप अलर्ट नियंत्रक प्रस्तुत करते हैं, तो आप इसे UIPopoverPresentationControllerDelegate विधि -prepareForPopoverPresentation में प्रदान कर सकते हैं।


26

स्विफ्ट 3.0 और उच्चतर के लिए अपडेट करें

    let actionSheetController: UIAlertController = UIAlertController(title: "SomeTitle", message: nil, preferredStyle: .actionSheet)

    let editAction: UIAlertAction = UIAlertAction(title: "Edit Details", style: .default) { action -> Void in

        print("Edit Details")
    }

    let deleteAction: UIAlertAction = UIAlertAction(title: "Delete Item", style: .default) { action -> Void in

        print("Delete Item")
    }

    let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .cancel) { action -> Void in }

    actionSheetController.addAction(editAction)
    actionSheetController.addAction(deleteAction)
    actionSheetController.addAction(cancelAction)

//        present(actionSheetController, animated: true, completion: nil)   // doesn't work for iPad

    actionSheetController.popoverPresentationController?.sourceView = yourSourceViewName // works for both iPhone & iPad

    present(actionSheetController, animated: true) {
        print("option menu presented")
    }

मैं दराज का उपयोग कर रहा हूं, मैं दिए गए समाधान का उपयोग करने की कोशिश करता हूं, लेकिन विफल रहा।
राणा अली वसीम

मेरे पास कोड नहीं है, क्योंकि मैं एक्शन शीट निकालता हूं और अलर्ट का उपयोग करता हूं। लेकिन मेरे कोड में सिर्फ एक पंक्ति अलग थी एक्शनशीट = UIAlertController (शीर्षक: "", मैसेज, ":", अधिमान्यता: .actSheet) लेकिन मुझे लॉग याद है, यह दराज के कारण दुर्घटनाग्रस्त हो गया था, मुझे लगता है कि दराज खोलने के लिए विरोध करता है। एक्शन शीट। क्योंकि यह स्क्रीन के बाएं कोने में खुल रहा था। मुद्दा केवल iPad पर था।
राणा अली वसीम

15

2018 अपडेट

मेरे पास इस कारण से एक ऐप अस्वीकृत था और एक त्वरित समाधान एक एक्शन शीट का उपयोग करके अलर्ट में बदलने के लिए था।

एक आकर्षण काम किया और ऐप स्टोर के परीक्षकों को बस ठीक कर दिया।

सभी के लिए एक उपयुक्त उत्तर नहीं हो सकता है, लेकिन मुझे आशा है कि यह आप में से कुछ को जल्दी से बाहर निकालने में मदद करता है।


1
आईपैड और आईफोन दोनों पर पूरी तरह से काम किया - धन्यवाद
जेरेमी एंड्रयूज

यह सबसे अच्छा समाधान नहीं है। कभी-कभी आप एक्शनशीट शैली का उपयोग करना चाहते हैं, जो आधुनिक है।
ShadeToD

9

स्विफ्ट 4 और इसके बाद के संस्करण

मैंने एक एक्सटेंशन बनाया है

extension UIViewController {
  public func addActionSheetForiPad(actionSheet: UIAlertController) {
    if let popoverPresentationController = actionSheet.popoverPresentationController {
      popoverPresentationController.sourceView = self.view
      popoverPresentationController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
      popoverPresentationController.permittedArrowDirections = []
    }
  }
}

कैसे इस्तेमाल करे:

let actionSheetVC = UIAlertController(title: "Title", message: nil, preferredStyle: .actionSheet)
addActionSheetForIpad(actionSheet: actionSheetVC)
present(actionSheetVC, animated: true, completion: nil)

मैं इसे करने की कोशिश करता हूं, लेकिन xcode 11.2.1 में func addActionSheerForiPad को कॉल करने में सक्षम नहीं हूं
राणा अली वसीम

@ RanaAliWaseem क्या आप इसे UIViewController क्लास के अंदर बुला रहे हैं?
ShadeToD

हाँ। मैं इसे UIViewController क्लास में कहता हूं। लेकिन यह UIViewController से विरासत में मिली बेस क्लास और बेस क्लास के साथ विरासत में मिला है।
राणा अली वसीम

8

यहाँ एक त्वरित समाधान है:

NSString *text = self.contentTextView.text;
NSArray *items = @[text];

UIActivityViewController *activity = [[UIActivityViewController alloc]
                                      initWithActivityItems:items
                                      applicationActivities:nil];

activity.excludedActivityTypes = @[UIActivityTypePostToWeibo];

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
    //activity.popoverPresentationController.sourceView = shareButtonBarItem;

    activity.popoverPresentationController.barButtonItem = shareButtonBarItem;

    [self presentViewController:activity animated:YES completion:nil];

}
[self presentViewController:activity animated:YES completion:nil];

3
यह सवाल UIAlertController के बारे में है, UIActivityViewController के बारे में नहीं
रोमन

क्या आप UIActivityViewController के साथ स्विफ्ट 3 का जवाब अपडेट कर सकते हैं?
दीया

7

स्विफ्ट 5

मैंने iPhone के लिए "एक्शनशीट" शैली और iPad के लिए "अलर्ट" का उपयोग किया। iPad स्क्रीन के केंद्र में प्रदर्शित होता है। स्रोत दृश्य निर्दिष्ट करने या कहीं भी एंकर को देखने की आवश्यकता नहीं है।

var alertStyle = UIAlertController.Style.actionSheet
if (UIDevice.current.userInterfaceIdiom == .pad) {
  alertStyle = UIAlertController.Style.alert
}

let alertController = UIAlertController(title: "Your title", message: nil, preferredStyle: alertStyle)

संपादित करें: ShareToD के सुझाव के अनुसार, अपडेट किया गया "UI_USER_INTERFACE_IDIOM () == UIUserInterfaceIdiom.pad" चेक


2
iOS 13 में 'UI_USER_INTERFACE_IDIOM' (13) iOS 13.0 में उपयोग किया गया था: - [UIDevice userInterfaceIdiom] सीधे। आपको इसे UIDevice.current.userInterfaceIdiom == .pad पर बदलना चाहिए
ShadeToD

इस दृष्टिकोण का एक नुकसान यह है कि अलर्ट अपनी सीमा के बाहर क्लिक करने पर खारिज करने योग्य नहीं है
mliu

2

मेरे लिए मुझे बस निम्नलिखित जोड़ना होगा:

if let popoverController = alertController.popoverPresentationController {
    popoverController.barButtonItem = navigationItem.rightBarButtonItem
}

2
आप अगर बयान को छोड़ देते हैं और वैकल्पिक श्रृंखलन का उपयोग कर सकते हैं: alertController.popoverPresentationController .barButtonItem = navigationItem.rightBarButtonItem?
डेल

2

अपनी कार्रवाई पत्रक प्रस्तुत करने से पहले बस निम्नलिखित कोड जोड़ें:

if let popoverController = optionMenu.popoverPresentationController {
    popoverController.sourceView = self.view
    popoverController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
    popoverController.permittedArrowDirections = []
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.