UIInputViewController NSAutoresizingMaskLayoutConstraint问题

时间:2016-11-03 09:00:08

标签: ios swift constraints inputaccessoryview uiinputviewcontroller

我一直在尝试在我的应用中实现输入附件VC,我遇到了以下问题。当我试图修改自定义UIInputViewController的根视图的高度时,尽管存在一个问题,但它仍然运行良好。问题是在日志中我看到以下内容:

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    <NSAutoresizingMaskLayoutConstraint:0x174490cc0 UIInputView:0x10a80bb80.(null) == 46.5>,    
    <NSAutoresizingMaskLayoutConstraint:0x17448cd50 UIInputView:0x10a80bb80.height == 76>,  
    <NSLayoutConstraint:0x17429b710 UIInputView:0x10a80bb80.top == UIInputSetHostView:0x10402e940.top>  
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x17429b710 UIInputView:0x10a80bb80.top == UIInputSetHostView:0x10402e940.top>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

我的自定义UIInputViewController的代码:

import UIKit
import RxSwift
import RxCocoa


@objc protocol InputViewControllerDelegate: NSObjectProtocol {
    func answerTextViewDidChange(_ textView: UITextView)
}

class InputViewController: UIInputViewController {
    fileprivate var closeButton: UIButton?
    private var separatorView: UIView?
    private var tipLabel: UILabel?
    private var answerTextView: ConstrainedTextView?

    private var buttonHeightConstraint: NSLayoutConstraint?
    private var separatorHeightConstraint: NSLayoutConstraint?
    private var answerTextViewBottomConstraint: NSLayoutConstraint?

    weak var delegate: InputViewControllerDelegate?

    private let junk = DisposeBag()

    private var appropriateMaxLines: Int {
        let isPortrait = UIDevice.current.orientation.isPortrait
        return isPortrait ? 5 : 3
    }

    var answerText: String {
        get {
            return answerTextView?.text ?? ""
        }

        set {
            answerTextView?.text = newValue
        }
    }

    var isAnswerTextViewFirstResponder: Bool {
        get {
            return answerTextView?.isFirstResponder ?? false
        }

        set {
            _ = newValue ? answerTextView?.becomeFirstResponder() : answerTextView?.resignFirstResponder()
        }
    }


    // MARK: - Life Cycle

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    override func loadView() {
        super.loadView()

        let notifName = Notification.Name.UIDeviceOrientationDidChange
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(rotated),
                                               name: notifName,
                                               object: nil)

        configureView()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        answerTextView?.maxLines = appropriateMaxLines
        setCloseButtonDisabledIfNeeded()
    }


    // MARK: - Layout

    private func configureView() {

        view.backgroundColor = RGB(0xF6F6F6)
        view.frame = CGRect(x: 0, y: 0, width: screenWidth, height: 70)
        view.autoresizingMask = [.flexibleWidth]


        // Separator

        separatorView = UIView()
        separatorView?.backgroundColor = UIColor.lightGray
        separatorView?.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(separatorView!)
        AutoLayoutEqualizeSuper(separatorView, .left, 0)
        AutoLayoutEqualizeSuper(separatorView, .right, 0)
        AutoLayoutEqualizeSuper(separatorView, .top, 0)
        separatorHeightConstraint = AutoLayoutSetAttribute(separatorView, .height, 1)


        // Close Button

        closeButton = UIButton(type: .system)
        closeButton?.setTitle("Hide", for: .normal)
        closeButton?.titleLabel?.font = UIFont.systemFont(ofSize: 17)
        closeButton?.translatesAutoresizingMaskIntoConstraints = false
        closeButton?.addTarget(self, action: #selector(dismissKeyboard), for: .touchUpInside)
        view.addSubview(closeButton!)
        AutoLayoutSetAttribute(closeButton, .width, 70)
        buttonHeightConstraint = AutoLayoutSetAttribute(closeButton, .height, 35)
        AutoLayoutEqualizeSuper(closeButton, .right, -5)
        view.addConstraint(NSLayoutConstraint(item: closeButton!, attribute: .top, relatedBy: .equal, toItem: separatorView, attribute: .bottom, multiplier: 1, constant: 0))


        // Tip Label

        tipLabel = UILabel()
        tipLabel?.textColor = UIColor.darkGray
        tipLabel?.text = "Your answer:"
        tipLabel?.font = UIFont.systemFont(ofSize: 17)
        tipLabel?.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(tipLabel!)
        AutoLayoutEqualizeSuper(tipLabel, .left, 5)
        AutoLayoutSetAttribute(tipLabel, .height, 35)
        view.addConstraint(NSLayoutConstraint(item: tipLabel!, attribute: .right, relatedBy: .equal, toItem: closeButton, attribute: .left, multiplier: 1, constant: 0))


        // Text View

        answerTextView = ConstrainedTextView()
        answerTextView?.backgroundColor = UIColor.white
        answerTextView?.delegate = self
        answerTextView?.scrollsToTop = false
        answerTextView?.showsVerticalScrollIndicator = false
        answerTextView?.font = REG_FONT(15)
        answerTextView?.translatesAutoresizingMaskIntoConstraints = false

        answerTextView?.layer.masksToBounds = true
        answerTextView?.layer.cornerRadius = 7

        answerTextView?.layer.borderColor = UIColor.lightGray.withAlphaComponent(0.7).cgColor
        answerTextView?.layer.borderWidth = 1

        view.addSubview(answerTextView!)
        AutoLayoutEqualizeSuper(answerTextView, .left, 5)
        AutoLayoutEqualizeSuper(answerTextView, .right, -5)
        answerTextViewBottomConstraint = AutoLayoutEqualizeSuper(answerTextView, .bottom, -5)

        answerTextView?
            .rx
            .observe(CGRect.self, "bounds")
            .distinctUntilChanged {
                $0?.height == $1?.height
            }
            .subscribe(onNext: { [unowned self] newBounds in
                if var newHeight = newBounds?.height,
                    let separatorHeight = self.separatorHeightConstraint?.constant,
                    let buttonHeight = self.buttonHeightConstraint?.constant,
                    let bottomSpace = self.answerTextViewBottomConstraint?.constant {

                    newHeight = newHeight < 35 ? 35 : newHeight

                    let generalHeight = newHeight + separatorHeight + buttonHeight + abs(bottomSpace)

                    var frame = self.view.frame
                    frame.size.height = generalHeight
                    self.view.frame = frame
                }
            })
            .addDisposableTo(junk)
    }


    // MARK: - Other methods

    fileprivate func setCloseButtonDisabledIfNeeded() {
        closeButton?.isEnabled = answerTextView?.isFirstResponder ?? false
    }

    func rotated() {
        answerTextView?.maxLines = appropriateMaxLines
    }
}


// MARK: - UITextViewDelegate Protocol Conformance

extension InputViewController: UITextViewDelegate {

    func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
        textView.inputAccessoryView = view
        return true
    }

    func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
        textView.inputAccessoryView = nil
        return true
    }

    func textViewDidBeginEditing(_ textView: UITextView) {
        setCloseButtonDisabledIfNeeded()
    }

    func textViewDidEndEditing(_ textView: UITextView) {
        setCloseButtonDisabledIfNeeded()
    }

    func textViewDidChange(_ textView: UITextView) {
        delegate?.answerTextViewDidChange(textView)
    }

}

0 个答案:

没有答案