1

I'm trying to autocomplete emails. I've done the autocomplete part, but I want to use some properties in strings. For example, after typing the user's e-mail address and making @g, I want to show a different background color of the mail.com section. Then when the user presses m I want to make this background color white again. Below are the codes I have written so far. Is there anyone who can help?

let suggestionsArray = ["gmail.com", "hotmail.com", "outlook.com"]
        
    private func autoComplete(str: String) -> Bool {
        if let text = textField.text {
            let control = text.components(separatedBy: "@")
            if control.count > 1 {
                var newText = control[0] + "@"
                var autoCompleteFinished: Bool = false
                let numberOfCharacters: Int = control[1].count + 1
                suggestionsArray.forEach({ suggestion in
                    if autoCompleteFinished { return }
                    if suggestion.prefix(numberOfCharacters) == (control[1] + str) {
                        autoCompleteFinished = true
                        newText = newText + suggestion
                        let colouredString: NSMutableAttributedString = NSMutableAttributedString(string: newText)
                        if let selectedRange = textField.selectedTextRange {
                            let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)
                            colouredString.addAttribute(NSAttributedStringKey.backgroundColor, value: UIColor.ubYellow, range: NSRange(location: cursorPosition + 1 ,length:suggestion.count-numberOfCharacters))
                        }
                        self.textField.attributedText = colouredString
                        //textField.text = newText
                        if newText.hasSuffix(suggestion) {
                            if let selectedRange = textField.selectedTextRange {
                                if let newPosition = textField.position(from: selectedRange.start, offset: -(suggestion.count-numberOfCharacters)) {
                                    textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
                                }
                            }
                        }
                    }
                })
                return autoCompleteFinished
            }
        }
    return false
    }

    private func characterAfterCursor() -> String? {
        if let cursorRange = textField.selectedTextRange {
            if let newPosition = textField.position(from: cursorRange.start, offset: 1) {
                let range = textField.textRange(from: newPosition, to: cursorRange.start)
                return textField.text(in: range!)
            }
        }
        return nil
    }
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if let ftype = self.fType {
            switch ftype {
            case .email, .emailNoImage:
                
                if string == characterAfterCursor() {
                    if let selectedRange = textField.selectedTextRange {
                        if let newPosition = textField.position(from: selectedRange.start, offset: 1) {
                            textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
                        }
                    }
                    return false
                }
                
                if string != characterAfterCursor() {
                    var lastString: Int
                    if let selectedRange = textField.selectedTextRange {
                        let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)
                        lastString = textField.text!.count - cursorPosition
                        textField.text?.removeLast(lastString)
                    }
                }
                
                if string != "" {
                    return !autoComplete(str: string)
                }

                break
            default:
                break
            }
        }```

Willeke
  • 14,578
  • 4
  • 19
  • 47
  • So you want the emails in the string to appear with a different background color / font color ? – Shawn Frank Apr 01 '22 at 17:31
  • Please trim your code to make it easier to find your problem. Follow these guidelines to create a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Community Apr 01 '22 at 19:05
  • Let me explain, I want the background color of the completed part to be different when the auto-completion for the email is finished. But I want the background color to return to default as the user enters characters. @ShawnFrank – Şevval Tıraşlar Apr 03 '22 at 02:33

2 Answers2

0

You can try to do this with regex

private func highlightMailServices() {
    
    // (?<=@) - Positive lookbehind to capture text after an '@'
    // \w+ - Capture one or more characters after the @
    // \. - Capture the '.' symbol after previous characters
    // [a-z]{2,} - Capture the domains like com, design
    let pattern = "(?<=@)\\w+\\.[a-z]{2,}"
    
    if let mainString = textView.text
    {
        let attributedText = NSMutableAttributedString(string: mainString)
        
        do
        {
            let regex = try NSRegularExpression(pattern: pattern,
                                                options: .caseInsensitive)
            
            // Loop through all the occurrences found and highlight
            // in yellow
            for match in regex.matches(in: mainString,
                                       options: NSRegularExpression.MatchingOptions(),
                                       range: NSRange(location: 0,
                                                      length: mainString.count))
                as [NSTextCheckingResult]
            {
                attributedText.addAttribute(NSAttributedString.Key.foregroundColor,
                                            value: UIColor.systemBlue,
                                            range: match.range)
            }
            
            textView.attributedText = attributedText
        }
        catch
        {
            // handle errors
            print("error")
        }
    }
}

You will need to improve this to highlight something like .com.au

This is the end product I get when testing with a textview where the emails get highlighted in blue text

NSRegularExpression REGEX highlight emails swift iOS textview textfield

Shawn Frank
  • 4,381
  • 2
  • 19
  • 29
0

I solved my problem. I wasn't updating the color after scrolling the cursor. I hope the answer satisfies you.

func autoComplete(str: String) -> Bool {
    if let text = textField.text {
        let control = text.components(separatedBy: "@")
        if control.count > 1 {
            var newText = control[0] + "@"
            var autoCompleteFinished: Bool = false
            let numberOfCharacters: Int = control[1].count + 1
            suggestionsArray.forEach({ suggestion in
                if autoCompleteFinished { return }
                if suggestion.prefix(numberOfCharacters) == (control[1] + str) {
                    autoCompleteFinished = true
                    newText = newText + suggestion
                    let colouredString: NSMutableAttributedString = NSMutableAttributedString(string: newText)
                    if let selectedRange = textField.selectedTextRange {
                        let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)
                        colouredString.addAttribute(NSAttributedStringKey.backgroundColor, value: UIColor.ubYellow, range: NSRange(location: cursorPosition + 1 ,length:suggestion.count-numberOfCharacters))
                    }
                    self.textField.attributedText = colouredString
                    if newText.hasSuffix(suggestion) {
                        if let selectedRange = textField.selectedTextRange {
                            if let newPosition = textField.position(from: selectedRange.start, offset: -(suggestion.count-numberOfCharacters)) {
                                textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
                            }
                        }
                    }
                }
            })
            return autoCompleteFinished
        }
    }
return false
}

func characterAfterCursor() -> String? {
    if let cursorRange = textField.selectedTextRange {
        if let newPosition = textField.position(from: cursorRange.start, offset: 1) {
            let range = textField.textRange(from: newPosition, to: cursorRange.start)
            return textField.text(in: range!)
        }
    }
    return nil
}













func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    let allText = (textField.text ?? "")
    let newPosition = textField.endOfDocument
    textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
    let colouredString: NSMutableAttributedString = NSMutableAttributedString(string: textField.text ?? "")
    colouredString.addAttribute(NSAttributedStringKey.backgroundColor, value: UIColor.clear, range: NSRange(location: 0 ,length: allText.count))
    self.textField.attributedText = colouredString
    return true
}

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if let ftype = self.fType {
        switch ftype {
        case .email, .emailNoImage:
            
            if string == characterAfterCursor() {
                if let selectedRange = textField.selectedTextRange {
                    if let newPosition = textField.position(from: selectedRange.start, offset: 1) {
                        textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
                        let allText = (textField.text ?? "")
                        let colouredString: NSMutableAttributedString = NSMutableAttributedString(string: allText)
                        if let selectedRange = textField.selectedTextRange {
                            let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)
                            colouredString.addAttribute(NSAttributedStringKey.backgroundColor, value: UIColor.clear, range: NSRange(location: 0 ,length: cursorPosition))
                            colouredString.addAttribute(NSAttributedStringKey.backgroundColor, value: UIColor.ubYellow, range: NSRange(location: cursorPosition ,length: allText.count - cursorPosition))
                        }
                        self.textField.attributedText = colouredString
                        textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
                    }
                }
                return false
            }
            
            if string != characterAfterCursor() {
                var lastString: Int
                if let selectedRange = textField.selectedTextRange {
                    let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)
                    lastString = textField.text!.count - cursorPosition
                    textField.text?.removeLast(lastString)
                    let colouredString: NSMutableAttributedString = NSMutableAttributedString(string: textField.text ?? "")
                    colouredString.addAttribute(NSAttributedStringKey.backgroundColor, value: UIColor.clear, range: NSRange(location: 0 ,length: cursorPosition))
                    self.textField.attributedText = colouredString
                }
            }
            
            if string != "" {
                return !autoComplete(str: string)
            }

            break
        default:
            break
        }
    }
    
    return true
}