【问题标题】:How to create a reusable UIAlert ActionSheet as an UIViewController extension?如何创建可重用的 UIAlert ActionSheet 作为 UIViewController 扩展?
【发布时间】:2019-06-13 10:47:06
【问题描述】:

我想创建一个可以在我的代码中多次使用的操作表。为此,我需要能够根据操作表标题使用功能。有没有办法像“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)
  }
}

【问题讨论】:

  • 嘿,如果这对您有帮助,请检查我的回答,然后请接受。谢谢

标签: swift extension-methods uialertcontroller uiactionsheet uialertaction


【解决方案1】:

对于 UIAlert,您只需要更改 preferredStyle .alert 即可,它适用于 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)

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

【讨论】:

    【解决方案2】:

    我找到了添加带有取消和尽可能多的操作的操作表的最佳方法。

    使用类型别名创建一个 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() })
          ])
      }
    }
    

    【讨论】:

      【解决方案3】:

      您可以传递一个闭包并在处理程序中调用它,这样应该可以工作。

      也不确定您为什么要传递 UIViewController ,因为您已经在 extension 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

      【讨论】:

        【解决方案4】:

        据我了解,当警报标题更改时,您需要调用特定函数,并且您希望能够从不同的视图控制器中调用, 我希望这会有所帮助

        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])
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-19
          • 2019-03-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多