自定义 UIView 类中的 UIButton 不起作用



我知道这个问题已经被问了很多次,但没有一个解决方案对我有用。

我有一个自定义 UIView 类,用于显示警报消息。我添加了UIButton来关闭视图。但是,当我选择它时,没有任何反应。

import UIKit
public class Alert: UIView {
    public var image: UIImage?
public var title: String?
public var message: String?
public var closeButtonText: String?
public var dialogBackgroundColor: UIColor = .white
public var dialogTitleTextColor: UIColor = .black
public var dialogMessageTextColor: UIColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1)
public var dialogImageColor: UIColor = UIColor(red:0.47, green:0.72, blue:0.35, alpha:1.0)
public var overlayColor: UIColor = .black
public var overlayOpacity: CGFloat = 0.66
public var paddingSingleTextOnly: CGFloat = 8
public var paddingTopAndBottom: CGFloat = 24
public var paddingFromSides: CGFloat = 8
public var seperatorHeight: CGFloat = 6
private var height: CGFloat = 0
private var width: CGFloat = 0
private var maxSize: CGSize = CGSize()
private let marginFromSides: CGFloat = 80
public lazy var imageSize: CGSize = CGSize(width: 75, height: 75)
public var overlay = false
public var blurOverlay = true
//animation duration
public var duration = 0.33
private var onComplete: (() ->  Void)?
@objc public var titleFont: UIFont =  UIFont.systemFont(ofSize: 18)
@objc public var messageFont: UIFont = UIFont.systemFont(ofSize: 15)

private lazy var backgroundView: UIView = {
    let view = UIView()
    view.alpha = 0
    return view
}()
public let dialogView: UIView = {
    let view = UIView()
    view.layer.cornerRadius = 6
    view.layer.masksToBounds = true
    view.alpha = 0
    view.clipsToBounds = true
    return view
}()
private lazy var imageView: UIImageView = {
    let view = UIImageView()
    view.contentMode = .scaleAspectFit
    return view
}()
public lazy var closeButton: UIButton = {
    let button = UIButton()
    return button
}()
private lazy var titleLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 0
    label.textAlignment = .center
    return label
}()
private lazy var messageLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 0
    label.textAlignment = .center
    return label
}()
@objc func closeButtonTapped(sender: UIButton){
    dismiss()
}
private func calculations() {
    height += paddingTopAndBottom
    maxSize = CGSize(width: frame.width - marginFromSides * 2, height: frame.height - marginFromSides)
}
public convenience init(title:String, message: String, image:UIImage) {
    self.init(frame: UIScreen.main.bounds)
    self.title = title
    self.message = message
    self.image = image
}
public convenience init(title:String, image:UIImage) {
    self.init(frame: UIScreen.main.bounds)
    self.title = title
    self.image = image
}
public convenience init(title: String, message: String) {
    self.init(frame: UIScreen.main.bounds)
    self.title = title
    self.message = message
}
public convenience init(message: String) {
    self.init(frame: UIScreen.main.bounds)
    paddingTopAndBottom = paddingSingleTextOnly
    paddingFromSides = paddingSingleTextOnly * 2
    self.message = message
}
override init(frame: CGRect) {
    super.init(frame: frame)
}
public required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
private func createOverlay() {
    backgroundView.frame = frame
    backgroundView.backgroundColor = overlayColor
    backgroundView.isUserInteractionEnabled = true
    addSubview(backgroundView)
    if let window = UIApplication.shared.keyWindow {
        window.addSubview(backgroundView)
    } else if let window = UIApplication.shared.delegate?.window??.rootViewController {
        window.view.addSubview(self)
    }
}
private func createBlurOverlay() {
    backgroundView.frame = frame
    //Blur Effect
    let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame = frame
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    backgroundView.addSubview(blurEffectView)
    addSubview(backgroundView)
    if let window = UIApplication.shared.keyWindow {
        window.addSubview(backgroundView)
    } else if let window = UIApplication.shared.delegate?.window??.rootViewController {
        window.view.addSubview(self)
    }
}
private func createTitle(title: String) {
    titleLabel.font = titleFont
    titleLabel.text = title
    titleLabel.frame.origin.y = height + 2
    let titleLabelSize = titleLabel.sizeThatFits(maxSize)
    handleSize(size: titleLabelSize)
    titleLabel.frame.size = titleLabelSize
    titleLabel.textColor = self.dialogTitleTextColor
    dialogView.addSubview(titleLabel)
}
private func createMessage(message: String) {
    messageLabel.font = messageFont
    messageLabel.text = message
    messageLabel.frame.origin.y = height
    let messageLabelSize = messageLabel.sizeThatFits(maxSize)
    messageLabel.frame.size = messageLabelSize
    messageLabel.textColor = self.dialogMessageTextColor
    handleSize(size: messageLabelSize)
    dialogView.addSubview(messageLabel)
}

