Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show Actionsheet in iPad

How can I show a UIActionsheet in iPad when I'm using my current code its giving me this error:

Your application has presented a UIAlertController (<UIAlertController: 0x7f9ec624af70>) of style UIAlertControllerStyleActionSheet. The modalPresentationStyle of a UIAlertController with this style is UIModalPresentationPopover. You must provide location information for this popover through the alert controller's popoverPresentationController. You must provide either a sourceView and sourceRect or a barButtonItem. If this information is not known when you present the alert controller, you may provide it in the UIPopoverPresentationControllerDelegate method -prepareForPopoverPresentation.

which is working totally fine in an iPhone :

let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
let reminderAction = UIAlertAction(title: "Reminder", style: .Default, handler: {
                (alert: UIAlertAction!) -> Void in }
optionMenu.addAction(reminderAction)
self.presentViewController(optionMenu, animated: true, completion: nil)

I came across some similar problems, the solution was this:

let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
optionMenu.popoverPresentationController?.sourceView = self.view
optionMenu.popoverPresentationController?.sourceRect = self.view.bounds

but it didnt worked for me maybe because my ActionSheet's Sender is on a UItableviewCell.

I tired to set AlertController's Sourceview to tableView's Cell but its not correctly placed and sometime its partially visible this is what I tried:

optionMenu.popoverPresentationController?.sourceView = currentCell.contentView
optionMenu.popoverPresentationController?.sourceRect = currentCell.contentView.bounds

Any clue how can I fix this problem?

like image 566
remy boys Avatar asked Aug 09 '16 19:08

remy boys


2 Answers

The sample code given below works both on iPhone and iPad.

 guard let viewRect = sender as? UIView else {
            return
        }

    let cameraSettingsAlert = UIAlertController(title: NSLocalizedString("Please choose a course", comment: ""), message: NSLocalizedString("", comment: ""), preferredStyle: .ActionSheet)
    cameraSettingsAlert.modalPresentationStyle = .Popover

    let photoResolutionAction = UIAlertAction(title: NSLocalizedString("Photo Resolution", comment: ""), style: .Default) { action in

    }
    let cameraOrientationAction = UIAlertAction(title: NSLocalizedString("Camera Orientation", comment: ""), style: .Default) { action in

    }
    let flashModeAction = UIAlertAction(title: NSLocalizedString("Flash Mode", comment: ""), style: .Default) { action in

    }
    let timeStampOnPhotoAction = UIAlertAction(title: NSLocalizedString("Time Stamp on Photo", comment: ""), style: .Default) { action in

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

    }
    cameraSettingsAlert.addAction(cancel)
    cameraSettingsAlert.addAction(cameraOrientationAction)
    cameraSettingsAlert.addAction(flashModeAction)
    cameraSettingsAlert.addAction(timeStampOnPhotoAction)
    cameraSettingsAlert.addAction(photoResolutionAction)

    if let presenter = cameraSettingsAlert.popoverPresentationController {
        presenter.sourceView = viewRect;
        presenter.sourceRect = viewRect.bounds;
    }
    presentViewController(cameraSettingsAlert, animated: true, completion: nil)
like image 66
Prashant Ghimire Avatar answered Oct 24 '22 18:10

Prashant Ghimire


Swift 4.1 Solution:-

  1. MAK Eextension FILE UIDEviceExtension.swift and with below code :-
import Foundation
import UIKit
public extension UIDevice {

    public class var isPhone: Bool {
        return UIDevice.current.userInterfaceIdiom == .phone
    }

    public class var isPad: Bool {
        return UIDevice.current.userInterfaceIdiom == .pad
    }

    public class var isTV: Bool {
        return UIDevice.current.userInterfaceIdiom == .tv
    }

    public class var isCarPlay: Bool {
        return UIDevice.current.userInterfaceIdiom == .carPlay
    }

}
  1. Call your action Sheet on UIViewcontroller By this Separate common method :-
import Foundation
import UIKit
class Common: NSObject{
       public class func showActionSheet(vc: UIViewController,sender:UIButton? = nil) {

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

                actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (alert:UIAlertAction!) -> Void in
                    //self.camera()
                }))

                actionSheet.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { (alert:UIAlertAction!) -> Void in
                    //self.photoLibrary()
                }))

                actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

                //if iPhone
                if UIDevice.isPhone {
                    vc.present(actionSheet, animated: true, completion: nil)
                }
                else {
                    //In iPad Change Rect to position Popover
                    if let btn = sender{
                        actionSheet.popoverPresentationController?.sourceRect = btn.frame
                        actionSheet.popoverPresentationController?.sourceView = vc.view

                    }
                    vc.present(actionSheet, animated: true, completion: nil)
                }

            }
    }
  1. Use it from your UIButton Click for iPhone/iPad both :-
   @objc func btnPicImageTaped(btn:UIButton){
        print("it will work for both iPhone /ipad")
        Common.showActionSheet(vc: self,sender: btn)
}
like image 37
Abhimanyu Rathore Avatar answered Oct 24 '22 17:10

Abhimanyu Rathore