Reputation: 472
We are using following URL encoding in Objective C now we are migrating to swift .what will be the equivalent encoding for below ObjC to swift 3.
- (NSString *) URLEncodedString {
NSMutableString * output = [NSMutableString string];
const unsigned char * source = (const unsigned char *)[self UTF8String];
int sourceLen = strlen((const char *)source);
for (int i = 0; i < sourceLen; ++i) {
const unsigned char thisChar = source[i];
if (thisChar == ' '){
[output appendString:@"+"];
} else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' ||
(thisChar >= 'a' && thisChar <= 'z') ||
(thisChar >= 'A' && thisChar <= 'Z') ||
(thisChar >= '0' && thisChar <= '9')) {
[output appendFormat:@"%c", thisChar];
} else {
[output appendFormat:@"%%%02X", thisChar];
}
}
return output;
}
Upvotes: 3
Views: 192
Reputation: 691
Try this swift 3 compatible code. I've tested it in a playground and works fine.
extension String {
func urlEncodedString() -> String {
var output = ""
for thisChar in self.utf8 {
if thisChar == UInt8(ascii: " ") {
output += "+"
}
else if thisChar == UInt8(ascii: ".") ||
thisChar == UInt8(ascii: "-") ||
thisChar == UInt8(ascii: "_") ||
thisChar == UInt8(ascii: "~") ||
(thisChar >= UInt8(ascii: "a") && thisChar <= UInt8(ascii: "z")) ||
(thisChar >= UInt8(ascii: "A") && thisChar <= UInt8(ascii: "Z")) ||
(thisChar >= UInt8(ascii: "0") && thisChar <= UInt8(ascii: "9")) {
output += "\(Character(UnicodeScalar(UInt32(thisChar))!))"
}
else {
output += String(format: "%%%02X", thisChar)
}
}
return output
}
}
Example usage:
let url = "https://www.google.es".urlEncodedString()
print(url)
Upvotes: 0
Reputation: 4141
You can probably do it this way -
extension String{
func urlEncodedString() -> String {
var output = String()
let source: [UInt8] = Array(self.utf8)
let sourceLen: Int = source.count
for i in 0..<sourceLen {
let thisChar = source[i]
if thisChar == UInt8(ascii: " ") {
output += "+"
}
else if thisChar == UInt8(ascii: ".") || thisChar == UInt8(ascii: "-") || thisChar == UInt8(ascii: "_") || thisChar == UInt8(ascii: "~") || (thisChar >= UInt8(ascii: "a") && thisChar <= UInt8(ascii: "z")) || (thisChar >= UInt8(ascii: "A") && thisChar <= UInt8(ascii: "Z")) || (thisChar >= UInt8(ascii: "0") && thisChar <= UInt8(ascii: "9")) {
output += "\(Character(UnicodeScalar(UInt32(thisChar))!))"
}
else {
output += String(format: "%%%02X", thisChar)
}
}
return output
}
}
Upvotes: 1
Reputation: 5186
Just replace below code (Swift 3.1.1):
func urlEncodedString() -> String {
var output = String()
let source: [UInt8] = UInt8(utf8)
let sourceLen: Int = strlen(CChar(source))
for i in 0..<sourceLen {
let thisChar: UInt8 = source[i]
if thisChar == " " {
output += "+"
}
else if thisChar == "." || thisChar == "-" || thisChar == "_" || thisChar == "~" || (thisChar >= "a" && thisChar <= "z") || (thisChar >= "A" && thisChar <= "Z") || (thisChar >= "0" && thisChar <= "9") {
output += "\(thisChar)"
}
else {
output += String(format: "%%%02X", thisChar)
}
}
return output
}
Upvotes: 0
Reputation: 47896
This code should generate exactly the same result as your Objective-C code. (Should compile and work as expected in both Swift 3 and 4.)
extension String {
var urlEncoded: String {
var output = ""
for thisChar in self.utf8 {
switch thisChar {
case UInt8(ascii: " "):
output.append("+")
case UInt8(ascii: "."), UInt8(ascii: "-"), UInt8(ascii: "_"), UInt8(ascii: "~"),
UInt8(ascii: "a")...UInt8(ascii: "z"),
UInt8(ascii: "A")...UInt8(ascii: "Z"),
UInt8(ascii: "0")...UInt8(ascii: "9"):
output.append(Character(UnicodeScalar(UInt32(thisChar))!))
default:
output = output.appendingFormat("%%%02X", thisChar)
}
}
return output
}
}
print("https://www.google.es".urlEncoded) //->https%3A%2F%2Fwww.google.es
Some points:
You can iterate on each UTF-8 byte with for thisChar in self.utf8
To convert a string literal (actually a UnicodeScalar Literal) to a UInt8
, you can use UInt8(ascii:)
You should better consider using addingPercentEncoding(withAllowedCharacters:)
with proper CharacterSet
and pre/post-processing
Upvotes: 2