【问题标题】:How do I present a View Controller with UIView, UIButton sub-classes?如何呈现带有 UIView、UIButton 子类的视图控制器?
【发布时间】:2020-10-06 22:41:35
【问题描述】:

所以我创建了这个 UIButton 子类。它是一个可重用的组件,可以添加到任何视图控制器中。我需要通过点击按钮来呈现一个警报视图控制器。所以基本上我需要找出按钮所在的视图控制器,以便我可以将视图控制器作为参数传递。

final class ProfileButton: UIButton {

let picker = UIImagePickerController()

lazy var shadowImageView: UIImageView = {
    let imageView = UIImageView()
    imageView.contentMode = .scaleAspectFill
    imageView.image = UIImage(named: "download")
    return imageView
}()

override public init(frame: CGRect) {
    super.init(frame: frame)
    setupSelf()
    self.addTarget(self, action: #selector(profileButtonTapped), for: .touchUpInside)
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
}
override public func layoutSubviews() {
    super.layoutSubviews()
    shadowImageView.layer.cornerRadius = self.frame.width/2.70
    shadowImageView.layer.masksToBounds = true
}

@objc func profileButtonTapped(){
    imageHandler(presenter: )
}

@objc func imageHandler(presenter: UIViewController!){
    let alertController = UIAlertController(title: "Profile Picture", message: "Please select your profile picture", preferredStyle: .alert)
    let okAction = UIAlertAction(title: "Photo Library", style: .default, handler: { (action: UIAlertAction!) in
        print("I am working")
    })
    let cameraAction = UIAlertAction(title: "Camera", style: .default, handler: { (action: UIAlertAction!) in
        print("I am working")
    })

    alertController.addAction(okAction)
    alertController.addAction(cameraAction)
    presenter.present(alertController, animated: true, completion: nil)
}

我实际上需要找出视图控制器,以便我可以将它传递给 imageHandler(presenter: UIViewController) 函数。

【问题讨论】:

  • 为什么不在视图控制器中使用addTarget(selector:)
  • 如果我有 20 个创建此对象的视图控制器。在每个视图控制器中添加目标是没有意义的。

标签: ios swift uiview uiviewcontroller uibutton


【解决方案1】:

您可以在UIButton 中添加对控制器的weak var 引用。更好的方法是在UIViewController 扩展和addTarget 中添加处理程序函数viewDidLoad 而不是UIButton 的init(frame:)。这是一个例子:

final class ProfileButton: UIButton {
    //Remove addTarget from init(frame:)
}

class ViewController: UIViewController {
    let profileButton = ProfileButton()
    override func viewDidLoad() {
        super.viewDidLoad()
        //...
        profileButton.addTarget(self, action: #selector(imageHandler), for: .touchUpInside)
    }
}

extension UIViewController {

    @objc func imageHandler() {
        let alertController = UIAlertController(title: "Profile Picture", message: "Please select your profile picture", preferredStyle: .alert)
        let okAction = UIAlertAction(title: "Photo Library", style: .default, handler: { (action: UIAlertAction!) in
            print("I am working")
        })
        let cameraAction = UIAlertAction(title: "Camera", style: .default, handler: { (action: UIAlertAction!) in
            print("I am working")
        })

        alertController.addAction(okAction)
        alertController.addAction(cameraAction)
        present(alertController, animated: true, completion: nil)
    }
}

【讨论】:

  • 我知道这种方法。但是 profileButton 子类应该是一个单独的实体,应该完成这项工作。所以不得不采取其他方式。
【解决方案2】:

在这种情况下,您可以使用此扩展程序获取顶级控制器

extension UIApplication {

    class func getTopMostViewController() -> UIViewController? {
        let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
        if var topController = keyWindow?.rootViewController {
            while let presentedViewController = topController.presentedViewController {
                topController = presentedViewController
            }
            return topController
        } else {
            return nil
        }
    }
}


@objc func imageHandler() {
        //...
        UIApplication.getTopMostViewController()?.present(alertController, animated: true, completion: nil)

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-28
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    • 2016-06-12
    • 2013-03-24
    • 1970-01-01
    相关资源
    最近更新 更多