How to Present iOS Uiactionsheet in Swift

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
}
}

Demo App

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



Leave a reply



Submit