現在のコードを使用しているときにiPadでUIActionsheet
を表示するには、次のエラーが表示されます。
アプリケーションは、スタイル
UIAlertController
のUIAlertControllerStyleActionSheet
(<UIAlertController: 0x7f9ec624af70>
)を提示しました。このスタイルのmodalPresentationStyle
のUIAlertController
はUIModalPresentationPopover
です。アラートコントローラのpopoverPresentationController
を介して、このポップオーバーの位置情報を提供する必要があります。sourceView
とsourceRect
またはbarButtonItem
のいずれかを指定する必要があります。アラートコントローラを提示したときにこの情報がわからない場合は、UIPopoverPresentationControllerDelegate
メソッド-prepareForPopoverPresentation
で提供できます。
これは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)
私はいくつかの同様の問題に遭遇しました、解決策はこれでした:
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
optionMenu.popoverPresentationController?.sourceView = self.view
optionMenu.popoverPresentationController?.sourceRect = self.view.bounds
しかし、おそらく私のActionSheetの送信者がUItableviewCellにあるため、うまくいきませんでした。
AlertControllerのSourceviewをtableViewのCellに設定するのに疲れましたが、正しく配置されておらず、部分的に表示されることがあります。これが私が試したものです。
optionMenu.popoverPresentationController?.sourceView = currentCell.contentView
optionMenu.popoverPresentationController?.sourceRect = currentCell.contentView.bounds
この問題を解決するにはどうすればよいですか?
以下に示すサンプルコードは、iPhoneと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)
IPadでActionSheetを表示したい場合は、popoverPresentationControllerを使用して表示し、iPadではアクションシートのキャンセルスタイルボタンを表示しません。このコードをSwift 3:
@IBAction func ActionSheetShow(_ sender: UIButton) {
let actionSheet = UIAlertController(title: "Choose any option", message: "choose as you like here!", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Click1", style: .cancel, handler: {
action in
print("first button")
}))
actionSheet.addAction(UIAlertAction(title: "Click2", style: .default, handler: {
action in
print("second button")
}))
actionSheet.addAction(UIAlertAction(title: "Click3", style: .destructive, handler: {
action in
print("third button")
}))
actionSheet.popoverPresentationController?.sourceView = self.view
actionSheet.popoverPresentationController?.sourceRect = sender.frame
present(actionSheet, animated: true, completion: nil)
}
幸運を!
Swift 4.1ソリューション:-
- MAK拡張ファイルUIDEviceExtension.Swiftおよび以下のコード:-
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
}
}
- UIViewcontrollerでアクションシートを呼び出すこの個別の一般的な方法:-
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)
}
}
}
- UIButton Click for iPhone/iPadから使用してください:-
@objc func btnPicImageTaped(btn:UIButton){
print("it will work for both iPhone /ipad")
Common.showActionSheet(vc: self,sender: btn)
}
PresentViewControllerの前に次の2行を追加します。 (Swift 3.2)
optionMenu.popoverPresentationController?.sourceView = self.view
optionMenu.popoverPresentationController?.sourceRect = (sender as AnyObject).frame
present(optionMenu, animated: true, completion: nil)
Swift 5用に更新
extension UIDevice {
class var isPhone: Bool {
return UIDevice.current.userInterfaceIdiom == .phone
}
class var isPad: Bool {
return UIDevice.current.userInterfaceIdiom == .pad
}
class var isTV: Bool {
return UIDevice.current.userInterfaceIdiom == .tv
}
class var isCarPlay: Bool {
return UIDevice.current.userInterfaceIdiom == .carPlay
}
}