Meshach
Meshach

Reputation: 315

Swift Strings appear to mishandle carriage returns and newlines together

For context, the app I'm developing is using a Bluetooth UART connection, and that's how I discovered this apparent issue.

When ending my messages with "/r/n" Swift ignores the newline when considering the length of the string. I can actually add a SECOND newline, but that introduces UART bugs.

Here's some code that outlines my issue:

var str = "Hey Apple"
print(str.count) //9
str += "\r" //"Hey Apple\r"
print(str.count) //10
str += "\n" //"Hey Apple\r\n"
print(str.count) //10
str += "\n" //"Hey Apple\r\n\n"
print(str.count) //11


var str2 = "Uh, hello?"
print(str2.count) //10
str2 += "\n" //"Uh, hello?\n"
print(str2.count) //11
str2 += "\n" //"Uh, hello?\n\n"
print(str2.count) //12
str2 += "\r" //"Uh, hello?\n\n\r"
print(str2.count) //13

There's something fishy here, and I don't know why.

Ideas?

Upvotes: 1

Views: 257

Answers (1)

Martin R
Martin R

Reputation: 539815

Both "\r" and "\r\n" count as a single "extended Unicode grapheme cluster", and that is what str.count counts (compare "Strings and Characters" in the Swift reference and Strings in Swift 2 in the Swift blog).

If you convert the string to UTF-8 data for sending it via Bluetooth and determine the actual length of the data

let data = Data(str.utf8)
let count = data.count // == str.utf8.count

then everything works as expected:

var str = "Hey Apple"
print(Data(str.utf8) as NSData) // <48657920 4170706c 65>
print(Data(str.utf8).count) // 9

str += "\r" //"Hey Apple\r"
print(Data(str.utf8) as NSData) // <48657920 4170706c 650d>
print(Data(str.utf8).count) // 10

str += "\n" //"Hey Apple\r\n"
print(Data(str.utf8) as NSData) // <48657920 4170706c 650d0a>
print(Data(str.utf8).count) // 11

str += "\n" //"Hey Apple\r\n\n"
print(Data(str.utf8) as NSData) // <48657920 4170706c 650d0a0a>
print(Data(str.utf8).count) // 12

Upvotes: 4

Related Questions