From 81f36cc517887c137fc67984c58935e8d1944227 Mon Sep 17 00:00:00 2001 From: Arkadiusz Mlynarczyk Date: Tue, 6 Nov 2018 10:57:49 +0100 Subject: [PATCH 1/2] Fix a problem after using highlightAll text was not replaced correctly --- Source/AutocompleteTextField.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Source/AutocompleteTextField.swift b/Source/AutocompleteTextField.swift index 8ee5207..82e434a 100644 --- a/Source/AutocompleteTextField.swift +++ b/Source/AutocompleteTextField.swift @@ -27,6 +27,9 @@ open class AutocompleteTextField: UITextField, UITextFieldDelegate { // The last string used as a replacement in shouldChangeCharactersInRange. private var lastReplacement: String? + // Used as a state flag after highlighting all the text + private var isHighlightingAll: Bool = false + public init() { super.init(frame: CGRect.zero) addTarget(self, action: #selector(textDidChange), for: .editingChanged) @@ -109,6 +112,7 @@ open class AutocompleteTextField: UITextField, UITextFieldDelegate { self.text = nil setCompletion(text ?? "") selectedTextRange = textRange(from: beginningOfDocument, to: beginningOfDocument) + isHighlightingAll = true } private func applyCompletion() { @@ -127,7 +131,7 @@ open class AutocompleteTextField: UITextField, UITextFieldDelegate { } private func removeCompletion() { - guard let completionRange = completionRange else { return } + guard var completionRange = completionRange else { return } applyCompletion() @@ -135,6 +139,12 @@ open class AutocompleteTextField: UITextField, UITextFieldDelegate { // Prevents the hard crash when you select all and start a new query guard let count = text?.count, count > 1 else { return } + // Fixes the problem when after highlighting all, entire string is deleted instead of only old part + if isHighlightingAll { + completionRange.location += (count - completionRange.length) + isHighlightingAll = false + } + text = (text as NSString?)?.replacingCharacters(in: completionRange, with: "") } From 8f49441a6588f7d5ae6297697c127a45f24912aa Mon Sep 17 00:00:00 2001 From: Arkadiusz Mlynarczyk Date: Tue, 26 Mar 2019 13:39:23 +0100 Subject: [PATCH 2/2] Converted project to Swift 4.1 --- .../project.pbxproj | 22 +++++++++++++------ .../xcshareddata/IDEWorkspaceChecks.plist | 8 +++++++ Example/DomainCompletionSource.swift | 2 +- Source/AutocompleteTextField.swift | 4 ++-- Tests/AutocompleteTextFieldUITests.swift | 20 ++++++++--------- 5 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 AutocompleteTextField.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/AutocompleteTextField.xcodeproj/project.pbxproj b/AutocompleteTextField.xcodeproj/project.pbxproj index 327197e..2a12c57 100644 --- a/AutocompleteTextField.xcodeproj/project.pbxproj +++ b/AutocompleteTextField.xcodeproj/project.pbxproj @@ -233,17 +233,19 @@ D31083311EAA7BF500ECF778 = { CreatedOnToolsVersion = 8.2.1; DevelopmentTeam = 43AQ936H96; - LastSwiftMigration = 0820; + LastSwiftMigration = 0940; ProvisioningStyle = Automatic; }; D310834F1EAA7C3600ECF778 = { CreatedOnToolsVersion = 8.2.1; DevelopmentTeam = 43AQ936H96; + LastSwiftMigration = 0940; ProvisioningStyle = Automatic; }; D370686F1EAE68B2000D6BA7 = { CreatedOnToolsVersion = 8.2.1; DevelopmentTeam = 43AQ936H96; + LastSwiftMigration = 0940; ProvisioningStyle = Automatic; TestTargetID = D310834F1EAA7C3600ECF778; }; @@ -476,7 +478,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -497,7 +500,8 @@ PRODUCT_BUNDLE_IDENTIFIER = org.mozilla.ios.AutocompleteTextField; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -511,7 +515,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mozilla.ios.AutocompleteTextFieldExample; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -525,7 +530,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mozilla.ios.AutocompleteTextFieldExample; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -537,7 +543,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mozilla.ios.AutocompleteTextFieldUITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; TEST_TARGET_NAME = AutocompleteTextFieldExample; }; name = Debug; @@ -550,7 +557,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.mozilla.ios.AutocompleteTextFieldUITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; TEST_TARGET_NAME = AutocompleteTextFieldExample; }; name = Release; diff --git a/AutocompleteTextField.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/AutocompleteTextField.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/AutocompleteTextField.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example/DomainCompletionSource.swift b/Example/DomainCompletionSource.swift index eec34f9..020b0c0 100644 --- a/Example/DomainCompletionSource.swift +++ b/Example/DomainCompletionSource.swift @@ -28,7 +28,7 @@ class DomainCompletionSource: AutocompleteTextFieldCompletionSource { // We don't actually want to match the top-level domain ("com", "org", etc.) by itself, so // so make sure the result includes at least one ".". let range = domainWithDotPrefix.index(range.lowerBound, offsetBy: 1) - let matchedDomain: String = domainWithDotPrefix.substring(from: range) + let matchedDomain = String(domainWithDotPrefix[range...]) if matchedDomain.contains(".") { return matchedDomain + "/" } diff --git a/Source/AutocompleteTextField.swift b/Source/AutocompleteTextField.swift index 82e434a..2976645 100644 --- a/Source/AutocompleteTextField.swift +++ b/Source/AutocompleteTextField.swift @@ -155,10 +155,10 @@ open class AutocompleteTextField: UITextField, UITextFieldDelegate { guard !completion.isEmpty, completion.lowercased().hasPrefix(text.lowercased()) else { return } // Add the completion suffix to the current text and highlight it. - let completion = completion.substring(from: completion.index(completion.startIndex, offsetBy: text.characters.count)) + let completion = completion[completion.index(completion.startIndex, offsetBy: text.count)...] let attributed = NSMutableAttributedString(string: text + completion) let range = NSMakeRange((text as NSString).length, (completion as NSString).length) - attributed.addAttribute(NSBackgroundColorAttributeName, value: highlightColor, range: range) + attributed.addAttribute(NSAttributedStringKey.backgroundColor, value: highlightColor, range: range) attributedText = attributed completionRange = range } diff --git a/Tests/AutocompleteTextFieldUITests.swift b/Tests/AutocompleteTextFieldUITests.swift index c428c44..2cbbab4 100644 --- a/Tests/AutocompleteTextFieldUITests.swift +++ b/Tests/AutocompleteTextFieldUITests.swift @@ -22,26 +22,26 @@ class AutocompleteTextFieldUITests: XCTestCase { field.typeText("w") XCTAssertEqual(field.value! as! String, "www.google.com/") - field.typeText(XCUIKeyboardKeyDelete) + field.typeText(XCUIKeyboardKey.delete.rawValue) XCTAssertEqual(field.value! as! String, "w") field.typeText("ww.yah") XCTAssertEqual(field.value! as! String, "www.yahoo.com/") - field.typeText(XCUIKeyboardKeyDelete) + field.typeText(XCUIKeyboardKey.delete.rawValue) XCTAssertEqual(field.value! as! String, "www.yah") - field.typeText(XCUIKeyboardKeyDelete) + field.typeText(XCUIKeyboardKey.delete.rawValue) XCTAssertEqual(field.value! as! String, "www.ya") - field.typeText(XCUIKeyboardKeyDelete) - field.typeText(XCUIKeyboardKeyDelete) - field.typeText(XCUIKeyboardKeyDelete) - field.typeText(XCUIKeyboardKeyDelete) - field.typeText(XCUIKeyboardKeyDelete) - field.typeText(XCUIKeyboardKeyDelete) + field.typeText(XCUIKeyboardKey.delete.rawValue) + field.typeText(XCUIKeyboardKey.delete.rawValue) + field.typeText(XCUIKeyboardKey.delete.rawValue) + field.typeText(XCUIKeyboardKey.delete.rawValue) + field.typeText(XCUIKeyboardKey.delete.rawValue) + field.typeText(XCUIKeyboardKey.delete.rawValue) XCTAssertEqual(field.value! as! String, "") field.typeText("g") XCTAssertEqual(field.value! as! String, "google.com/") field.typeText("z") XCTAssertEqual(field.value! as! String, "gz") - field.typeText(XCUIKeyboardKeyDelete) + field.typeText(XCUIKeyboardKey.delete.rawValue) XCTAssertEqual(field.value! as! String, "g") field.typeText("o") XCTAssertEqual(field.value! as! String, "google.com/")