为什么导航栏按钮项在textview已被resignedFirstResponder()时不起作用?

时间:2018-01-11 16:50:53

标签: ios core-data uitextview uibarbuttonitem first-responder

这是一个奇怪的。我有两个条形按钮项目,一个是取消,一个是完成。完成按钮将文本保存在coreData中的textview中,然后从navigationController弹出当前视图并转到上一个viewcontroller。取消按钮只是前一个控制器。当textview是firstResponder()或键盘启动时,整个过程都有效。当键盘作为第一个应答器退出时,两个按钮都不起作用。就像在不做任何事情一样。完成按钮不保存文本也不会将我带到以前的viewcontroller。

以下是两个按钮的代码:

完成按钮:

 @objc func handleDoneButton() {
    print("hello")
    if edittaskview.text.isEmpty == true
    {
        moContext.delete(editnotes!)
    }
    else
    {
        editnotes?.sNote = edittaskview.text
    }
    var error: NSError?
    do {
        // Save The object

        try moContext.save()
        print("SAVED")
    } catch let error1 as NSError {
        error = error1
    }

    _ = navigationController?.popViewController(animated: true)


}

取消按钮:

 @objc func handleCancelButton()
{
    _ = navigationController?.popViewController(animated: true)
}

同样,只有当textview是第一个响应者时才点击按钮,这两个功能中的代码都有效,否则他们就不会这样做。

ViewController代码:

import UIKit
import CoreData

 class editViewController: UIViewController, UICollectionViewDelegate, 
  UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, 
UITextViewDelegate, UIGestureRecognizerDelegate{
 var editnotes: addednotes?
var prioritynumber: Int = 1
let moContext = (UIApplication.shared.delegate as! 
AppDelegate).persistentContainer.viewContext
var colorArray = [prioritylevels]()
lazy var edittaskview: UITextView = {
    let textview = UITextView()
    textview.isScrollEnabled = false
    textview.font = UIFont.systemFont(ofSize: 16)
    textview.backgroundColor = .white
    textview.delegate = self

    return textview
}()
var clearview: UIView = {
   let view = UIView()
    view.backgroundColor = .clear
    //view.isUserInteractionEnabled = false
    return view
}()
let rightBarButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(handleDoneButton))
let leftBarButton = UIBarButtonItem(title: "Cancel", style: .done, target: self, action: #selector(handleCancelButton))

lazy var priorityCV: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    layout.minimumInteritemSpacing = 0
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.delegate = self
    cv.dataSource = self

    return cv
}()

let line: UIView = {
    let line = UIView()
    return line
}()

let reminderView: UIView = {
   let reminder = UIView()
    reminder.backgroundColor = .white
    return reminder
}()

let reminderTitle: UILabel = {
   let title = UILabel()
    title.text = "Due Date"
    title.textColor = .black
    title.font = UIFont(name: "Avenir Next", size: 16)
    title.font = UIFont.boldSystemFont(ofSize: 16)

    return title
}()
let reminderMsg: UILabel = {
    let title = UILabel()
    title.text = "No Due Date Set"
    title.textColor = .black
  //  title.font = UIFont(name: "Avenir Next", size: 12)
    title.font = UIFont.systemFont(ofSize: 12)

    return title
}()
let reminderAddBtn: UIButton = {
    let btn = UIButton(type: .system)
    btn.setTitle("Set", for: .normal)
    btn.setTitleColor(.black, for: .normal)
    btn.titleLabel?.font = UIFont.systemFont(ofSize: 14)
    btn.addTarget(self, action: #selector(handleSetReminderBtn), for: .touchUpInside)
    return btn
}()

var textHeightConstraint: NSLayoutConstraint?

override func viewWillAppear(_ animated: Bool) {
    adjustTextViewHeight()
}
 let datePicker: UIDatePicker = UIDatePicker()

override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = UIColor(red:0.97, green:0.97, blue:0.97, alpha:1.0)

    datePicker.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: .valueChanged)
    //ColorArray for PriorityCV
    colorArray = [prioritylevels(color: UIColor(red:0.00, green:0.78, blue:0.73, alpha:1.0), name: "   Low", prioritynumber: 1), prioritylevels(color: UIColor(red:0.00, green:0.78, blue:0.35, alpha:1.0), name: "Medium", prioritynumber: 2),prioritylevels(color: UIColor(red:0.88, green:0.63, blue:0.00, alpha:1.0), name: "  High", prioritynumber: 3), prioritylevels(color: UIColor(red:0.96, green:0.28, blue:0.70, alpha:1.0), name: "Urgent", prioritynumber: 4)]



    priorityCV.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cvid")

    navigationItem.title = "Edit Task"
    self.navigationItem.setHidesBackButton(true, animated: false)
    self.navigationController?.navigationBar.tintColor = UIColor.white
    navigationItem.rightBarButtonItem = rightBarButton
    navigationItem.leftBarButtonItem = leftBarButton
    view.addSubview(clearview)
    clearview.addSubview(line)
    clearview.addSubview(edittaskview)
    clearview.addSubview(priorityCV)
    clearview.addSubview(reminderView)
    reminderView.addSubview(reminderTitle)
    reminderView.addSubview(reminderMsg)
    reminderView.addSubview(reminderAddBtn)
    edittaskview.text = editnotes?.sNote
    edittaskview.becomeFirstResponder() //taskview becomes first responder here when the view is loaded. 
