I can't figure out String.Index vs. Int
error is...
Instance method 'replaceSubrange(_:with:)' requires the types 'String.Index' and 'Int' be equivalent
func MID( destin: String, start_pos: Int, length: Int, source: String )
{
var destin_string = destin
let dest_index = Int( start_pos - 1 )
let dest_end_index = Int( dest_index + length )
destin_string.replaceSubrange( dest_index...dest_end_index, <<<<<< error
with: source )
}
The index type of String
is not Int
-compatible because a character can contain multiple bytes.
A workaround to convert Int
indices to String.Index
is NSRange
which matches the startPos
and length
parameters and which can be reliably converted to Range<String.Index>
.
By the way to modify the string inside the function and never use it makes no sense. A better way is an inout
parameter
func MID(destin: inout String, startPos: Int, length: Int, source: String )
{
let nsRange = NSRange(location: startPos, length: length)
guard let range = Range(nsRange, in: destin) else { return }
destin.replaceSubrange(range, with: source)
}
The best way is to work with indices all the way and specially the function index(:offsetBy:)
Something like this
func MID(destin: String, start_pos: Int, length: Int, source: String ) -> String {
var destin_string = destin
let dest_index = destin.index(destin.startIndex, offsetBy: start_pos)
let dest_end_index = destin.index(destin.startIndex, offsetBy: start_pos + length)
destin_string.replaceSubrange( dest_index...dest_end_index,
with: source )
return destin_string
}
You might need to adjust some calculations depending on what this function is supposed to do.
Here is a variant of the above with what I consider a bit better naming and some basic error handling
func replace(in string: String, start: Int, length: Int, with replacement: String ) -> String {
if string.isEmpty || start >= string.count { return string }
var input = string
let startIndex = string.index(string.startIndex, offsetBy: start)
var endIndex = string.index(string.startIndex, offsetBy: start + length)
if endIndex >= string.endIndex { endIndex = string.endIndex }
input.replaceSubrange(startIndex..<endIndex, with: replacement)
return input
}
In Swift String
is a collection with its own Index
type, which doesn't coincide with Int
type as per Swift's Array
collection.
You'd better read the the official String
documentation at the section "Manipulating Indices".
Anyway, in your case rather than that method you wrote, you'd better just write an helper in an extension to get the range of indices from a String
instance and then use directly the replaceSubrange(_:with:)
method.
Something like:
extension String {
func indicesRange(position: Int, length: Int) -> Range<String.Index>? {
assert(position >= 0 && length >= 0, "position and length must not be negative.")
guard
let start = index(startIndex, offsetBy: position, limitedBy: endIndex),
start < endIndex,
let end = index(start, offsetBy: length, limitedBy: endIndex),
end > start
else { return nil }
return start..<end
}
}
// usage assuming previously defined destination and source strings,
// as well as startPos and length non-negative Int values:
if let range = destination.indicesRange(position: startPos, length: length) {
destination.replaceSubrange(range, with: source)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.