private func createImage(image: UIImage) {
    imageView.image = image.withRenderingMode(.alwaysTemplate)
    imageView.frame.origin.y = height
    imageView.frame.size = imageSize
    imageView.tintColor = self.dialogImageColor
    handleSize(size: imageSize)
    dialogView.addSubview(imageView)
}
private func createButton(){
    closeButton.setTitle("Close", for: .normal)
    closeButton.tintColor = UIColor.white
    closeButton.frame.origin.y = height + 20
    let closeButtonSize = CGSize(width: width - 60, height: 60)
    closeButton.frame.size = closeButtonSize
    closeButton.layer.cornerRadius = 6
    closeButton.backgroundColor = Color.NavigationBar.tintColor
    closeButton.isUserInteractionEnabled = true
    handleSize(size: closeButtonSize)
    dialogView.addSubview(closeButton)
}
private func createDialog() {
    centerAll()
    height += paddingTopAndBottom
    dialogView.frame.size = CGSize(width: width, height: height)
    dialogView.backgroundColor = self.dialogBackgroundColor
    dialogView.isUserInteractionEnabled = true
    addSubview(dialogView)
    self.dialogView.center = self.center
    self.dialogView.transform = CGAffineTransform(scaleX: 1.15, y: 1.15)
    if let window = UIApplication.shared.keyWindow {
        window.addSubview(dialogView)
        closeButton.addTarget(self, action: #selector(closeButtonTapped(sender:)), for: .touchUpInside)
    } else if let window = UIApplication.shared.delegate?.window??.rootViewController {
        UIApplication.topViewController()?.view.addSubview(self)
        window.view.addSubview(self)
        closeButton.addTarget(self, action: #selector(closeButtonTapped(sender:)), for: .touchUpInside)
    }
}
private func centerAll() {
    if ((messageLabel.text) != nil) {
        messageLabel.frame.origin.x = (width - messageLabel.frame.width) / 2
    }
    if ((titleLabel.text) != nil) {
        titleLabel.frame.origin.x = (width - titleLabel.frame.width) / 2
    }
    if ((imageView.image) != nil) {
        imageView.frame.origin.x = (width - imageView.frame.width) / 2
    }
    closeButton.frame.origin.x = (width - closeButton.frame.width) / 2
}
private func handleSize(size: CGSize) {
    if width < size.width + paddingFromSides * 2 {
        width = size.width + paddingFromSides * 2
    }
    if paddingTopAndBottom != paddingSingleTextOnly {
        height += seperatorHeight
    }
    height += size.height
}
private func showAnimation() {
    UIView.animate(withDuration: duration, animations: {
        if self.overlay {
            self.backgroundView.alpha = self.overlayOpacity
            self.dialogView.transform = CGAffineTransform(scaleX: 1, y: 1)
        }
        self.dialogView.alpha = 1
    })
}
public func show() {
    if let complete = onComplete {
        self.onComplete = complete
    }
    calculations()
    if self.overlay {
        if blurOverlay {
            createBlurOverlay()
        } else {
            createOverlay()
        }
    }
    if let img = image {
        createImage(image: img)
    }
    if let title = title {
        createTitle(title: title)
    }
    if let message = message {
        createMessage(message: message)
    }
    createButton()
    createDialog()
    showAnimation()
}
public func dismiss(){
    UIView.animate(withDuration: duration, animations: {
        if self.overlay {
            self.backgroundView.alpha = 0
        }
        self.dialogView.transform = CGAffineTransform(scaleX: 1.15, y: 1.15)
        self.dialogView.alpha = 0
    }, completion: { (completed) in
        self.dialogView.removeFromSuperview()
        if (self.overlay)
        {
            self.backgroundView.removeFromSuperview()
        }
        self.removeFromSuperview()
        if let completionHandler = self.onComplete {
            completionHandler()
        }
    })
}
}

我如何创建警报;

let alert = Alert(title: "hata",message: "hata mesajı ekrana basıldı", image: #imageLiteral(resourceName: "error"))
alert.show()

如果我在UIView控制器(我创建此UIView的位置(中声明目标为:

Alert.closeButton.addTarget(self, action: #selector(closeButtonTapped(sender:), for: .touchUPInside)

并在UIView控制器中创建函数它正在工作。我不知道为什么它在自定义类中不起作用。

所以我的问题是,当按钮选项卡时如何关闭警报视图?

尝试了以下解决方案,但对我不起作用;

自定义类中的 UIButton 目标操作

假设这些行位于函数内 - 例如由于按钮点击:

@IBAction func didTap(_ sender: Any) {
    let alert = Alert(title: "hata",message: "hata mesajı ekrana basıldı", image: #imageLiteral(resourceName: "error"))
    alert.show()
}

您正在创建 Alert 类的实例,在其中调用 .show() 函数,然后它就超出了范围。

因此,只要该函数存在,alert就不再存在,并且其中的任何代码都无法运行。

您需要有一个类级变量来在显示它时保留它:

class MyViewController: UIViewController {
    var alert: Alert?
    @IBAction func didTap(_ sender: Any) {
        alert = Alert(title: "hata",message: "hata mesajı ekrana basıldı", image: #imageLiteral(resourceName: "error"))
        alert?.show()
    }
}

以下是处理Alert观点的"错误方式"和"正确方式"的演示:https://github.com/DonMag/EmreTest

查看此代码

1-在UIView类中调用IBAction

import UIKit
public class Alert: UIView {
    public lazy var closeButton: UIButton = {
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        button.backgroundColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
        return button
    }()
    func createDialog() {
          closeButton.addTarget(self, action: #selector(self.closeButtonTapped(sender:)), for: .touchUpInside)
        self.addSubview(closeButton)
    }
    @objc func closeButtonTapped(sender: UIButton){
        print("Call   1")
    }
}
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let alert = Alert(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        alert.createDialog()
        self.view.addSubview(alert)
    }
}

2-在UIView控制器类中调用IBAction

import UIKit
public class Alert: UIView {
    public lazy var closeButton: UIButton = {
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        button.backgroundColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
        return button
    }()
    func createDialog() {
        //  closeButton.addTarget(self, action: #selector(self.closeButtonTapped(sender:)), for: .touchUpInside)
        self.addSubview(closeButton)
    }
    @objc func closeButtonTapped(sender: UIButton){
        print("Call   1")
    }
}
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let alert = Alert(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        alert.createDialog()
        alert.closeButton.addTarget(self, action: #selector(self.closeButtonTappedController(_:)), for: .touchUpInside)
        self.view.addSubview(alert)
    }
    @IBAction func closeButtonTappedController(_ sender:UIButton){
        print("Call   2")
    }
}

最新更新