//        view.addSubview(datePicker)


    setupViews()
    line.backgroundColor = editnotes?.sPriorityColor

    let dismissbytap =  UITapGestureRecognizer()
    dismissbytap.addTarget(self, action: #selector(handleDismissByTap))
    dismissbytap.delegate = self
    clearview.addGestureRecognizer(dismissbytap) //a clear uiview is added behind all the subviews.  this uiview is used to dismiss keyboard when tapped on it.

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return colorArray.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell =  collectionView.dequeueReusableCell(withReuseIdentifier: "cvid", for: indexPath)
    cell.backgroundColor = colorArray[indexPath.row].color
    let prioritylabel = UILabel(frame: CGRect(x: view.frame.width / 20, y: 0, width: view.frame.width / 4, height: 30))

    cell.addSubview(prioritylabel)
    prioritylabel.text = colorArray[indexPath.row].name
    prioritylabel.textColor = .white
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: view.frame.width / 4, height: 30)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    prioritynumber = colorArray[indexPath.row].prioritynumber
    line.backgroundColor = colorArray[indexPath.row].color
    editnotes?.sPriorityColor = colorArray[indexPath.row].color
    editnotes?.sPriorityNumber = prioritynumber
    print(prioritynumber)
}
func setupViews()
{
   _ = edittaskview.anchor(line.bottomAnchor, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, topConstant: 2, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)
    self.edittaskview.contentInset = UIEdgeInsetsMake(2, 8, 4, 8)

    self.textHeightConstraint = edittaskview.heightAnchor.constraint(equalToConstant: 80)
    self.textHeightConstraint?.isActive = true
    self.adjustTextViewHeight()
    _ = clearview.anchor(view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)
  _ = priorityCV.anchor(edittaskview.bottomAnchor, left: clearview.leftAnchor, bottom: nil, right: clearview.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 30)
  _ = line.anchor(clearview.topAnchor, left: clearview.leftAnchor, bottom: nil, right: clearview.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 4)

  _ = reminderView.anchor(priorityCV.bottomAnchor, left: clearview.leftAnchor, bottom: nil, right: view.rightAnchor, topConstant: 30, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 60)
    _ = reminderTitle.anchor(reminderView.topAnchor, left: reminderView.leftAnchor, bottom: nil, right: nil, topConstant: 8, leftConstant: 8, bottomConstant: 0, rightConstant: 0, widthConstant: 100, heightConstant: 20)
    _ = reminderMsg.anchor(reminderTitle.bottomAnchor, left: reminderView.leftAnchor, bottom: nil, right: nil, topConstant: 4, leftConstant: 8, bottomConstant: 0, rightConstant: 0, widthConstant: 100, heightConstant: 24)
    _ = reminderAddBtn.anchor(reminderView.topAnchor, left: nil, bottom: nil, right: reminderView.rightAnchor, topConstant: 20, leftConstant: 0, bottomConstant: 20, rightConstant: 32, widthConstant: 30, heightConstant: 20)
}

@objc func handleDoneButton() {
    print("hello")

    if edittaskview.text.isEmpty == true
    {
        moContext.delete(editnotes!)
    }
    else
    {
        editnotes?.sNote = edittaskview.text
    }
    var error: NSError?
    do {
        // Save The object

        try moContext.save()
        print("SAVED")
    } catch let error1 as NSError {
        error = error1
    }

    _ = navigationController?.popViewController(animated: true)


}

func textViewDidChange(_ textView: UITextView) {
    self.adjustTextViewHeight()
}


func adjustTextViewHeight() {
    let fixedWidth = edittaskview.frame.size.width

    let newSize = edittaskview.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    self.textHeightConstraint?.constant = newSize.height + 15

    self.view.layoutIfNeeded()
}


@objc func handleCancelButton()
{
    _ = navigationController?.popViewController(animated: true)
}


@objc func datePickerValueChanged(_ sender: UIDatePicker) {
    let componenets = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: sender.date)
    if let day = componenets.day, let month = componenets.month, let year = componenets.year, let hour = componenets.hour, let minute = componenets.minute  {
        print("\(day) \(month) \(year) \(hour) \(minute)")
    }
}

@objc func handleDismissByTap() {
    edittaskview.resignFirstResponder() // Resigning textview as first responder


}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
   return touch.view == gestureRecognizer.view
}

3 个答案:

答案 0 :(得分:1)

我不知道怎么做,而不是单独创建条形按钮,然后分配它们self.navigationBarItem.leftbarbutton = leftBarbutton 我决定使用UIBarButtonItem构造函数构造它们。

self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .done, target: self, action: #selector(handleCancelButton))

有效!

说实话很奇怪。

答案 1 :(得分:0)

这看起来很奇怪 - 而且我不知道为什么导航栏按钮仅在文本视图处于活动状态时调用函数,但是......

解决此问题的一种方法是将您的左右UIBarButtonItem声明移至viewDidLoad()而不是班级。

另外,如果您将edittaskview.becomeFirstResponder()viewDidLoad()移至viewDidAppear(),您将获得更好的动画和键盘外观。

答案 2 :(得分:0)

您还可以做的就是将UIBarButtonItem的声明设为lazy var

该类正在实例化。如果将其设置为lazy var,则将在需要使用它时创建它。如果您想将其保留为let并且在课堂上使用,请执行以下操作:

override func viewDidLoad() {
    super.viewDidLoad()
    yourBarButtonItem.target = self
}

这两种方法都可以使目标保持完整。我遇到了同样的问题。

这仍然是一个奇怪的问题,我认为编译器应该对您大喊大叫,因为您尝试在初始化之前使用self。而是在您放self()时这样做。