【问题标题】:Making a text view respond to text typed by the user使文本视图响应用户输入的文本
【发布时间】:2015-09-02 14:46:00
【问题描述】:

我的应用中有一个文本视图,允许用户在其中输入任何内容。我希望文本视图在输入时检测到几个单词并更改它们的颜色。

例如,如果用户键入-“我最喜欢的颜色是红色”,那么我希望单词“红色”得到文本颜色“红色”。但因此应该在句子中输入红色单词后立即发生。我应该如何实现这个?

【问题讨论】:

  • 我看到您将这些类嵌套在函数中。不要那样做。当您创建/设计类时,您正在创建模板。所以你想把它们放在一个单独的文件中。在您的 UIViewController 中,您创建该类的一个实例并调用该类的函数。
  • @RMenke 好的,我用类代码创建了一个 Swift 文件。然后我在 ViewController 类中键入了其他代码。我应该如何创建、实例化和调用该类的函数?
  • syntaxHighlighter:荧光笔!不工作
  • 创建实例:var myInstanceOfAClass : AClass = AClass()var myInstanceOfAClass : AClass = AClass(stuffTheClassNeeds: StuffIGiveToTheClass) 仔细查看我回答中的代码。您需要所有部件。
  • 调用类函数:myInstanceOfAClass.myClassFunction() or myInstanceOfAClass.myClassFunction(stuffTheFunctionNeeds: StuffIGiveToTheFunction)

标签: ios swift xcode6 uitextview


【解决方案1】:

你需要三样东西:

  • 在界面构建器中,您需要使用其中一种委托方法。我认为“editingChanged”是这里最好的。从带有“ctrl”的文本字段拖动到您的文档中。

  • 您需要一种方法来检查文本字段中的字符串并检测单词。

    componentsSeparatedByCharactersInSet

  • 您需要一种方法来设置句子中的一个单词的样式。

    NSMutableAttributedString

也很有趣:how to separate a string without removing the delimiter

部分代码(把它扔到操场上):

这将找到所有要更改的单词,但删除分隔符。完成代码需要做更多的工作。

var strSeperator : NSCharacterSet = NSCharacterSet(charactersInString: ",.:;?! ")

var strArray = str.componentsSeparatedByCharactersInSet(strSeperator)

var styledText = NSMutableAttributedString()

for i in 0..<strArray.count {

    let currentWord = strArray[i]
    var currentBoolFoundInControl : Bool = false

    for iB in 0..<colorTheseStrings.count {

        let controlWord = colorTheseStrings[iB]

        if controlWord == currentWord {
            currentBoolFoundInControl = true
            // add to mutable attributed string in a color
        }

    }

    var attrString1 = NSMutableAttributedString(string: "\(strArray[i]) ")

    if currentBoolFoundInControl == true {

        var range = (strArray[i] as NSString).rangeOfString(strArray[i])
        if strArray[i] == "red" {
            attrString1.addAttribute(NSForegroundColorAttributeName, value: UIColor(red: 0.5, green: 0.0, blue: 0.0, alpha: 1.0), range: range)
        } else if strArray[i] == "blue" {
            attrString1.addAttribute(NSForegroundColorAttributeName, value: UIColor(red: 0.0, green: 0.0, blue: 0.5, alpha: 1.0), range: range)

        }
    }

    styledText.appendAttributedString(attrString1)
}

myTextField.attributedText = styledText

另一种方式:

download it here

我认为这种方式是最稳健、最酷、最高效的。 代码可以稍微清理一下,并且可以使用更多的风格/风格。这对于“天蓝色”之类的东西确实有问题,因为它会首先找到“蓝色”并替换它。但我不得不留下一些改进的空间。 ;)

我无法自拔,所以我修复了最后一个问题。

再一次,我修复了,我的修复。现在更高效且实际正确。

第一部分是 HighLighter 类,将其放在单独的文档中。

// text hightlighter

class SyntaxGroup {

    var wordCollection : [String] = []
    var type : String = ""
    var color : UIColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)

    init(wordCollection_I : [String], type_I : String, color_I: UIColor) {

        wordCollection = wordCollection_I
        type = type_I
        color = color_I

    }
}

class SyntaxDictionairy {

    var collections : [SyntaxGroup] = []

}

class SyntaxRange {

    var range : NSRange
    var color : UIColor

    init (color_I : UIColor, range_I : NSRange) {
        color = color_I
        range = range_I
    }

}

class HighLighter {

    var ranges : [SyntaxRange] = []
    var baseString : NSMutableString = NSMutableString()
    var highlightedString : NSMutableAttributedString = NSMutableAttributedString()
    var syntaxDictionairy : SyntaxDictionairy

    init (syntaxDictionairy_I : SyntaxDictionairy) {

        syntaxDictionairy = syntaxDictionairy_I

    }

