代码拉取完成,页面将自动刷新
//
// IQKeyboardReturnKeyHandler.swift
// https://github.com/hackiftekhar/IQKeyboardManager
// Copyright (c) 2013-16 Iftekhar Qurashi.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
import UIKit
private class IQTextFieldViewInfoModal: NSObject {
fileprivate weak var textFieldDelegate: UITextFieldDelegate?
fileprivate weak var textViewDelegate: UITextViewDelegate?
fileprivate weak var textFieldView: UIView?
fileprivate var originalReturnKeyType = UIReturnKeyType.default
init(textFieldView: UIView?, textFieldDelegate: UITextFieldDelegate?, textViewDelegate: UITextViewDelegate?, originalReturnKeyType: UIReturnKeyType = .default) {
self.textFieldView = textFieldView
self.textFieldDelegate = textFieldDelegate
self.textViewDelegate = textViewDelegate
self.originalReturnKeyType = originalReturnKeyType
}
}
/**
Manages the return key to work like next/done in a view hierarchy.
*/
public class IQKeyboardReturnKeyHandler: NSObject, UITextFieldDelegate, UITextViewDelegate {
///---------------
/// MARK: Settings
///---------------
/**
Delegate of textField/textView.
*/
@objc public weak var delegate: (UITextFieldDelegate & UITextViewDelegate)?
/**
Set the last textfield return key type. Default is UIReturnKeyDefault.
*/
@objc public var lastTextFieldReturnKeyType: UIReturnKeyType = UIReturnKeyType.default {
didSet {
for modal in textFieldInfoCache {
if let view = modal.textFieldView {
updateReturnKeyTypeOnTextField(view)
}
}
}
}
///--------------------------------------
/// MARK: Initialization/Deinitialization
///--------------------------------------
@objc public override init() {
super.init()
}
/**
Add all the textFields available in UIViewController's view.
*/
@objc public init(controller: UIViewController) {
super.init()
addResponderFromView(controller.view)
}
deinit {
for modal in textFieldInfoCache {
if let textField = modal.textFieldView as? UITextField {
textField.returnKeyType = modal.originalReturnKeyType
textField.delegate = modal.textFieldDelegate
} else if let textView = modal.textFieldView as? UITextView {
textView.returnKeyType = modal.originalReturnKeyType
textView.delegate = modal.textViewDelegate
}
}
textFieldInfoCache.removeAll()
}
///------------------------
/// MARK: Private variables
///------------------------
private var textFieldInfoCache = [IQTextFieldViewInfoModal]()
///------------------------
/// MARK: Private Functions
///------------------------
private func textFieldViewCachedInfo(_ textField: UIView) -> IQTextFieldViewInfoModal? {
for modal in textFieldInfoCache {
if let view = modal.textFieldView {
if view == textField {
return modal
}
}
}
return nil
}
private func updateReturnKeyTypeOnTextField(_ view: UIView) {
var superConsideredView: UIView?
//If find any consider responderView in it's upper hierarchy then will get deepResponderView. (Bug ID: #347)
for disabledClass in IQKeyboardManager.shared.toolbarPreviousNextAllowedClasses {
superConsideredView = view.superviewOfClassType(disabledClass)
if superConsideredView != nil {
break
}
}
var textFields = [UIView]()
//If there is a tableView in view's hierarchy, then fetching all it's subview that responds.
if let unwrappedTableView = superConsideredView { // (Enhancement ID: #22)
textFields = unwrappedTableView.deepResponderViews()
} else { //Otherwise fetching all the siblings
textFields = view.responderSiblings()
//Sorting textFields according to behaviour
switch IQKeyboardManager.shared.toolbarManageBehaviour {
//If needs to sort it by tag
case .byTag: textFields = textFields.sortedArrayByTag()
//If needs to sort it by Position
case .byPosition: textFields = textFields.sortedArrayByPosition()
default: break
}
}
if let lastView = textFields.last {
if let textField = view as? UITextField {
//If it's the last textField in responder view, else next
textField.returnKeyType = (view == lastView) ? lastTextFieldReturnKeyType: UIReturnKeyType.next
} else if let textView = view as? UITextView {
//If it's the last textField in responder view, else next
textView.returnKeyType = (view == lastView) ? lastTextFieldReturnKeyType: UIReturnKeyType.next
}
}
}
///----------------------------------------------
/// MARK: Registering/Unregistering textFieldView
///----------------------------------------------
/**
Should pass UITextField/UITextView intance. Assign textFieldView delegate to self, change it's returnKeyType.
@param view UITextField/UITextView object to register.
*/
@objc public func addTextFieldView(_ view: UIView) {
let modal = IQTextFieldViewInfoModal(textFieldView: view, textFieldDelegate: nil, textViewDelegate: nil)
if let textField = view as? UITextField {
modal.originalReturnKeyType = textField.returnKeyType
modal.textFieldDelegate = textField.delegate
textField.delegate = self
} else if let textView = view as? UITextView {
modal.originalReturnKeyType = textView.returnKeyType
modal.textViewDelegate = textView.delegate
textView.delegate = self
}
textFieldInfoCache.append(modal)
}
/**
Should pass UITextField/UITextView intance. Restore it's textFieldView delegate and it's returnKeyType.
@param view UITextField/UITextView object to unregister.
*/
@objc public func removeTextFieldView(_ view: UIView) {
if let modal = textFieldViewCachedInfo(view) {
if let textField = view as? UITextField {
textField.returnKeyType = modal.originalReturnKeyType
textField.delegate = modal.textFieldDelegate
} else if let textView = view as? UITextView {
textView.returnKeyType = modal.originalReturnKeyType
textView.delegate = modal.textViewDelegate
}
if let index = textFieldInfoCache.firstIndex(where: { $0.textFieldView == view}) {
textFieldInfoCache.remove(at: index)
}
}
}
/**
Add all the UITextField/UITextView responderView's.
@param view UIView object to register all it's responder subviews.
*/
@objc public func addResponderFromView(_ view: UIView) {
let textFields = view.deepResponderViews()
for textField in textFields {
addTextFieldView(textField)
}
}
/**
Remove all the UITextField/UITextView responderView's.
@param view UIView object to unregister all it's responder subviews.
*/
@objc public func removeResponderFromView(_ view: UIView) {
let textFields = view.deepResponderViews()
for textField in textFields {
removeTextFieldView(textField)
}
}
@discardableResult private func goToNextResponderOrResign(_ view: UIView) -> Bool {
var superConsideredView: UIView?
//If find any consider responderView in it's upper hierarchy then will get deepResponderView. (Bug ID: #347)
for disabledClass in IQKeyboardManager.shared.toolbarPreviousNextAllowedClasses {
superConsideredView = view.superviewOfClassType(disabledClass)
if superConsideredView != nil {
break
}
}
var textFields = [UIView]()
//If there is a tableView in view's hierarchy, then fetching all it's subview that responds.
if let unwrappedTableView = superConsideredView { // (Enhancement ID: #22)
textFields = unwrappedTableView.deepResponderViews()
} else { //Otherwise fetching all the siblings
textFields = view.responderSiblings()
//Sorting textFields according to behaviour
switch IQKeyboardManager.shared.toolbarManageBehaviour {
//If needs to sort it by tag
case .byTag: textFields = textFields.sortedArrayByTag()
//If needs to sort it by Position
case .byPosition: textFields = textFields.sortedArrayByPosition()
default:
break
}
}
//Getting index of current textField.
if let index = textFields.firstIndex(of: view) {
//If it is not last textField. then it's next object becomeFirstResponder.
if index < (textFields.count - 1) {
let nextTextField = textFields[index+1]
nextTextField.becomeFirstResponder()
return false
} else {
view.resignFirstResponder()
return true
}
} else {
return true
}
}
///---------------------------------------
/// MARK: UITextField/UITextView delegates
///---------------------------------------
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(textField)?.textFieldDelegate {
if unwrapDelegate.responds(to: #selector(UITextFieldDelegate.textFieldShouldBeginEditing(_:))) {
return unwrapDelegate.textFieldShouldBeginEditing?(textField) == true
}
}
}
return true
}
@objc public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(textField)?.textFieldDelegate {
if unwrapDelegate.responds(to: #selector(UITextFieldDelegate.textFieldShouldEndEditing(_:))) {
return unwrapDelegate.textFieldShouldEndEditing?(textField) == true
}
}
}
return true
}
@objc public func textFieldDidBeginEditing(_ textField: UITextField) {
updateReturnKeyTypeOnTextField(textField)
var aDelegate: UITextFieldDelegate? = delegate
if aDelegate == nil {
if let modal = textFieldViewCachedInfo(textField) {
aDelegate = modal.textFieldDelegate
}
}
aDelegate?.textFieldDidBeginEditing?(textField)
}
@objc public func textFieldDidEndEditing(_ textField: UITextField) {
var aDelegate: UITextFieldDelegate? = delegate
if aDelegate == nil {
if let modal = textFieldViewCachedInfo(textField) {
aDelegate = modal.textFieldDelegate
}
}
aDelegate?.textFieldDidEndEditing?(textField)
}
#if swift(>=4.2)
@available(iOS 10.0, *)
@objc public func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
var aDelegate: UITextFieldDelegate? = delegate
if aDelegate == nil {
if let modal = textFieldViewCachedInfo(textField) {
aDelegate = modal.textFieldDelegate
}
}
aDelegate?.textFieldDidEndEditing?(textField, reason: reason)
}
#else
@available(iOS 10.0, *)
@objc public func textFieldDidEndEditing(_ textField: UITextField, reason: UITextFieldDidEndEditingReason) {
var aDelegate: UITextFieldDelegate? = delegate
if aDelegate == nil {
if let modal = textFieldViewCachedInfo(textField) {
aDelegate = modal.textFieldDelegate
}
}
aDelegate?.textFieldDidEndEditing?(textField, reason: reason)
}
#endif
@objc public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(textField)?.textFieldDelegate {
if unwrapDelegate.responds(to: #selector(UITextFieldDelegate.textField(_:shouldChangeCharactersIn:replacementString:))) {
return unwrapDelegate.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) == true
}
}
}
return true
}
@objc public func textFieldShouldClear(_ textField: UITextField) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(textField)?.textFieldDelegate {
if unwrapDelegate.responds(to: #selector(UITextFieldDelegate.textFieldShouldClear(_:))) {
return unwrapDelegate.textFieldShouldClear?(textField) == true
}
}
}
return true
}
@objc public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
var shouldReturn = true
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(textField)?.textFieldDelegate {
if unwrapDelegate.responds(to: #selector(UITextFieldDelegate.textFieldShouldReturn(_:))) {
shouldReturn = unwrapDelegate.textFieldShouldReturn?(textField) == true
}
}
}
if shouldReturn == true {
goToNextResponderOrResign(textField)
return true
} else {
return goToNextResponderOrResign(textField)
}
}
@objc public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(textView)?.textViewDelegate {
if unwrapDelegate.responds(to: #selector(UITextViewDelegate.textViewShouldBeginEditing(_:))) {
return unwrapDelegate.textViewShouldBeginEditing?(textView) == true
}
}
}
return true
}
@objc public func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(textView)?.textViewDelegate {
if unwrapDelegate.responds(to: #selector(UITextViewDelegate.textViewShouldEndEditing(_:))) {
return unwrapDelegate.textViewShouldEndEditing?(textView) == true
}
}
}
return true
}
@objc public func textViewDidBeginEditing(_ textView: UITextView) {
updateReturnKeyTypeOnTextField(textView)
var aDelegate: UITextViewDelegate? = delegate
if aDelegate == nil {
if let modal = textFieldViewCachedInfo(textView) {
aDelegate = modal.textViewDelegate
}
}
aDelegate?.textViewDidBeginEditing?(textView)
}
@objc public func textViewDidEndEditing(_ textView: UITextView) {
var aDelegate: UITextViewDelegate? = delegate
if aDelegate == nil {
if let modal = textFieldViewCachedInfo(textView) {
aDelegate = modal.textViewDelegate
}
}
aDelegate?.textViewDidEndEditing?(textView)
}
@objc public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
var shouldReturn = true
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(textView)?.textViewDelegate {
if unwrapDelegate.responds(to: #selector(UITextViewDelegate.textView(_:shouldChangeTextIn:replacementText:))) {
shouldReturn = (unwrapDelegate.textView?(textView, shouldChangeTextIn: range, replacementText: text)) == true
}
}
}
if shouldReturn == true && text == "\n" {
shouldReturn = goToNextResponderOrResign(textView)
}
return shouldReturn
}
@objc public func textViewDidChange(_ textView: UITextView) {
var aDelegate: UITextViewDelegate? = delegate
if aDelegate == nil {
if let modal = textFieldViewCachedInfo(textView) {
aDelegate = modal.textViewDelegate
}
}
aDelegate?.textViewDidChange?(textView)
}
@objc public func textViewDidChangeSelection(_ textView: UITextView) {
var aDelegate: UITextViewDelegate? = delegate
if aDelegate == nil {
if let modal = textFieldViewCachedInfo(textView) {
aDelegate = modal.textViewDelegate
}
}
aDelegate?.textViewDidChangeSelection?(textView)
}
@available(iOS 10.0, *)
@objc public func textView(_ aTextView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(aTextView)?.textViewDelegate {
if unwrapDelegate.responds(to: #selector(textView as (UITextView, URL, NSRange, UITextItemInteraction) -> Bool)) {
return unwrapDelegate.textView?(aTextView, shouldInteractWith: URL, in: characterRange, interaction: interaction) == true
}
}
}
return true
}
@available(iOS 10.0, *)
@objc public func textView(_ aTextView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(aTextView)?.textViewDelegate {
if unwrapDelegate.responds(to: #selector(textView as (UITextView, NSTextAttachment, NSRange, UITextItemInteraction) -> Bool)) {
return unwrapDelegate.textView?(aTextView, shouldInteractWith: textAttachment, in: characterRange, interaction: interaction) == true
}
}
}
return true
}
@available(iOS, deprecated: 10.0)
@objc public func textView(_ aTextView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(aTextView)?.textViewDelegate {
if unwrapDelegate.responds(to: #selector(textView as (UITextView, URL, NSRange) -> Bool)) {
return unwrapDelegate.textView?(aTextView, shouldInteractWith: URL, in: characterRange) == true
}
}
}
return true
}
@available(iOS, deprecated: 10.0)
@objc public func textView(_ aTextView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange) -> Bool {
if delegate == nil {
if let unwrapDelegate = textFieldViewCachedInfo(aTextView)?.textViewDelegate {
if unwrapDelegate.responds(to: #selector(textView as (UITextView, NSTextAttachment, NSRange) -> Bool)) {
return unwrapDelegate.textView?(aTextView, shouldInteractWith: textAttachment, in: characterRange) == true
}
}
}
return true
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。