How to present iOS UIActionSheet in Swift?
Your Approach is fine, but you can add UIActionSheet
with other way with ease.
You can add UIActionSheetDelegate
in UIViewController` like
class ViewController: UIViewController ,UIActionSheetDelegate
Set you method like,
@IBAction func downloadSheet(sender: AnyObject)
{
let actionSheet = UIActionSheet(title: "Choose Option", delegate: self, cancelButtonTitle: "Cancel", destructiveButtonTitle: nil, otherButtonTitles: "Save", "Delete")
actionSheet.showInView(self.view)
}
You can get your button index when it clicked like
func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int)
{
println("\(buttonIndex)")
switch (buttonIndex){
case 0:
println("Cancel")
case 1:
println("Save")
case 2:
println("Delete")
default:
println("Default")
//Some code here..
}
}
Update 1: for iOS8+
//Create the AlertController and add Its action like button in Actionsheet
let actionSheetControllerIOS8: UIAlertController = UIAlertController(title: "Please select", message: "Option to select", preferredStyle: .ActionSheet)
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel) { _ in
print("Cancel")
}
actionSheetControllerIOS8.addAction(cancelActionButton)
let saveActionButton = UIAlertAction(title: "Save", style: .default)
{ _ in
print("Save")
}
actionSheetControllerIOS8.addAction(saveActionButton)
let deleteActionButton = UIAlertAction(title: "Delete", style: .default)
{ _ in
print("Delete")
}
actionSheetControllerIOS8.addAction(deleteActionButton)
self.present(actionSheetControllerIOS8, animated: true, completion: nil)
Swift: How to create UIActionSheet with click on button UITableVieCell
Try this and do some changes in UserTableViewCell
class UserTableViewCell: UITableViewCell {
weak var myVC : UIViewController?
@IBAction func btnMenu(_ sender: UIButton) {
//here I want to execute the UIActionSheet
let actionsheet = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
actionsheet.addAction(UIAlertAction(title: "Take a Photo", style: UIAlertActionStyle.default, handler: { (action) -> Void in
}))
actionsheet.addAction(UIAlertAction(title: "Choose Exisiting Photo", style: UIAlertActionStyle.default, handler: { (action) -> Void in
}))
actionsheet.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: { (action) -> Void in
}))
myVC?.present(actionsheet, animated: true, completion: nil)
}
}
And modify this method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "userCell", for: indexPath) as? UserTableViewCell;
cell?.view(with: users[indexPath.row]);
cell?.myVC = self
return cell!;
}
How to create a general method for multiple UIActionSheet in Swift
Solution 1:
If your AlertViewController
's actions will always have segue to perform you can significantly reduce duplication like below using struct and variadic parameters:
struct Option {
var name: String
var segueIdentifier: String
}
func configureActionSheet(options: Option...) {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheet.addAction(cancel)
for option in options {
let currentOption = UIAlertAction(title: option.name, style: .default) { action in
self.performSegue(withIdentifier: option.segueIdentifier, sender: self)
}
actionSheet.addAction(currentOption)
}
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad ){
actionSheet.popoverPresentationController?.sourceView = self.view
actionSheet.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
actionSheet.popoverPresentationController?.permittedArrowDirections = []
}
self.present(actionSheet, animated: true, completion: nil)
}
func showMenu1() {
let option1 = Option(name: "Option 1", segueIdentifier: "optionOne")
let option2 = Option(name: "Option 2", segueIdentifier: "optionTwo")
self.configureActionSheet(options: option1, option2)
}
Solution 2:
If your AlertViewController
's action will always be different then there is not much you can do but still avoid duplication as follows:
func configureActionSheet() -> UIAlertController {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheet.addAction(cancel)
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad ){
actionSheet.popoverPresentationController?.sourceView = self.view
actionSheet.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
actionSheet.popoverPresentationController?.permittedArrowDirections = []
}
return actionSheet
}
func showFirstMenu() {
let optionOne = UIAlertAction(title: "Option 1", style: .default) { action in
self.performSegue(withIdentifier: "optionOne", sender: self)
}
let optionTwo = UIAlertAction(title: "Option 2", style: .default) { action in
self.performSegue(withIdentifier: "optionTwo", sender: self)
}
let actionSheet = configureActionSheet()
actionSheet.addAction(optionOne)
actionSheet.addAction(optionTwo)
self.present(actionSheet, animated: true, completion: nil)
}
How to present actionSheet in iPhone style on iPad on iOS13?
The desired behaviour is not possible since iOS 13.2 anymore.
UIActionSheet with swift
You never set the action sheet's delegate:
myActionSheet = UIActionSheet()
myActionSheet.delegate = self
Customised UIActionSheet
If you really want to do something like that you could give this a go. I can't guarantee it'll be approved by Apple and honestly, it's just not recommended from a UI and Apple HIG perspective.
Keep in mind UIActionSheet
has been deprecated and it's recommended to use UIAlertController
with a preferredStyle
of .ActionSheet
so that's what this example is going to use.
import UIKit
class ViewController: UIViewController {
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let controller = SwiftDemoAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
controller.addAction(UIAlertAction(title: "Reset to default", style: .Destructive, handler: nil))
controller.addAction(UIAlertAction(title: "Save", style: .Default, handler: nil))
self.presentViewController(controller, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
class SwiftDemoAlertController: UIAlertController, UITableViewDataSource {
private var controller : UITableViewController
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
controller = UITableViewController(style: .Plain)
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
controller.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
controller.tableView.dataSource = self
controller.tableView.addObserver(self, forKeyPath: "contentSize", options: [.Initial, .New], context: nil)
self.setValue(controller, forKey: "contentViewController")
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
guard keyPath == "contentSize" else {
return
}
controller.preferredContentSize = controller.tableView.contentSize
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
controller.tableView.removeObserver(self, forKeyPath: "contentSize")
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell")!
switch(indexPath.row) {
case 0:
cell.textLabel?.text = "Upcoming activities"
let switchView = UISwitch(frame: CGRectZero)
cell.accessoryView = switchView
switchView.setOn(true, animated: false)
break
case 1:
cell.textLabel?.text = "Past activities"
let switchView = UISwitch(frame: CGRectZero)
cell.accessoryView = switchView
switchView.setOn(false, animated: false)
break
case 2:
cell.textLabel?.text = "Activities where I am admin"
let switchView = UISwitch(frame: CGRectZero)
cell.accessoryView = switchView
switchView.setOn(true, animated: false)
break
case 3:
cell.textLabel?.text = "Attending"
let switchView = UISwitch(frame: CGRectZero)
cell.accessoryView = switchView
switchView.setOn(true, animated: false)
break
case 4:
cell.textLabel?.text = "Declined"
let switchView = UISwitch(frame: CGRectZero)
cell.accessoryView = switchView
switchView.setOn(true, animated: false)
break
case 5:
cell.textLabel?.text = "Not responded"
let switchView = UISwitch(frame: CGRectZero)
cell.accessoryView = switchView
switchView.setOn(true, animated: false)
break
default:
fatalError()
}
return cell
}
}
How can I insert images next to text inside a UIActionSheet?
This isn't possible with a stock UIAlertController
/UIAlertAction
. You would need to create a custom view controller to get this functionality.
Related Topics
How to Set Image for Bar Button with Swift
How to Manually Deprecate Members
How to Present iOS Uiactionsheet in Swift
Adding Navigation Bar Programmatically iOS
Generate Random Numbers with a Given Distribution
Get Safe Area Inset Top and Bottom Heights
Secure Keys in iOS App Scenario, Is It Safe
Levenshtein Distance Algorithm Better Than O(N*M)
Swift - How to Remove a Decimal from a Float If the Decimal Is Equal to 0
What Does Error "Thread 1:Exc_Bad_Instruction (Code=Exc_I386_Invop, Subcode=0X0)" Mean
How to Style Uitextview to Like Rounded Rect Text Field
Instead of Push Segue How to Replace View Controller (Or Remove from Navigation Stack)
Realmswift: Convert Results to Swift Array
How to Create Custom Mkannotationview and Custom Annotation Title and Subtitle
Differencebetween a Property and a Variable in Swift
How to Determine Height of Uicollectionview with Flowlayout
How to Check If a File Exists in the Documents Directory in Swift