어떻게 변환 할 수 있습니다 NSRange
에 Range<String.Index>
스위프트에?
다음 UITextFieldDelegate
방법 을 사용하고 싶습니다 .
func textField(textField: UITextField!,
shouldChangeCharactersInRange range: NSRange,
replacementString string: String!) -> Bool {
textField.text.stringByReplacingCharactersInRange(???, withString: string)
답변
의 NSString
버전 (Swift String과 반대)은을 replacingCharacters(in: NSRange, with: NSString)
허용 NSRange
하므로 간단한 해결책은 first 로 변환 String
하는 것NSString
입니다. Swift 3과 2에서는 델리게이트 및 대체 메소드 이름이 약간 다르므로 사용중인 Swift에 따라 다릅니다.
스위프트 3.0
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let nsString = textField.text as NSString?
let newString = nsString?.replacingCharacters(in: range, with: string)
}
스위프트 2.x
func textField(textField: UITextField,
shouldChangeCharactersInRange range: NSRange,
replacementString string: String) -> Bool {
let nsString = textField.text as NSString?
let newString = nsString?.stringByReplacingCharactersInRange(range, withString: string)
}
답변
현재 스위프트 4 (엑스 코드 9), 스위프트 표준 라이브러리는 스위프트 문자열 범위 (사이의 변환 방법 제공 Range<String.Index>
) 및 NSString
범위 ( NSRange
). 예:
let str = "a?b??c"
let r1 = str.range(of: "??")!
// String range to NSRange:
let n1 = NSRange(r1, in: str)
print((str as NSString).substring(with: n1)) // ??
// NSRange back to String range:
let r2 = Range(n1, in: str)!
print(str[r2]) // ??
따라서 텍스트 필드 위임 방법에서 텍스트 교체는 이제 다음과 같이 수행 할 수 있습니다
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
if let oldString = textField.text {
let newString = oldString.replacingCharacters(in: Range(range, in: oldString)!,
with: string)
// ...
}
// ...
}
(Swift 3 및 이전 버전에 대한 이전 답변 🙂
Swift 1.2부터는 String.Index
초기화 프로그램이 있습니다
init?(_ utf16Index: UTF16Index, within characters: String)
중간 변환없이 다음 NSRange
으로 Range<String.Index>
올바르게 변환 하는 데 사용할 수 있습니다 (이모 지, 지역 지표 또는 기타 확장 된 그래 핀 군집 포함) NSString
.
extension String {
func rangeFromNSRange(nsRange : NSRange) -> Range<String.Index>? {
let from16 = advance(utf16.startIndex, nsRange.location, utf16.endIndex)
let to16 = advance(from16, nsRange.length, utf16.endIndex)
if let from = String.Index(from16, within: self),
let to = String.Index(to16, within: self) {
return from ..< to
}
return nil
}
}
이 메소드는 주어진 Swift 문자열에 대해 모든 s가 유효 하지 않기 때문에 선택적 문자열 범위를 리턴 NSRange
합니다.
UITextFieldDelegate
위임 방법은 다음과 같이 쓸 수있다
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if let swRange = textField.text.rangeFromNSRange(range) {
let newString = textField.text.stringByReplacingCharactersInRange(swRange, withString: string)
// ...
}
return true
}
역변환은
extension String {
func NSRangeFromRange(range : Range<String.Index>) -> NSRange {
let utf16view = self.utf16
let from = String.UTF16View.Index(range.startIndex, within: utf16view)
let to = String.UTF16View.Index(range.endIndex, within: utf16view)
return NSMakeRange(from - utf16view.startIndex, to - from)
}
}
간단한 테스트 :
let str = "a?b??c"
let r1 = str.rangeOfString("??")!
// String range to NSRange:
let n1 = str.NSRangeFromRange(r1)
println((str as NSString).substringWithRange(n1)) // ??
// NSRange back to String range:
let r2 = str.rangeFromNSRange(n1)!
println(str.substringWithRange(r2)) // ??
스위프트 2 업데이트 :
Swift 2 버전은 rangeFromNSRange()
Serhii Yakovenko가 이미이 답변 에서 제공했습니다. 완전성을 위해 여기에 포함 시킵니다 .
extension String {
func rangeFromNSRange(nsRange : NSRange) -> Range<String.Index>? {
let from16 = utf16.startIndex.advancedBy(nsRange.location, limit: utf16.endIndex)
let to16 = from16.advancedBy(nsRange.length, limit: utf16.endIndex)
if let from = String.Index(from16, within: self),
let to = String.Index(to16, within: self) {
return from ..< to
}
return nil
}
}
스위프트 2 버전 NSRangeFromRange()
은
extension String {
func NSRangeFromRange(range : Range<String.Index>) -> NSRange {
let utf16view = self.utf16
let from = String.UTF16View.Index(range.startIndex, within: utf16view)
let to = String.UTF16View.Index(range.endIndex, within: utf16view)
return NSMakeRange(utf16view.startIndex.distanceTo(from), from.distanceTo(to))
}
}
스위프트 3 업데이트 (Xcode 8) :
extension String {
func nsRange(from range: Range<String.Index>) -> NSRange {
let from = range.lowerBound.samePosition(in: utf16)
let to = range.upperBound.samePosition(in: utf16)
return NSRange(location: utf16.distance(from: utf16.startIndex, to: from),
length: utf16.distance(from: from, to: to))
}
}
extension String {
func range(from nsRange: NSRange) -> Range<String.Index>? {
guard
let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex),
let to16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location + nsRange.length, limitedBy: utf16.endIndex),
let from = from16.samePosition(in: self),
let to = to16.samePosition(in: self)
else { return nil }
return from ..< to
}
}
예:
let str = "a?b??c"
let r1 = str.range(of: "??")!
// String range to NSRange:
let n1 = str.nsRange(from: r1)
print((str as NSString).substring(with: n1)) // ??
// NSRange back to String range:
let r2 = str.range(from: n1)!
print(str.substring(with: r2)) // ??
답변
Range<String.Index>
클래식 대신 사용해야 합니다 NSRange
. 내가하는 방법 (아마도 더 좋은 방법이있을 수 있음)은 문자열을 String.Index
이동시키는 것입니다 advance
.
대체하려는 범위를 모르지만 처음 두 문자를 바꾸려는 척하십시오.
var start = textField.text.startIndex // Start at the string's start index
var end = advance(textField.text.startIndex, 2) // Take start index and advance 2 characters forward
var range: Range<String.Index> = Range<String.Index>(start: start,end: end)
textField.text.stringByReplacingCharactersInRange(range, withString: string)
답변
Martin R의 대답 은 유니 코드를 설명하기 때문에 올바른 것 같습니다.
그러나 게시물 (Swift 1) 당시 그의 코드는 advance()
기능 을 제거했기 때문에 Swift 2.0 (Xcode 7)에서 컴파일되지 않습니다 . 업데이트 된 버전은 다음과 같습니다.
스위프트 2
extension String {
func rangeFromNSRange(nsRange : NSRange) -> Range<String.Index>? {
let from16 = utf16.startIndex.advancedBy(nsRange.location, limit: utf16.endIndex)
let to16 = from16.advancedBy(nsRange.length, limit: utf16.endIndex)
if let from = String.Index(from16, within: self),
let to = String.Index(to16, within: self) {
return from ..< to
}
return nil
}
}
스위프트 3
extension String {
func rangeFromNSRange(nsRange : NSRange) -> Range<String.Index>? {
if let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex),
let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex),
let from = String.Index(from16, within: self),
let to = String.Index(to16, within: self) {
return from ..< to
}
return nil
}
}
스위프트 4
extension String {
func rangeFromNSRange(nsRange : NSRange) -> Range<String.Index>? {
return Range(nsRange, in: self)
}
}
답변
당신은 변환하는 방법을 구체적으로 요청 때문에 그러나 에밀리의 대답과 유사 NSRange
에 Range<String.Index>
당신이 이런 짓을 할 것이다 :
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let start = advance(textField.text.startIndex, range.location)
let end = advance(start, range.length)
let swiftRange = Range<String.Index>(start: start, end: end)
...
}
답변
@Emilie의 훌륭한 답변에 대한 리프로 대체 / 경쟁 답변이 아닙니다.
(Xcode6-Beta5)
var original = "???This is a test"
var replacement = "!"
var startIndex = advance(original.startIndex, 1) // Start at the second character
var endIndex = advance(startIndex, 2) // point ahead two characters
var range = Range(start:startIndex, end:endIndex)
var final = original.stringByReplacingCharactersInRange(range, withString:replacement)
println("start index: \(startIndex)")
println("end index: \(endIndex)")
println("range: \(range)")
println("original: \(original)")
println("final: \(final)")
산출:
start index: 4
end index: 7
range: 4..<7
original: ???This is a test
final: ??!his is a test
색인은 여러 코드 단위를 설명합니다. 플래그 (Regional INDICATOR SYMBOL LETTERS ES)는 8 바이트이고 (FACE WITH TOYS OF JOY)는 4 바이트입니다. (이 특별한 경우 바이트 수는 UTF-8, UTF-16 및 UTF-32 표현에서 동일하다는 것이 밝혀졌습니다.)
기능으로 감싸기 :
func replaceString(#string:String, #with:String, #start:Int, #length:Int) ->String {
var startIndex = advance(original.startIndex, start) // Start at the second character
var endIndex = advance(startIndex, length) // point ahead two characters
var range = Range(start:startIndex, end:endIndex)
var final = original.stringByReplacingCharactersInRange(range, withString: replacement)
return final
}
var newString = replaceString(string:original, with:replacement, start:1, length:2)
println("newString:\(newString)")
산출:
newString: !his is a test
답변
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
let strString = ((textField.text)! as NSString).stringByReplacingCharactersInRange(range, withString: string)
}