Swift 如何创建可重用的UIAlert操作表作为UIViewController扩展?

Swift 如何创建可重用的UIAlert操作表作为UIViewController扩展?,swift,extension-methods,uialertcontroller,uiactionsheet,uialertaction,Swift,Extension Methods,Uialertcontroller,Uiactionsheet,Uialertaction,我想创建一个可以在代码中多次使用的操作表。为此,我需要能够根据操作表标题使用函数。是否有一种方法可以像“title”参数那样将函数作为参数数组传递 //MARK: - UIAlert action sheet title enum ActionSheetLabel: String { case camera = "Camera" case photoLibrary = "Album" case cancel = "Cancel" } class CameraHandler {

我想创建一个可以在代码中多次使用的操作表。为此,我需要能够根据操作表标题使用函数。是否有一种方法可以像“title”参数那样将函数作为参数数组传递

//MARK: - UIAlert action sheet title
enum ActionSheetLabel: String {
  case camera = "Camera"
  case photoLibrary = "Album"
  case cancel = "Cancel"
}



class CameraHandler {
static let cameraHandler = CameraHandler()
func openCamera() { }
func openPhotoLibrary() { }
}


//MARK: - Alert that shows an action sheet with cancel
extension UIViewController {
  func showActionSheetWithCancel(vc: UIViewController, title: [ActionSheetLabel] /*Make a function parameter here to match title*/) {
    let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

for value in title {
  actionSheet.addAction(UIAlertAction(title: value.rawValue, style: .default, handler: {
    (alert: UIAlertAction!) -> Void in

    //Use the parameter function here to match title

  }))
}

actionSheet.addAction(UIAlertAction(title: ActionSheetLabel.cancel.rawValue, style: .cancel, handler: nil))
vc.present(actionSheet, animated: true, completion: nil)
  }
}

您可以传递一个闭包,并在处理程序中调用它,类似这样的操作应该会起作用

也不确定为什么要传递
UIViewController
,因为您已经在
扩展UIViewController
中定义了函数,因此我允许我自己删除它并使用
self.present

extension UIViewController {
func showActionSheetWithCancel(title: [ActionSheetLabel], action: @escaping () -> ()?) {
    let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
    for value in title {
        actionSheet.addAction(UIAlertAction(title: value.rawValue, style: .default, handler: {
            (alert: UIAlertAction!) -> Void in
           // action
            action()

        }))
    }
    let alertAction = UIAlertAction(title: ActionSheetLabel.cancel.rawValue, style: .cancel) { (_) in
        action() // or for cancel call it here
    }
    actionSheet.addAction(alertAction)
    self.present(actionSheet, animated: true, completion: nil)


  }
}

如您所见,
@escaping()->()?
是可选的,因此您也可以传递
nil

对于UIAlert,您只需更改preferredStyle。对其发出警报,它就可以用于UIAlert,下面的代码只需复制并粘贴它即可用于UIActionSheet

 extension UIViewController {
       func popupAlert(title: String?, message: String?, actionTitles:[String?], actionStyle:[UIAlertAction.Style], actions:[((UIAlertAction) -> Void)?], vc: UIViewController) {
              let alert = UIAlertController(title: title, message: message, preferredStyle: .actionSheet)
              for (index, title) in actionTitles.enumerated() {
                   let action = UIAlertAction(title: title, style: actionStyle[index], handler: actions[index])
                   alert.addAction(action)
              }
              vc.present(alert, animated: true, completion: nil)
         }
    }
检查以下代码的用法

self.popupAlert(title: "Alert"), message: “Error in Loading”, actionTitles: ["Okey", "Email"], actionStyle: [.default, .default], actions: [nil,{ action in
         // I have set nil for first button click
         // do your code for second button click
 }], vc: self)

如果你有任何疑问,请评论我。谢谢

据我所知,当警报标题更改时,您需要调用特定的函数,并且您希望能够从不同的ViewController执行此操作, 我希望这会有所帮助

extension UIViewController {

 func showActionSheetWithCancel(vc: UIViewController, title: [ActionSheetLabel] ) {
            let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
            let cameraHandler = CameraHandler()
            for value in title {

                switch value.rawValue {
                case ActionSheetLabel.camera.rawValue:
                    actionSheet.addAction(UIAlertAction(title: ActionSheetLabel.camera.rawValue, style: .default, handler: { (alert) in
                        cameraHandler.openCamera()

                    }))
                case ActionSheetLabel.photoLibrary.rawValue:
                    actionSheet.addAction(UIAlertAction(title: ActionSheetLabel.photoLibrary.rawValue, style: .default, handler: { (alert) in

                        cameraHandler.openPhotoLibrary()

                    }))
                default:
                    actionSheet.addAction(UIAlertAction(title: ActionSheetLabel.cancel.rawValue, style: .cancel, handler: nil))

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

        }
}
函数的调用如下所示:

 showActionSheetWithCancel(vc: self, title: [UIViewController.ActionSheetLabel.camera])

我已经找到了最好的方法来添加一个行动表与取消和尽可能多的行动需要

使用类型别名创建UIViewController扩展:

//MARK: - Alert that shows an action sheet with cancel 
extension UIViewController {
  typealias AlertAction = () -> ()
  typealias AlertButtonAction = (ActionSheetLabel, AlertAction)

  func showActionSheetWithCancel(titleAndAction: [AlertButtonAction]) {
    let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

for value in titleAndAction {
  actionSheet.addAction(UIAlertAction(title: value.0.rawValue, style: .default, handler: {
  (alert: UIAlertAction!) -> Void in

    value.1()

}))
}
actionSheet.addAction(UIAlertAction(title: ActionSheetLabel.cancel.rawValue, style: .cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
  }
}
然后,在类或其他要使用该方法的地方,按以下方式添加该方法:

//MARK: - UIAlert action sheet title
enum ActionSheetLabel: String {
  case camera = "Camera"
  case photoLibrary = "Album"
  case cancel = "Cancel"
}

//MARK: - Class example where to use the action sheet action
class CameraHandler {

fileprivate let currentVC: UIViewController!

func openCamera() { 
// Open user camera
}
func openPhotoLibrary() { 
// Open user photo library
}

  // Method example of this action sheet
  func showActionSheetWithCameraAndLibrary(vc: UIViewController) {

    //This is the way to use the extension
    vc.showActionSheetWithCancel(titleAndAction: [
      (ActionSheetLabel.camera, { [weak self] in self?.openCamera() }),
      (ActionSheetLabel.photoLibrary, { [weak self] in self?.openPhotoLibrary() })
      ])
  }
}

嘿,你检查我的答案,如果这对你有帮助,那么请接受它。非常感谢。