我无法使用回调作为完成处理程序在 类 之间传递数据

I can't pass data between classes using callback as completion handler

我想将自定义 class 中的 textField 文本传递给 ViewController 并在点击 DatePicker 的 BarButtonItem 时将其填充到数组中。我使用回调作为完成处理程序,但它捕获了 EXC-BAD-ACCESS。是什么导致了这个错误,我如何将文本传递到我的 ViewController?

class HourDatePicker: UITextField {

    var datePicker =  UIDatePicker()

    override init(frame: CGRect) {
        super.init(frame: frame)
        commominit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commominit()
    }

    func commominit(){
        text = ""
        datePicker.datePickerMode = .dateAndTime
        datePicker.minuteInterval = 30
        datePicker.locale = Locale(identifier: "ja")
        datePicker.addTarget(self, action: #selector(setText), for: .valueChanged)
        setText()
        inputView = datePicker
        inputAccessoryView = customPicker()
     }

    @objc func setText(){
        let f = DateFormatter()
        f.dateStyle = .full
        f.timeStyle = .short
        f.locale = Locale(identifier: "ja")
        textColor = .black
        text = "\(f.string(from: datePicker.date))"

    }
    private func customPicker() -> UIToolbar {
        let toolbar = UIToolbar()
        toolbar.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: 40)
        let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
        space.width = 100
        let flexSpaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
        let todayButtonItem = UIBarButtonItem(title: "today", style: .done, target: self, action: #selector(setToday))
        let selectButtonItem = UIBarButtonItem(title: "select", style: .done, target: self, action: #selector(tellCalenderText))

        let toolbarItem = [space, flexSpaceItem, todayButtonItem, selectButtonItem]
         toolbar.setItems(toolbarItem, animated: true)
        }
        return toolbar
    }

    @objc func tellCalenderText(completion: ((_ titleText: String) -> Void)){
        //I want to pass text here.
        if text != "" {
        guard let titleText = text else {return}
        completion(titleText)
        } else {
            return
        }

    }
class Calender1ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    private let selectDate = HourDatePicker()
    private var keepDate: [String] = []

    @IBOutlet weak var timeTextView: UITextView!
    @IBOutlet weak var dateText: HourDatePicker!
    @IBOutlet weak var calenderTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.calenderTableView.delegate = self
        self.calenderTableView.dataSource = self

        selectDate.tellCalenderText {[weak self] (titleText) in
            self?.bringDate(title: titleText)
        }


    }

    func bringDate(title: String){

        print("title: \(title)")
        self.keepDate.append(title)
        timeTextView.text.append(contentsOf: "\(title)\n")

    }

谢谢。

这是错误日志。 error log

首先,我觉得你有点搞砸了:

private let selectDate = HourDatePicker()

有:

@IBOutlet weak var dateText: HourDatePicker!

然后在 viewDidLoad()...

中使用 selectDate

试一试。我只做了一些更改,并尝试包含足够的评论以使其清晰。我想你会发现这是一种更直接的方式来让你的自定义 HourDatePicker class 将信息传递回视图控制器:

class HourDatePicker: UITextField {

    var datePicker =  UIDatePicker()

    override init(frame: CGRect) {
        super.init(frame: frame)
        commominit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commominit()
    }

    func commominit(){
        text = ""
        datePicker.datePickerMode = .dateAndTime
        datePicker.minuteInterval = 30
        datePicker.locale = Locale(identifier: "ja")
        datePicker.addTarget(self, action: #selector(setText), for: .valueChanged)
        setText()
        inputView = datePicker
        inputAccessoryView = customPicker()
    }

    @objc func setToday(){
        datePicker.date = Date()
    }

    @objc func setText(){
        let f = DateFormatter()
        f.dateStyle = .full
        f.timeStyle = .short
        f.locale = Locale(identifier: "ja")
        textColor = .black
        text = "\(f.string(from: datePicker.date))"

    }
    private func customPicker() -> UIToolbar {
        let toolbar = UIToolbar()
        toolbar.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: 40)
        let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: self, action: nil)
        space.width = 100
        let flexSpaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
        let todayButtonItem = UIBarButtonItem(title: "today", style: .done, target: self, action: #selector(setToday))
        let selectButtonItem = UIBarButtonItem(title: "select", style: .done, target: self, action: #selector(tellCalenderText))

        let toolbarItem = [space, flexSpaceItem, todayButtonItem, selectButtonItem]
        toolbar.setItems(toolbarItem, animated: true)
        return toolbar
    }

    // "callback" closure
    var tellController: ((String) ->())?

    // triggered by "select" bar button tap
    @objc func tellCalenderText() -> Void {
        // get text from self
        guard let t = text else {
            return
        }
        // execute the callback closure
        tellController?(t)
    }

//  @objc func tellCalenderText(completion: ((_ titleText: String) -> Void)){
//      //I want to pass text here.
//      if text != "" {
//          guard let titleText = text else {return}
//          completion(titleText)
//      } else {
//          return
//      }
//
//  }
}

//ViewController
class Calender1ViewController: UIViewController {

    // not needed
    //private let selectDate = HourDatePicker()

    private var keepDate: [String] = []

    // UITextView connected via Storyboard
    @IBOutlet weak var timeTextView: UITextView!

    // UITextField set to HourDatePicker, connected via Storyboard
    @IBOutlet weak var dateText: HourDatePicker!

    @IBOutlet weak var calenderTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // set the callback closure for the HourDatePicker
        dateText.tellController = { [weak self] (titleText) in
            self?.bringDate(title: titleText)
        }

        // not needed
        //selectDate.tellCalenderText {[weak self] (titleText) in
        //  self?.bringDate(title: titleText)
        //}

    }

    func bringDate(title: String){

        print("title: \(title)")
        self.keepDate.append(title)
        timeTextView.text.append(contentsOf: "\(title)\n")

    }
}