Using stringByReplacingCharactersInRange in Swift

2020-02-10 02:17发布

I'm trying to use UITextFieldDelegate in Swift/Xcode6 and I'm struggling with the way I'm supposed to use stringByReplacingCharactersInRange. The compiler error is 'Cannot convert the expression's type 'String' to type '$T8'.

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool
{
    let s = textField.text.stringByReplacingCharactersInRange(range:range, withString:string)
    if countElements(s) > 0 {

    } else {

    }
    return true
}

Update for Xcode 6 Beta 5: The thing is shouldChangeCharactersInRange gives an NSRange object and we'd need a Swift Range object for stringByReplacingCharactersInRange. Can this still be considered a bug as I don't see why we should still be dealing with NS* objects? The String argument of the delegate method is anyway of a Swift type.

标签: swift
13条回答
不美不萌又怎样
2楼-- · 2020-02-10 02:53

Working & tested

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let newString = NSString(string: textField.text!).replacingCharacters(in: range, with: string)

    print(newString)

      return true;
}
查看更多
叛逆
3楼-- · 2020-02-10 02:54

This is a cross-post from this question, but without a way to make a Range<String.Index> the Swift-native String.stringByReplacingCharactersInRange() is pretty useless. So, here's a function to generate a Range<String.Index>:

func RangeMake(#start:Int, #end:Int) -> Range<String.Index> {
    assert(start <= end, "start must be less than or equal to end")
    func rep(str: String, count: Int) -> String {
        var result = ""
        for i in 0..count {
            result += str
        }
        return result
    }
    let length = end - start
    let padding = rep(" ", start)
    let dashes = rep("-", length)
    let search = padding + dashes
    return search.rangeOfString(dashes, options: nil, range: Range(start: search.startIndex, end: search.endIndex), locale: NSLocale.systemLocale())
}

let sourceString = "Call me Ishmael."
let range = RangeMake(start: 8, end: 15)    
let name = sourceString.substringWithRange(range)
// name = "Ishmael"
查看更多
乱世女痞
4楼-- · 2020-02-10 03:00

for iOS 8.3 use following code

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
    if textField.isEqual(<textField whose value to be copied>)
    {
        <TextField to be updated>.text = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
    }

    return true
}
查看更多
Animai°情兽
5楼-- · 2020-02-10 03:04

Here's how to calculate the resulting string in various Swift versions.

Note that all methods use -[NSString stringByReplacingOccurrencesOfString:withString:] in exactly the same way, just differing in syntax.

This is the preferred way to calculate the resulting string. Converting to a Swift Range and use that on a Swift String is error prone. Johan's answer for example is incorrect in a couple of ways when operating on non-ASCII strings.

Swift 3:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let result = (textField.text as NSString?)?.replacingCharacters(in: range, with: string) ?? string
    // ... do something with `result`
}

Swift 2.1:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let result = (textField.text as NSString?)?.stringByReplacingCharactersInRange(range, withString: string)
    // ... do something with `result`
}

Swift 1 (only left here for reference):

let result = textField.text.bridgeToObjectiveC().stringByReplacingCharactersInRange(range, withString:string)
查看更多
虎瘦雄心在
6楼-- · 2020-02-10 03:05

Nothing worked for me except the following: (FYI I'm using Xcode7.0 GM, Swift 2.0, iOS9GM)

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let currentText = textField.text ?? ""
    let prospectiveText = (currentText as NSString).stringByReplacingCharactersInRange(range, withString: string)
    print("prospectiveText", prospectiveText)
    return true;
}
查看更多
可以哭但决不认输i
7楼-- · 2020-02-10 03:08

As of Swift 4, this is a little simpler, like Alexander Volkov's answer, but without the extension.

   func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let revisedText: String
        if let text = textField.text, let swiftRange = Range(range, in: text) {
            revisedText = text.replacingCharacters(in: swiftRange, with: string)
        } else {
            revisedText = string
        }
        // Do something with the text and return boolean.
   }
查看更多
登录 后发表回答