Reputation: 961
I have a ViewController containing TextFields and I would need to send those values to a dedicated HTTP service. My main concern comes from the encoding type, as this app is in French and may contain some accents ('é', 'è', etc,...) but also I need to format correctly my fields as it may contain spaces as well....
I tried to use different ways but I still have a wrong encoding on the server side.
here is a sample of my code:
let url_to_request = "http://11.22.33.44:8080/SRV/addRepertoire"
var params = "owner=\(User.sharedInstance.email)&adresse=\(adresse.text!)&nom=\(nom.text!)&telephone=\(telephone.text!)&commentaires=\(commentaires.text!)"
//trying to encode in ISO-8859-1
let dt = NSString(CString: params, encoding: NSISOLatin1StringEncoding)
//preparing string to be used in a NSURL
let final_url = dt!.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
print("URL loadRepertoire: \(url_to_request+"?"+final_url!)")
for instance, field "nom" contains "bébé" which is encoded "b%C4%82%C5%A0b%C4%82%C5%A0" whereas my server is expecting "b%E9b%E9"
EDIT2:
I tried to use the following:
let url_to_request = "http://11.22.33.44:8080/SRV/addRepertoire"
let params = "owner=\(User.sharedInstance.email)&adresse=\(adresse.text!)&nom=\(nom.text!)&telephone=\(telephone.text!)&commentaires=\(commentaires.text!)"
let tmp_url = url_to_request + "?" + params
let final_url = tmp_url.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
print("URL addRepertoire: \(final_url)")
but the result remains:
b%C3%83%C2%A9b%C3%83%C2%A9, diplayed bébé instead of bébé
Upvotes: 1
Views: 731
Reputation: 1164
For Objective-C :
- (NSString *)stringByAddingPercentEncodingForISOLatin1 {
NSCharacterSet *allowedCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.~=&"];
NSData *data = [self dataUsingEncoding:NSISOLatin1StringEncoding];
if (data) {
NSMutableString *result = [@"" mutableCopy];
const char *bytes = [data bytes];
for (NSUInteger i = 0; i < [data length]; i++)
{
unsigned char ch = (unsigned char)bytes[i];
if (ch >= 0x80 || ![allowedCharacterSet characterIsMember:ch]) {
[result appendFormat:@"%%%02X", ch];
} else {
[result appendFormat:@"%c", ch];
}
}
return [result copy];
}
return nil;}
Upvotes: 0
Reputation: 513
Here is a solution in Swift 4:
extension String {
// Url percent encoding according to RFC3986 specifications
// https://tools.ietf.org/html/rfc3986#section-2.1
func urlPercentEncoded(withAllowedCharacters allowedCharacters:
CharacterSet, encoding: String.Encoding) -> String {
var returnStr = ""
// Compute each char seperatly
for char in self {
let charStr = String(char)
let charScalar = charStr.unicodeScalars[charStr.unicodeScalars.startIndex]
if allowedCharacters.contains(charScalar) == false,
let bytesOfChar = charStr.data(using: encoding) {
// Get the hexStr of every notAllowed-char-byte and put a % infront of it, append the result to the returnString
for byte in bytesOfChar {
returnStr += "%" + String(format: "%02hhX", byte as CVarArg)
}
} else {
returnStr += charStr
}
}
return returnStr
}
}
Usage:
"aouäöü!".urlPercentEncoded(withAllowedCharacters: .urlQueryAllowed,
encoding: .isoLatin1)
// Results in -> "aou%E4%F6%FC!"
Upvotes: 0
Reputation: 47876
stringByAddingPercentEncodingWithAllowedCharacters
always uses UTF-8 representation, so I'm afraid you may need to do it yourself.
extension String {
func stringByAddingPercentEncodingForISOLatin1() -> String? {
let allowedCharacterSet = NSCharacterSet(charactersInString:
"0123456789"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "_-.~"
+ "=&" //You'd better remove this and encode each param.
)
if let data = self.dataUsingEncoding(NSISOLatin1StringEncoding) {
var result = ""
for i in 0..<data.length {
let ch = UnsafePointer<UInt8>(data.bytes)[i]
if ch >= 0x80 || !allowedCharacterSet.characterIsMember(unichar(ch)) {
result += String(format: "%%%02X", ch)
} else {
result.append(UnicodeScalar(ch))
}
}
return result
} else {
return nil
}
}
}
"bébé".stringByAddingPercentEncodingForISOLatin1()! //->"b%E9b%E9"
Upvotes: 5