    func run(string : String?, completion: (finished: Bool) -> Void) {

        ranges = [] // reset the ranges, else it crashes when you change a previous part of the text
        highlightedString = NSMutableAttributedString() // make sure all strings start fresh
        baseString = NSMutableString() // make sure all strings start fresh

        // multi threading to prevent locking up the interface with large libraries.
        let qualityOfServiceClass = QOS_CLASS_DEFAULT
        let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
        dispatch_async(backgroundQueue) { () -> Void in

            if string != nil && string != "" {

                self.highlightedString = NSMutableAttributedString(string: string!)

                for i in 0..<self.syntaxDictionairy.collections.count {

                    for iB in 0..<self.syntaxDictionairy.collections[i].wordCollection.count {

                        let currentWordToCheck = self.syntaxDictionairy.collections[i].wordCollection[iB]
                        self.baseString = NSMutableString(string: string!)

                        while self.baseString.containsString(self.syntaxDictionairy.collections[i].wordCollection[iB]) {

                            let nsRange = (self.baseString as NSString).rangeOfString(currentWordToCheck)
                            let newSyntaxRange = SyntaxRange(color_I: self.syntaxDictionairy.collections[i].color, range_I: nsRange)
                            self.ranges.append(newSyntaxRange)

                            var replaceString = ""
                            for _ in 0..<nsRange.length {
                                replaceString += "§" // secret unallowed character
                            }
                            self.baseString.replaceCharactersInRange(nsRange, withString: replaceString)
                        }
                    }
                }
                for i in 0..<self.ranges.count {

                    self.highlightedString.addAttribute(NSForegroundColorAttributeName, value: self.ranges[i].color, range: self.ranges[i].range)

                }
            }

            dispatch_sync(dispatch_get_main_queue()) { () -> Void in

                completion(finished: true)
            }

        }
    }
}

在 ViewController 中: 这是您将与 UITextfield 一起使用的代码。 首先创建一个荧光笔实例并设置您的单词词典和相应的颜色。然后在需要的时候启动run函数。

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var myTextfield: UITextField!

    var syntaxHighLighter : HighLighter! // declare highlighter

    override func viewDidLoad() {
        super.viewDidLoad()
        setUpHighLighter()
    }
    // this is just a little function to put the set up for the highlighter outside of viewDidLoad()
    func setUpHighLighter() {

        // build a dict of words to highlight
        let redColor = UIColor(red: 0.5, green: 0.0, blue: 0.0, alpha: 1.0)
        let blueColor = UIColor(red: 0.0, green: 0.0, blue: 0.5, alpha: 1.0)
        let greenColor = UIColor(red: 0.0, green: 0.5, blue: 0.0, alpha: 1.0)

        let redGroup = SyntaxGroup(wordCollection_I: ["red","bordeaux"], type_I: "Color", color_I: redColor)
        let blueGroup = SyntaxGroup(wordCollection_I: ["coralblue","blue","skyblue","azur"], type_I: "Color", color_I: blueColor)
        let greenGroup = SyntaxGroup(wordCollection_I: ["green"], type_I: "Color", color_I: greenColor)

        let dictionairy : SyntaxDictionairy = SyntaxDictionairy()
        dictionairy.collections.append(blueGroup)
        dictionairy.collections.append(greenGroup)
        dictionairy.collections.append(redGroup)

        syntaxHighLighter = HighLighter(syntaxDictionairy_I: dictionairy)

    }
    // this is where the magic happens, place the code from inside the editingChanged inside your function that responds to text changes.
    @IBAction func editingChanged(sender: UITextField) {

        syntaxHighLighter.run(myTextfield.text) { (finished) -> Void in
            self.myTextfield.attributedText = self.syntaxHighLighter.highlightedString
        }
    }
}

【讨论】:

【解决方案2】:
textField.addTarget(self, action: "textFieldDidChange:",forControlEvents: UIControlEvents.EditingChanged)

func textFieldDidChange(textField: UITextField) {
//your code

var main_string = textField.text
var string_to_color = "red"

var range = (main_string as NSString).rangeOfString(string_to_color)

var attributedString = NSMutableAttributedString(string:main_string)
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor() , range: range)

}

【讨论】:

  • 我明白了,但我应该如何只更改一个特定单词的颜色? @FawadMasud
  • 你应该使用 NSMutableattributedstring。我会尽快更新。
  • 或查看我的答案以立即获得;)
  • 该死的太短了。我们两个答案的结合是最好的。您还需要一种检测多个字符串的方法。
  • @RMenke 我认为同样的程序可以处理多个字符串。
【解决方案3】:

也许你可以实现 Text View Delegate 来检测用户何时完成输入,在条件中询问书面文本是否是你想要的,在肯定的情况下做一些事情(改变颜色)。 这里有一些文档https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITextViewDelegate_Protocol/ 你可以尝试实现这样的东西:

let text: UITextView? //this must be binded with the storyboard ui

//MARK UITextViewDelegate

func textViewDidChange(_ textView: UITextView){
     if (textView.text == "bla"){
         textView.colour == UIColour(Red)
     }
}

此代码只是一个架构。阅读文档并检查语法。希望对你有帮助!!

美联储

【讨论】:

  • 看看代码我可以说这根本行不通,因为这个词可以在句子中间的任何地方:)
  • 在这种情况下,您必须解析 textView.text 并在句子的任何部分搜索内容。
【解决方案4】:

你必须在 UITextView 委托方法中使用attributedText

- (void)textViewDidChange:(UITextView *)textView

这将解决您的问题。

【讨论】:

    【解决方案5】:

    我认为您应该这样做(如果我错了,请纠正我,因为我没有 Xcode 在这台计算机上进行测试,但这应该可以)。如果这不起作用,请执行 Fawad Masud 并将其添加到视图中加载...

     yourTextView.addTarget(self, action: "textViewDidChange:",forControlEvents: UIControlEvents.EditingChanged)
    

    override func viewDidLoad() {
        super.viewDidLoad()
        yourTextView.delegate = self //Basically makes the function below applicable to this textview
    }
    
    func textViewDidChange(textView: UITextView) { //Every time text changes this code is run
       var textViewText = yourTextView.text as NSString!
    
    if textViewText.containsString("red") {
          textViewText.textColor = UIColor.redColor()
    
       }
    }
    

    【讨论】:

    • 我无法在 textView @EthanCotler 上添加 .addTarget
    猜你喜欢
    • 2020-01-02
    • 1970-01-01
    • 2017-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多