From 4adfe1489c4ed02d6d370892fdb138711dee40a5 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Wed, 18 Oct 2017 02:43:44 +0300 Subject: [PATCH 1/8] Update for setting date --- CHANGELOG.md | 5 +++++ Example/UIAnimatedTextField.xcodeproj/project.pbxproj | 8 +++++++- UIAnimatedTextField.podspec | 2 +- UIAnimatedTextField/Source/UIAnimatedTextField.swift | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..446cc81 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.2.0 + +- **Fix**: date setting after picker presented. \ No newline at end of file diff --git a/Example/UIAnimatedTextField.xcodeproj/project.pbxproj b/Example/UIAnimatedTextField.xcodeproj/project.pbxproj index edc96d0..3eaf972 100644 --- a/Example/UIAnimatedTextField.xcodeproj/project.pbxproj +++ b/Example/UIAnimatedTextField.xcodeproj/project.pbxproj @@ -173,9 +173,12 @@ files = ( ); inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-UIAnimatedTextField_Tests/Pods-UIAnimatedTextField_Tests-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/UIAnimatedTextField/UIAnimatedTextField.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/UIAnimatedTextField.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -203,13 +206,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-UIAnimatedTextField_Tests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ diff --git a/UIAnimatedTextField.podspec b/UIAnimatedTextField.podspec index 3b94d90..cfa5d4b 100644 --- a/UIAnimatedTextField.podspec +++ b/UIAnimatedTextField.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'UIAnimatedTextField' - s.version = '0.1.13' + s.version = '0.2.0' s.summary = 'UITextField with animated placeholder' s.description = <<-DESC This custom control can be used as a replacement for UITextField. It comes with 5 different text types: simple, password, url, tappable, date. diff --git a/UIAnimatedTextField/Source/UIAnimatedTextField.swift b/UIAnimatedTextField/Source/UIAnimatedTextField.swift index 814bd6f..ef1a775 100644 --- a/UIAnimatedTextField/Source/UIAnimatedTextField.swift +++ b/UIAnimatedTextField/Source/UIAnimatedTextField.swift @@ -418,7 +418,7 @@ open class UIAnimatedTextField: UIView { datePicker.timeZone = TimeZone(secondsFromGMT: 0) datePicker.datePickerMode = .date datePicker.backgroundColor = UIColor.white - datePicker.setDate(currentDate, animated: true) + datePicker.setDate(selectedDate ?? currentDate, animated: true) datePicker.maximumDate = currentDate datePicker.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: .valueChanged) From c5bf32e147cc5149b6203c36590ad28e6fb37c13 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Mon, 30 Oct 2017 10:23:59 +0300 Subject: [PATCH 2/8] Update to background color --- .../Source/UIAnimatedTextField.swift | 213 +++++++++--------- 1 file changed, 110 insertions(+), 103 deletions(-) diff --git a/UIAnimatedTextField/Source/UIAnimatedTextField.swift b/UIAnimatedTextField/Source/UIAnimatedTextField.swift index ef1a775..0efdcbd 100644 --- a/UIAnimatedTextField/Source/UIAnimatedTextField.swift +++ b/UIAnimatedTextField/Source/UIAnimatedTextField.swift @@ -25,7 +25,7 @@ import UIKit @objc public protocol UIAnimatedTextFieldDelegate: class { - + @objc optional func animatedTextFieldValueDidChange(_ animatedTextField: UIAnimatedTextField) @objc optional func animatedTextFieldWillReactForTap() @objc optional func animatedTextFieldShouldBeginEditing(_ animatedTextField: UIAnimatedTextField) -> Bool @@ -37,7 +37,7 @@ import UIKit replacementString string: String) -> Bool @objc optional func animatedTextFieldShouldClear(_ animatedTextField: UIAnimatedTextField) -> Bool @objc optional func animatedTextFieldShouldReturn(_ animatedTextField: UIAnimatedTextField) -> Bool - + } public enum AnimatedTextFieldState { @@ -55,28 +55,28 @@ public enum TextType { @IBDesignable open class UIAnimatedTextField: UIView { - + // MARK: - Constants struct Constants { static let done = "Done" static let space = " " static let defaultDateFormat = "dd/MM/yyyy" } - + // MARK: - Delegate - + weak public var delegate: UIAnimatedTextFieldDelegate? - + // MARK: - UI Properties - + private(set) public var textField: EditableTextField! private(set) public var placeholderLabel: UILabel! private(set) public var lineView: UIView! - + private var disclosureIndicatorImageView: UIImageView! - + // MARK: - @IBInspectable Properties - + @IBInspectable public var placeholder: String? { get { return placeholderLabel.text @@ -85,7 +85,7 @@ open class UIAnimatedTextField: UIView { placeholderLabel.text = newValue } } - + @IBInspectable public var isLeftTextAlignment: Bool { get { return textField.textAlignment == .left @@ -96,7 +96,7 @@ open class UIAnimatedTextField: UIView { placeholderLabel.textAlignment = alignment } } - + @IBInspectable public var placeholderTopColor: UIColor = UIColor.gray { didSet { setState(toState: state) @@ -107,19 +107,19 @@ open class UIAnimatedTextField: UIView { setState(toState: state) } } - + @IBInspectable public var enteredTextColor: UIColor { get { return textField.textColor ?? UIColor.black } set { textField.textColor = newValue } } - + @IBInspectable public var lineColor: UIColor { get { return lineView.backgroundColor ?? UIColor.gray } set { lineView.backgroundColor = newValue } } - + // MARK: - Public Properties - + public var text: String? { get { return textField.text @@ -140,7 +140,7 @@ open class UIAnimatedTextField: UIView { placeholderLabel.font = newValue } } - + public var isDisclosureIndicatorVisible: Bool = false { didSet { disclosureIndicatorImageView.isHidden = !isDisclosureIndicatorVisible @@ -156,15 +156,15 @@ open class UIAnimatedTextField: UIView { textField.autocapitalizationType = .words textField.inputView = nil textField.inputAccessoryView = nil - + tapAction = nil isDisclosureIndicatorVisible = false - + if let tapGestureRecognizer = tapGestureRecognizer { removeGestureRecognizer(tapGestureRecognizer) self.tapGestureRecognizer = nil } - + switch type { case .password: textField.isSecureTextEntry = true @@ -178,7 +178,7 @@ open class UIAnimatedTextField: UIView { tapAction = action textField.isUserInteractionEnabled = false isDisclosureIndicatorVisible = true - + tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapGestureRecognizerAction(_:))) if let tapGestureRecognizer = tapGestureRecognizer { addGestureRecognizer(tapGestureRecognizer) @@ -193,48 +193,55 @@ open class UIAnimatedTextField: UIView { } } } - + public dynamic var selectedDate: Date? public var dateFormat: String = Constants.defaultDateFormat + public var doneTitle: String = Constants.done { didSet { textField.inputAccessoryView = getDateInputAccessoryView() } } - + + public var doneTitleColor: UIColor = .black { + didSet { + textField.inputAccessoryView = getDateInputAccessoryView() + } + } + // MARK: - Static Properties - + static public let animationDuration: TimeInterval = 0.3 static public let disclosureIndicatorWidth = 15.0 - + // MARK: - Private Properties - + private var tapGestureRecognizer: UITapGestureRecognizer? private var tapAction: ((_ animatedTextField: UIAnimatedTextField) -> Void)? private var isShownInfo: Bool = false - + private var state: AnimatedTextFieldState { var state: AnimatedTextFieldState = .placeholder - + if textField.text?.characters.count ?? 0 > 0 || textField.isFirstResponder { state = .text } - + return state } - + // MARK: - Initialization - + override public init(frame: CGRect) { super.init(frame: frame) initialization() } - + required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) initialization() } - + private func initialization() { textField = EditableTextField() textField.delegate = self @@ -244,7 +251,7 @@ open class UIAnimatedTextField: UIView { return self?.type } addSubview(textField) - + placeholderLabel = UILabel() placeholderLabel.isUserInteractionEnabled = false placeholderLabel.textColor = placeholderBottomColor @@ -252,50 +259,50 @@ open class UIAnimatedTextField: UIView { placeholderLabel.adjustsFontSizeToFitWidth = true placeholderLabel.minimumScaleFactor = 0.5 addSubview(placeholderLabel) - + lineView = UIView() lineView.backgroundColor = placeholderLabel.textColor addSubview(lineView) - + disclosureIndicatorImageView = UIImageView() disclosureIndicatorImageView.image = UIImage(named: "disclosureIndicator") disclosureIndicatorImageView.contentMode = .center disclosureIndicatorImageView.isHidden = true addSubview(disclosureIndicatorImageView) - + layoutSubviews() } - + // MARK: - Layout - + private func textFieldFrame() -> CGRect { var size = bounds.size var origin = bounds.origin - + size.height = 2/3 * size.height origin.y = 1/3 * bounds.size.height - + if isDisclosureIndicatorVisible { origin.x += CGFloat(UIAnimatedTextField.disclosureIndicatorWidth) size.width -= CGFloat(UIAnimatedTextField.disclosureIndicatorWidth) * 2 } - + let textFieldBounds = CGRect(origin: origin, size: size) return textFieldBounds } - + private func placeholderLabelFrame(state: AnimatedTextFieldState) -> CGRect { if state == .placeholder { return textFieldFrame() } else { var size = bounds.size size.height = 1/3 * size.height - + let placeholderLabelBounds = CGRect(origin: bounds.origin, size: size) return placeholderLabelBounds } } - + private func disclosureIndicatorFrame() -> CGRect { let fieldFrame = textFieldFrame() let frame = CGRect(x: bounds.width - CGFloat(UIAnimatedTextField.disclosureIndicatorWidth), @@ -304,7 +311,7 @@ open class UIAnimatedTextField: UIView { height: fieldFrame.height) return frame } - + private func placeholderLabelTransform(state: AnimatedTextFieldState) -> CGAffineTransform { if state == .placeholder { return CGAffineTransform.identity @@ -312,26 +319,26 @@ open class UIAnimatedTextField: UIView { return CGAffineTransform(scaleX: 0.8, y: 0.8) } } - + override open func layoutSubviews() { super.layoutSubviews() - + textField.frame = textFieldFrame() - + if isDisclosureIndicatorVisible { disclosureIndicatorImageView.frame = disclosureIndicatorFrame() } - + setState(toState: state, duration: 0) - + lineView.frame = CGRect(x: 0, y: bounds.height - UIView.onePixelInPoints * 2, width: bounds.width, height: UIView.onePixelInPoints) } - + // MARK: - Animation - + public func setState(toState state: AnimatedTextFieldState, duration: TimeInterval = 0) { UIView.animate( withDuration: duration, @@ -354,50 +361,50 @@ open class UIAnimatedTextField: UIView { }, completion: nil) } - + // MARK: - Actions - + @objc private func tapGestureRecognizerAction(_ sender: UITapGestureRecognizer) { delegate?.animatedTextFieldWillReactForTap?() tapAction?(self) } - + open func validateText() -> Bool { guard let text = textField.text else { return false } - + switch type { case .url: return text.isValidEmail default: break } - + return true } - + open func showInfo(infoText: String) { guard !isShownInfo else { return } - + isShownInfo = true - + let currentPlaceholder = placeholder - + UIView.transition(with: placeholderLabel, duration: 0.5, options: .transitionFlipFromTop, animations: { [weak self] in self?.placeholder = infoText }, completion: nil) - + DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) { [weak self] in guard let placeholderLabel = self?.placeholderLabel else { return } - + UIView.transition(with: placeholderLabel, duration: 0.5, options: .transitionFlipFromBottom, @@ -408,12 +415,12 @@ open class UIAnimatedTextField: UIView { }) } } - + // MARK: - Private - + private func getDateInputView() -> UIDatePicker { let currentDate = Date() - + let datePicker = UIDatePicker() datePicker.timeZone = TimeZone(secondsFromGMT: 0) datePicker.datePickerMode = .date @@ -421,33 +428,33 @@ open class UIAnimatedTextField: UIView { datePicker.setDate(selectedDate ?? currentDate, animated: true) datePicker.maximumDate = currentDate datePicker.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: .valueChanged) - + return datePicker } - + @objc private func datePickerValueChanged(_ datePicker: UIDatePicker) { updateText(from: datePicker) } - + private func getDateInputAccessoryView() -> UIView { let toolbar = UIToolbar() toolbar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 44) toolbar.autoresizingMask = [.flexibleWidth] toolbar.barTintColor = UIColor.white - + let spacerItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let doneItem = UIBarButtonItem(title: doneTitle, - style: .done, + style: .plain, target: self, action: #selector(datePickerDoneAction)) let attributes = [ - NSForegroundColorAttributeName: UIColor.black + NSForegroundColorAttributeName: doneTitleColor ] - + doneItem.setTitleTextAttributes(attributes, for: .normal) - - toolbar.items = [spacerItem, doneItem] - + + toolbar.setItems([spacerItem, doneItem], animated: false) + return toolbar } @@ -455,58 +462,58 @@ open class UIAnimatedTextField: UIView { selectedDate = datePicker.date text = datePicker.date.toString(withFormat: dateFormat) } - + @objc private func datePickerDoneAction() { if let datePicker = textField.inputView as? UIDatePicker { updateText(from: datePicker) } textField.resignFirstResponder() } - + @objc private func textFieldValueDidChange() { delegate?.animatedTextFieldValueDidChange?(self) } - + } // MARK: - Extension extension UIAnimatedTextField: UITextFieldDelegate { - + open func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { var result = true - + if let delegateResult = delegate?.animatedTextFieldShouldBeginEditing?(self) { result = delegateResult } - + return result } - + open func textFieldDidBeginEditing(_ textField: UITextField) { if textField.text?.characters.count ?? 0 == 0 { setState(toState: .text, duration: UIAnimatedTextField.animationDuration) } - + if case .date = type { if let datePicker = textField.inputView as? UIDatePicker { textField.text = datePicker.date.toString(withFormat: dateFormat) } } - + delegate?.animatedTextFieldDidBeginEditing?(self) } - + open func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { var result = true - + if let delegateResult = delegate?.animatedTextFieldShouldEndEditing?(self) { result = delegateResult } - + return result } - + open func textFieldDidEndEditing(_ textField: UITextField) { if textField.text?.characters.count ?? 0 == 0 { setState(toState: .placeholder, duration: UIAnimatedTextField.animationDuration) @@ -518,21 +525,21 @@ extension UIAnimatedTextField: UITextFieldDelegate { delegate?.animatedTextFieldDidEndEditing?(self) } - + open func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, - replacementString string: String) -> Bool { + replacementString string: String) -> Bool { var result = true - + if let delegateResult = delegate?.animatedTextField?(self, shouldChangeCharactersInRange: range, replacementString: string) { result = delegateResult } - + if string == Constants.space { if textField.text?.isEmpty ?? true { result = false } - + switch type { case .password, .url: result = false @@ -540,28 +547,28 @@ extension UIAnimatedTextField: UITextFieldDelegate { break } } - + return result } - + open func textFieldShouldClear(_ textField: UITextField) -> Bool { var result = true - + if let delegateResult = delegate?.animatedTextFieldShouldClear?(self) { result = delegateResult } - + return result } - + open func textFieldShouldReturn(_ textField: UITextField) -> Bool { var result = true - + if let delegateResult = delegate?.animatedTextFieldShouldReturn?(self) { result = delegateResult } - + return result } - + } From 7a0d673396f0c7aa570a1cd4bc979efedcba6c73 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Mon, 30 Oct 2017 10:27:46 +0300 Subject: [PATCH 3/8] Fix done title --- UIAnimatedTextField/Source/UIAnimatedTextField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UIAnimatedTextField/Source/UIAnimatedTextField.swift b/UIAnimatedTextField/Source/UIAnimatedTextField.swift index 0efdcbd..1d4562b 100644 --- a/UIAnimatedTextField/Source/UIAnimatedTextField.swift +++ b/UIAnimatedTextField/Source/UIAnimatedTextField.swift @@ -444,7 +444,7 @@ open class UIAnimatedTextField: UIView { let spacerItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let doneItem = UIBarButtonItem(title: doneTitle, - style: .plain, + style: .done, target: self, action: #selector(datePickerDoneAction)) let attributes = [ From 7041eb4107eb6ccf6dc3682374c0d28f4218758b Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Sun, 12 Nov 2017 01:25:06 +0300 Subject: [PATCH 4/8] Update - fix swift 4 warnings - add posibility to disable actions - add functionality to disable moving cursor --- .../Source/EditableTextField.swift | 61 ++++++++++++++++++- .../Source/UIAnimatedTextField.swift | 6 +- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/UIAnimatedTextField/Source/EditableTextField.swift b/UIAnimatedTextField/Source/EditableTextField.swift index c57c0ce..41fb7ef 100644 --- a/UIAnimatedTextField/Source/EditableTextField.swift +++ b/UIAnimatedTextField/Source/EditableTextField.swift @@ -24,10 +24,33 @@ import Foundation +enum EditableActionType { + case selectAll + case select + case cut + case copy + case paste + + static let allActions = [EditableActionType.selectAll, .select, .cut, .paste, .copy] +} + public class EditableTextField: UITextField { - + + /// Actions, that will be disabled for this textField. + /// By default no actions are disabled. + var disabledActions: [EditableActionType] = [] + + /// Allows to disable moving cursor for user + var pinCursorToEnd: Bool = false + var getType: (() -> TextType?)? - + + // MARK: - Private + + private var disabledSelectors: [Selector] { + return disabledActions.map { selector(from: $0) } + } + private let menuSelectors = [ #selector(selectAll(_:)), #selector(select(_:)), @@ -35,8 +58,14 @@ public class EditableTextField: UITextField { #selector(copy(_:)), #selector(paste(_:)) ] + + // MARK: - Overriden override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { + if disabledSelectors.contains(action) { + return false + } + guard let type = getType?() else { return super.canPerformAction(action, withSender: sender) } @@ -61,5 +90,33 @@ public class EditableTextField: UITextField { return super.caretRect(for: position) } + + override public func closestPosition(to point: CGPoint) -> UITextPosition? { + if pinCursorToEnd { + return endOfDocument + } + + return super.closestPosition(to: point) + } } + +// MARK: - Private extensions + +private extension UITextField { + + func selector(from actionTyoe: EditableActionType) -> Selector { + switch actionTyoe { + case .selectAll: + return #selector(selectAll(_:)) + case .select: + return #selector(select(_:)) + case .cut: + return #selector(cut(_:)) + case .copy: + return #selector(copy(_:)) + case .paste: + return #selector(paste(_:)) + } + } +} diff --git a/UIAnimatedTextField/Source/UIAnimatedTextField.swift b/UIAnimatedTextField/Source/UIAnimatedTextField.swift index 1d4562b..be0b274 100644 --- a/UIAnimatedTextField/Source/UIAnimatedTextField.swift +++ b/UIAnimatedTextField/Source/UIAnimatedTextField.swift @@ -223,7 +223,7 @@ open class UIAnimatedTextField: UIView { private var state: AnimatedTextFieldState { var state: AnimatedTextFieldState = .placeholder - if textField.text?.characters.count ?? 0 > 0 || textField.isFirstResponder { + if textField.text?.count ?? 0 > 0 || textField.isFirstResponder { state = .text } @@ -491,7 +491,7 @@ extension UIAnimatedTextField: UITextFieldDelegate { } open func textFieldDidBeginEditing(_ textField: UITextField) { - if textField.text?.characters.count ?? 0 == 0 { + if textField.text?.count ?? 0 == 0 { setState(toState: .text, duration: UIAnimatedTextField.animationDuration) } @@ -515,7 +515,7 @@ extension UIAnimatedTextField: UITextFieldDelegate { } open func textFieldDidEndEditing(_ textField: UITextField) { - if textField.text?.characters.count ?? 0 == 0 { + if textField.text?.count ?? 0 == 0 { setState(toState: .placeholder, duration: UIAnimatedTextField.animationDuration) } From 17ddd2c3b79cbf259ceb564252b967a9e022d1d5 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Sun, 12 Nov 2017 01:30:41 +0300 Subject: [PATCH 5/8] Fix access level --- .../Source/EditableTextField.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/UIAnimatedTextField/Source/EditableTextField.swift b/UIAnimatedTextField/Source/EditableTextField.swift index 41fb7ef..a6d3787 100644 --- a/UIAnimatedTextField/Source/EditableTextField.swift +++ b/UIAnimatedTextField/Source/EditableTextField.swift @@ -24,26 +24,26 @@ import Foundation -enum EditableActionType { +public enum EditableActionType { case selectAll case select case cut case copy case paste - static let allActions = [EditableActionType.selectAll, .select, .cut, .paste, .copy] + public static let allActions = [EditableActionType.selectAll, .select, .cut, .paste, .copy] } -public class EditableTextField: UITextField { +open class EditableTextField: UITextField { /// Actions, that will be disabled for this textField. /// By default no actions are disabled. - var disabledActions: [EditableActionType] = [] + open var disabledActions: [EditableActionType] = [] /// Allows to disable moving cursor for user - var pinCursorToEnd: Bool = false + open var pinCursorToEnd: Bool = false - var getType: (() -> TextType?)? + open var getType: (() -> TextType?)? // MARK: - Private @@ -61,7 +61,7 @@ public class EditableTextField: UITextField { // MARK: - Overriden - override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { + override open func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { if disabledSelectors.contains(action) { return false } @@ -79,7 +79,7 @@ public class EditableTextField: UITextField { return super.canPerformAction(action, withSender: sender) } - override public func caretRect(for position: UITextPosition) -> CGRect { + override open func caretRect(for position: UITextPosition) -> CGRect { guard let type = getType?() else { return super.caretRect(for: position) } @@ -91,7 +91,7 @@ public class EditableTextField: UITextField { return super.caretRect(for: position) } - override public func closestPosition(to point: CGPoint) -> UITextPosition? { + override open func closestPosition(to point: CGPoint) -> UITextPosition? { if pinCursorToEnd { return endOfDocument } From 9dea74461e7f5630c858b9001705f279bd088c07 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Sat, 18 Nov 2017 19:54:14 +0300 Subject: [PATCH 6/8] Update for swift 4 --- .../project.pbxproj | 22 +++++++++++++++---- .../UIAnimatedTextField-Example.xcscheme | 4 +++- .../Source/UIAnimatedTextField.swift | 4 ++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Example/UIAnimatedTextField.xcodeproj/project.pbxproj b/Example/UIAnimatedTextField.xcodeproj/project.pbxproj index 3eaf972..aa9d180 100644 --- a/Example/UIAnimatedTextField.xcodeproj/project.pbxproj +++ b/Example/UIAnimatedTextField.xcodeproj/project.pbxproj @@ -128,12 +128,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0820; + LastUpgradeCheck = 0910; ORGANIZATIONNAME = CocoaPods; TargetAttributes = { 607FACE41AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; - LastSwiftMigration = 0820; + LastSwiftMigration = 0910; TestTargetID = 607FACCF1AFB9204008FA782; }; }; @@ -240,14 +240,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -287,14 +293,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -332,7 +344,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -345,7 +358,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Release; }; diff --git a/Example/UIAnimatedTextField.xcodeproj/xcshareddata/xcschemes/UIAnimatedTextField-Example.xcscheme b/Example/UIAnimatedTextField.xcodeproj/xcshareddata/xcschemes/UIAnimatedTextField-Example.xcscheme index 42ae55d..6fcae08 100644 --- a/Example/UIAnimatedTextField.xcodeproj/xcshareddata/xcschemes/UIAnimatedTextField-Example.xcscheme +++ b/Example/UIAnimatedTextField.xcodeproj/xcshareddata/xcschemes/UIAnimatedTextField-Example.xcscheme @@ -1,6 +1,6 @@ Date: Mon, 20 Nov 2017 17:48:55 +0300 Subject: [PATCH 7/8] Fix bug with animation --- UIAnimatedTextField/Source/UIAnimatedTextField.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/UIAnimatedTextField/Source/UIAnimatedTextField.swift b/UIAnimatedTextField/Source/UIAnimatedTextField.swift index 1b0bb31..e0e3fa8 100644 --- a/UIAnimatedTextField/Source/UIAnimatedTextField.swift +++ b/UIAnimatedTextField/Source/UIAnimatedTextField.swift @@ -349,8 +349,13 @@ open class UIAnimatedTextField: UIView { return } - strongSelf.placeholderLabel.transform = strongSelf.placeholderLabelTransform(state: state) - strongSelf.placeholderLabel.frame = strongSelf.placeholderLabelFrame(state: state) + if strongSelf.isLeftTextAlignment { + strongSelf.placeholderLabel.transform = strongSelf.placeholderLabelTransform(state: state) + strongSelf.placeholderLabel.frame = strongSelf.placeholderLabelFrame(state: state) + } else { + strongSelf.placeholderLabel.frame = strongSelf.placeholderLabelFrame(state: state) + strongSelf.placeholderLabel.transform = strongSelf.placeholderLabelTransform(state: state) + } switch state { case .placeholder: From cf9b3a72c5215eb862b67e5d1dffa094458b2cc9 Mon Sep 17 00:00:00 2001 From: Igor Kislyuk Date: Mon, 4 Dec 2017 11:42:52 +0300 Subject: [PATCH 8/8] PR fix --- UIAnimatedTextField/Source/EditableTextField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UIAnimatedTextField/Source/EditableTextField.swift b/UIAnimatedTextField/Source/EditableTextField.swift index a6d3787..831547d 100644 --- a/UIAnimatedTextField/Source/EditableTextField.swift +++ b/UIAnimatedTextField/Source/EditableTextField.swift @@ -31,7 +31,7 @@ public enum EditableActionType { case copy case paste - public static let allActions = [EditableActionType.selectAll, .select, .cut, .paste, .copy] + public static let allActions: [EditableActionType] = [.selectAll, .select, .cut, .paste, .copy] } open class EditableTextField: UITextField {