I am trying to implement actionsheet in ipad with the help of popoverPresentationController.everything is working fine but i am facing one problem that Cancel
style button is not coming in the actionsheet.
here is my code for refernece
#IBAction func logoutAction(_ sender: UIButton) {
let alertController = UIAlertController(title: "", message: "do you want to logout", preferredStyle: .actionSheet)
let yesAction = UIAlertAction(title: "Logout", style: .destructive, handler: { (action) -> Void in
Singleton.sharedInstance.logoutButtonAction()
logEvent(label: "user_log_out")
})
let noAction = UIAlertAction(title: "cancel", style: .cancel, handler: { (action) -> Void in
self?.dismiss(animated: true, completion: nil)
})
alertController.addAction(yesAction)
alertController.addAction(noAction)
alertController.popoverPresentationController?.sourceView = self?.view
alertController.popoverPresentationController?.sourceRect = sender.frame
/* if let presenter = alertController.popoverPresentationController {
presenter.sourceView = self!.logoutButton
presenter.sourceRect = self!.logoutButton.bounds
}*/
self?.present(alertController, animated: true, completion: nil)
})
}
```
I have two buttons, one that shows the segmented control and one that tries to hide it. The problem is when I click the one to show it, it works. However, when I click the one to hide it, it doesn't work. Here is my code:
let delayHide = UIAlertAction(title: "Hide Delay", style: .default) { (action) in
self.segmentedHidden = 1
self.setupSegmented()
}
let delayShow = UIAlertAction(title: "Show Delay", style: .default) { (action) in
self.segmentedHidden = 0
self.setupSegmented()
}
Here is also the code for when I try to hide it:
if (segmentedHidden == 0) {
segmentedControl.isHidden = false
} else {
segmentedControl.isHidden = true
}
Where did I go wrong?
Use following code:
#IBAction func buttonTapped(_ sender: UIButton) {
let alert = UIAlertController(title: "Alert", message: "Segment", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Show", style: .default, handler: { (alertAction) in
self.showHideSegmentControl(isHidden: false)
}))
alert.addAction(UIAlertAction(title: "hide", style: .default, handler: { (alertAction) in
self.showHideSegmentControl(isHidden: true)
}))
self.present(alert, animated: true, completion: nil)
}
func showHideSegmentControl(isHidden: Bool) {
segmentedControl.isHidden = isHidden
}
I'm a huge beginner when it comes to programming.
I currently have an alert controller set up so that when I click a button in the view controller an alert controller pops up. I can enter text into a textfield (in the alert controller) and the text will show up on a label (in my view controller), when I click okay (in the alert controller). This is the code for what i have:
//Text button
#IBOutlet weak var TextLabel: UILabel!
#IBAction func TextButtonTapped(_ sender: UIButton) {
print("Text Button Tapped")
openTextAlert()
}
func openTextAlert() {
//Create Alert Controller
let alert9 = UIAlertController (title: "Whatever Text Your Heart Desires:", message: nil, preferredStyle: UIAlertControllerStyle.alert)
//Create Cancel Action
let cancel9 = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
alert9.addAction(cancel9)
//Create OK Action
let ok9 = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) { (action: UIAlertAction) in print("OK")
let textfield = alert9.textFields?[0]
print(textfield?.text!)
self.TextLabel.text = textfield?.text!
}
alert9.addAction(ok9)
//Add Text Field
alert9.addTextField { (textfield: UITextField) in
textfield.placeholder = "Whatever text you want to enter"
}
//Present Alert Controller
self.present(alert9, animated:true, completion: nil)
}
How can I get multiple actions in my alert controller so that it ALSO acts as a dropdown menu with certain words so that I don't need to always write out key words? I need both, the ability to type my own words and phrases and a preset of words and phrases for efficiency.
Please help! I'm a huge noob. Thank you :)
Swift 3, Xcode 8, IOS
Just write this using your code. Is this what you need?
EDIT: the yourNewButtonTapped function is simply to show you how you can set a condition to show either the simple alert or the actionSheet. In this function, when you click your new button, and then your TextButton, your alert will be shown. If you click your new button again, you will set userWantsToShowAlert as false. And when you click again your textButtonTapped, the openActionSheet will be called.
You can do this in so many ways.
#IBOutlet weak var TextLabel: UILabel!
var userWantsToShowAlert = false
#IBAction func yourNewButtonTapped(_ sender: UIButton) {
userWantsToShowAlert = !userWantsToShowAlert
print("User wants to show alert? \(userWantsToShowAlert)")
//This is userWantsToShowAlert is false, it will change it to true. And if it is true, it will change it to false.
}
#IBAction func TextButtonTapped(_ sender: UIButton) {
print("Text Button Tapped")
if(userWantsToShowAlert){
openTextAlert()
}else{
openActionSheetAlert()
}
}
func openTextAlert() {
//Create Alert Controller
let alert9 = UIAlertController (title: "Whatever Text Your Heart Desires:", message: nil, preferredStyle: UIAlertControllerStyle.alert)
//Create Cancel Action
let cancel9 = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
alert9.addAction(cancel9)
//Create OK Action
let ok9 = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) { (action: UIAlertAction) in print("OK")
let textfield = alert9.textFields?[0]
print(textfield?.text!)
self.TextLabel.text = textfield?.text!
}
alert9.addAction(ok9)
//Add Text Field
alert9.addTextField { (textfield: UITextField) in
textfield.placeholder = "Whatever text you want to enter"
}
//Present Alert Controller
self.present(alert9, animated:true, completion: nil)
}
func openActionSheetAlert(){
let alert9 = UIAlertController (title: "Whatever Text Your Heart Desires:", message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
//Create Cancel Action
let cancel9 = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
alert9.addAction(cancel9)
let bt1 = UIAlertAction(title: "1", style: UIAlertActionStyle.default){
(action) in self.TextLabel.text = "Word 1"}
alert9.addAction(bt1)
let bt2 = UIAlertAction(title: "2", style: UIAlertActionStyle.default){
(action) in self.TextLabel.text = "Word 2"}
alert9.addAction(bt2)
let bt3 = UIAlertAction(title: "3", style: UIAlertActionStyle.default){
(action) in self.TextLabel.text = "Word 3"}
alert9.addAction(bt3)
let bt4 = UIAlertAction(title: "4", style: UIAlertActionStyle.default){
(action) in self.TextLabel.text = "Word 4"}
alert9.addAction(bt4)
alert9.popoverPresentationController?.sourceView = self.view
alert9.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.size.width / 2.0, y: self.view.bounds.size.height / 2.0, width: 1.0, height: 1.0)
self.present(alert9, animated:true, completion: nil)
}
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?
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)
If you want to show any ActionSheet on iPad so their use popoverPresentationController to show and at iPad don't show the cancel style button of action sheet.
Use this code in 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)
}
Good Luck!
Swift 4.1 Solution:-
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
}
}
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)
}
}
}
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)
}
Add Following two lines before presentViewController. (Swift 3.2)
optionMenu.popoverPresentationController?.sourceView = self.view
optionMenu.popoverPresentationController?.sourceRect = (sender as AnyObject).frame
present(optionMenu, animated: true, completion: nil)
Updated for 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
}
}
You can take sourceView & sourceRect from sender:
#IBAction func btMenuPressed(_ sender: Any) {
let Sender = sender as? UIButton
let actSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
actSheet.addAction(UIAlertAction(title: "settings", style: .default) { _ in self.doSettings() })
...
...
actSheet.popoverPresentationController?.sourceView = Sender!.superview!
actSheet.popoverPresentationController?.sourceRect = Sender!.frame
resent(actSheet, animated: true)
}
Swift 5+ solution Very smooth and easy just call this function and you will easy solve your problem
let IPAD = UIDevice.current.userInterfaceIdiom == .pad
//Mark:- Choose Action Sheet Methods
func actionSheet() {
var actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertController.Style.actionSheet)
actionSheet.view.tintColor = UIColor.black
let button1 = UIAlertAction(title: "Button 1".localizableString(language: Defaults.selectedLanguageCode), style: .default, handler: {
(alert: UIAlertAction!) -> Void in
})
let button2 = UIAlertAction(title: "Button 2".localizableString(language: Defaults.selectedLanguageCode), style: .default, handler: {
(alert: UIAlertAction!) -> Void in
})
let cancelAction = UIAlertAction(title: "Cancel".localizableString(language: Defaults.selectedLanguageCode), style: .cancel, handler: {
(alert: UIAlertAction!) -> Void in
})
if IPAD {
//In iPad Change Rect to position Popover
actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertController.Style.alert)
}
actionSheet.addAction(button1)
actionSheet.addAction(button2)
actionSheet.addAction(cancelAction)
print("Action Sheet Open")
self.present(actionSheet, animated: true, completion: nil)
}
#IBAction func addToCart(sender: AnyObject) {
let itemObjectTitle = itemObject.valueForKey("itemDescription") as! String
let alertController = UIAlertController(title: "Add \(itemObjectTitle) to cart?", message: "", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) { (action) in
var badgeNumber = 0
self.navigationController!.tabBarItem.badgeValue == "\(badgeNumber++)"
}
let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: nil)
alertController.addAction(yesAction)
alertController.addAction(cancelAction)
presentViewController(alertController, animated: true, completion: nil)
}
I need the selection of "Yes" on the alert to increment a badge on a Tab Bar Item every time it is pressed, has anyone had this problem?
let yesAction = UIAlertAction(title: "Yes", style: .Default) { action in
// Your code to update the tab bar here
}
Alternative:
UIAlertAction(title: "Yes",
style: UIAlertActionStyle.Default,
handler: { // Code goes here
})