Why doesn't CFStringEncodings have UTF8 in Swift? - ios

I am trying to create a percent encoded string in Swift so I can safely send text as a GET request. I found some Objective C code which I am trying to convert to Swift. I've written the following Swift code:
CFURLCreateStringByAddingPercentEscapes(nil,
CFStringRef(encodedString), nil,
CFStringRef("/%&=?$#+-~#<>|\\*,.()[]{}^!"),
kCFStringEncodingUTF8)
There is no kCFStringEncodingUTF8 in Swift ... If you right click the CFStringEncodings source you see there is a million things in there but no UTF8. I don't understand. How can I use the UTF8 string encoding in this situation?
EDIT : I found a way to encode a string but I still don't understand what happened to kCFStringEncodingUTF8

The UTF-8 string encoding is defined as
enum CFStringBuiltInEncodings : CFStringEncoding {
// ...
case UTF8 /* kTextEncodingUnicodeDefault + kUnicodeUTF8Format */
// ...
}
and can be used as
let orig = "a/b(c)"
let escaped = CFURLCreateStringByAddingPercentEscapes(nil, orig, nil,
"/%&=?$#+-~#<>|\\*,.()[]{}^!",
CFStringBuiltInEncodings.UTF8.rawValue)
println(escaped)
// a%2Fb%28c%29
As mentioned by #Zaph in a comment, stringByAddingPercentEncodingWithAllowedCharacters might
be easier to use:
let charset = NSCharacterSet(charactersInString: "/%&=?$#+-~#<>|\\*,.()[]{}^!").invertedSet
let escaped = orig.stringByAddingPercentEncodingWithAllowedCharacters(charset)
or use one of the pre-defined character sets from
Creating a Character Set for URL Encoding.

kCFStringEncodingUTF8 has been replace in Swift with: UTF8.
There is a new NSString method added in iOS7 that takes a character set and a number of specialized character sets have been added and of course you can create specialized character sets. There is very little reason to use CFURLCreateStringByAddingPercentEscapes any more. See this: SO Answer

Related

Swift URL.path changes encoding of utf-8 characters

Why does converting a String to an URL in Swift 4.2 and then converting the URL back to a String using url.path change the encoding of special characters like german umlauts (ä, ö, ü), even if I use a utf-8 encoding?
I wrote some sample code to show my problem. I encoded the strings to base64 in order to show that there is a difference.
I also have a similar unsolved problem with special characters and swift here.
Sample Code
let string = "/path/to/file"
let stringUmlauts = "/path/to/file/with/umlauts/testäöü"
let base64 = Data(string.utf8).base64EncodedString()
let base64Umlauts = Data(stringUmlauts.utf8).base64EncodedString()
print(base64, base64Umlauts)
let url = URL(fileURLWithPath: string)
let urlUmlauts = URL(fileURLWithPath: stringUmlauts)
let base64Url = Data(url.path.utf8).base64EncodedString()
let base64UrlUmlauts = Data(urlUmlauts.path.utf8).base64EncodedString()
print(base64Url, base64UrlUmlauts)
Output
The base64 and base64Url string stay the same but the base64Umlauts and the base64UrlUmlauts are different.
"L3BhdGgvdG8vZmlsZQ==" for base64
"L3BhdGgvdG8vZmlsZQ==" for base64Url
"L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdMOkw7bDvA==" for base64Umlauts
"L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdGHMiG/MiHXMiA==" for base64UrlUmlauts
When I put the base64Umlauts and base64UrlUmlauts strings into an online Base64 decoder, they both show /path/to/file/with/umlauts/testäöü, but the ä, ö, ü are different (not visually).
stringUmlauts.utf8 uses the Unicode characters äöü.
But urlUmlauts.path.utf8 uses the Unicode characters aou each followed by the combining ¨.
This is why you get different base64 encoding - the characters look the same but are actually encoded differently.
What's really interesting is that Array(stringUmlauts) and Array(urlUmlauts.path) are the same. The difference doesn't appear until you perform the UTF-8 encoding of the otherwise exact same String values.
Since the base64 encoding is irrelevant, here's a more concise test:
let stringUmlauts = "/path/to/file/with/umlauts/testäöü"
let urlUmlauts = URL(fileURLWithPath: stringUmlauts)
print(stringUmlauts, urlUmlauts.path) // Show the same
let rawStr = stringUmlauts
let urlStr = urlUmlauts.path
print(rawStr == urlStr) // true
print(Array(rawStr) == Array(urlStr)) // true
print(Array(rawStr.utf8) == Array(urlStr.utf8)) // false!!!
So how is the UTF-8 encoding of two equal strings different?
One solution to this is to use precomposedStringWithCanonicalMapping on the result of path.
let urlStr = urlUmlauts.path.precomposedStringWithCanonicalMapping
Now you get true from:
print(Array(rawStr.utf8) == Array(urlStr.utf8)) // now true

How to add Unicode escape sequence in Localizable.strings?

How can a Unicode escape sequence be added to a string in Localizeable.strings file if the string is casted to NSString?
Here is one (ugly) example:
// Localized string: "\u{200F}Number %#" = "\u{200E}Number %#";
let string = NSMutableAttributedString(string: NSString(format: NSLocalizedString("Number %#", comment: "") as NSString, aNumber as NSNumber)) as String
From this question I understand that the problem is the incompatible escape sequences of Localizeable.strings and NSString.
Adding the unicode characters directly is Localizeable.strings file is not an option because I need to insert bidirectional semantics markers that are not printable characters. They would also be lost in most translation programs.
How can I work around that?

What kind of encoding is this ? And what script should I use to decode this?

I have an encode string which I have to convert to a form which has HTML tags and display it in a webview. The encoded data I have is of this format :-
Having+a+pet+is+quite+like+parenting%2C+you+just+cannot+stand+the+chance+being+away+from+them.+Still%2C+very+often+it+occurs+that+you+cannot+have+your+pets+around+everywhere+so+you+need+to+shelter+them+elsewhere+for+a+while.+But+at+the+end+of+the+day%2C+one+must+admit+that+it+is+pretty+hard+to+trust+anyone+with+our+furry+babies.+Who+knows+them+better+than+us%2C+their+habits%2C+eating+orders%2C+temperaments+and+socialization+tendencies%3F%0D%0A%0D%0AIt+is+because+of+this+very+reason+that+we+at+%3Ca+href%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%22+target%3D%22_blank%22+rel%3D%22noopener%22%3EWhat%92s+Up+Noida+are+sharing%3C%2Fa%3E+with+you+the+list+of+5+pet+boarding+facilities+which+you+can+actually+trust.%0D%0A%3Ch4%3E%3Cstrong%3EThe+Dog+Resorts%2C+Noida+%3C%2Fstrong%3E%3C%2Fh4%3E%0D%0AAt+the+Dog+Resort+Noida%2C+be+assured+that+your+pet+will+be+cared+for+by+thorough+professionals.+%A0They+resort+boasts+of+a+10%2C000+sq.+ft.+premises+area+where+about+5000+sq+.ft+is+wide+open+green+area+to+make+your+pet+stay+playful+and+cheering.+The+best+aspect+about+the+place+is+that+there+is+complete+medical+care+and+behavioral+apprehending+of+pets+as+they+have+a+dedicated+team+of+veterinary+doctors%2C+dog+trainers%2C+and+other+pet+care+expertise.%0D%0A%0D%0A%3Ca+href%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%2Fblog%2Fwp-content%2Fuploads%2F2017%2F06%2FDog-resort-noida.png%22%3E%3Cimg+class%3D%22aligncenter+wp-image-4902+size-full%22+src%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%2Fblog%2Fwp-content%2Fuploads%2F2017%2F06%2FDog-resort-noida.png%22+alt%3D%22Dog+resort+noida%22+width%3D%221052%22+height%3D%22326%22+%2F%3E%3C%2Fa%3E%0D%0A%0D%0A%3Cstrong%3EAddress%3A%A0+Sector+112%2C+Noida%3C%2Fstrong%3E%0D%0A%3Cstrong%3E+Contact%3A+9911782646%3C%2Fstrong%3E%0D%0A%3Ch4%3E%3Cstrong%3EBest+Pet+Boarding+%3C%2Fstrong%3E%3C%2Fh4%3E%0D%0AThey+are+indeed+one+of+the+highly+rated+and+positively+reviewed+pet+boarding+facilities+in+Noida.+Not+just+for+dogs+but+they+have+a+friendly+providence+of+pet+care+and+day+boarding+services+for+other+pets+like+fish%2C+bird%2C+guinea+pig%2C+hamster%2C+cat%2C+and+others+as+well.%A0+The+idea+of+creating+is+%91no-cage%92+free+space+for+beloved+pets+was+developed+by+Kaveri+Rana+Bhardwaj+and+Yashraj+Bhardwaj.+At+the+Best+Pet+Boarding%2C+the+emphasis+is+on+making+your+pet+socialize+and+have+a+free+will+of+wandering+in+wide+space.+They+believe+in+the+unique+concept+of+letting+in+a+trained+dog+which+said+to+be+their+%91alpha%92+among+other+pet+dogs%2C+this+maintains+the+decorum+all+the+time.%0D%0A%0D%0A%3Ca+href%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%2Fblog%2Fwp-content%2Fuploads%2F2017%2F06%2Fbest-pet-boarding.jpg%22%3E%3Cimg+class%3D%22aligncenter+wp-image-4903+size-full%22+src%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%2Fblog%2Fwp-content%2Fuploads%2F2017%2F06%2Fbest-pet-boarding.jpg%22+alt%3D%22best+pet+boarding+noida%22+width%3D%22960%22+height%3D%22489%22+%2F%3E%3C%2Fa%3E%0D%0A%0D%0A%3Cstrong%3EAddress%3A+B+14+1+Omicron+2%2C+Greater+Noida%3C%2Fstrong%3E%0D%0A%3Cstrong%3E+Phone%3A+09711951179%3C%2Fstrong%3E%0D%0A%3Ch4%3E%3Cstrong%3EPet+Home+Affairs+Day+Boarding+%3C%2Fstrong%3E%3C%2Fh4%3E%0D%0A%3Ca+style%3D%22font-size%3A+14px%3B+font-family%3A+%27Open+Sans%27%2C+Arial%2C+sans-serif%3B+color%3A+%2319232d%3B+text-decoration-line%3A+underline%3B%22+href%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%2Fblog%2Fwp-content%2Fuploads%2F2017%2F06%2Fpet-home-affairs-day-care.jpg%22%3E%3Cimg+class%3D%22alignright+wp-image-4906+size-full%22+style%3D%22font-size%3A+14px%3B%22+src%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%2Fblog%2Fwp-content%2Fuploads%2F2017%2F06%2Fpet-home-affairs-day-care.jpg%22+alt%3D%22pet+boarding+in+noida%22+width%3D%22350%22+height%3D%22263%22+%2F%3E%3C%2Fa%3E%0D%0A%0D%0APet+Home+Affairs+enjoys+a+sterling+reputation+in+pet+care+industry+and+is+one+of+the+remarkable+services+in+Noida.+At+the+boarding%2C+there+are+professionals+who+understand+the+needs+of+your+pet+and+also+your+preferences+about+the+specific+services+you+need+for+your+pet.+Pet+care+system+is+well+scheduled+for+meal+and+medicine+timings+and+under+the+care+of+pet+care+experts+here.%0D%0A%0D%0A%3Cstrong%3EAddress%3A%A0+Supertech+Capetown%2C+Sector+74%2C+Noida.%3C%2Fstrong%3E%0D%0A%3Cstrong%3E+Phone%3A+09873204636%3C%2Fstrong%3E%0D%0A%3Ch4%3E%3Cstrong%3EClean+Cute+%3C%2Fstrong%3E%3C%2Fh4%3E%0D%0AWith+their+10%2C000+sq.+ft+wide+space+of+Dog+day+care+and+pet+holiday+home%2C+Clean+Cute+is+known+to+serve+all+sizes%2C+kinds%2C+breeds%2C+and+age+of+pets.+They+are+biggest+and+best+boarding+facility+not+only+in+Noida+but+also+in+NCR.+Clean+Cute+is+managed+by+a+highly+skilled+dog+handling+team+offering+pet+grooming+services%2C+recreational+activities%2C+health+care%2C+therapies%2C+pet+parenting+counseling%2C+dog+behavior+management%2C+skin+care%2C+dog+rehabilitation+and+actually%2C+what+not.%0D%0A%0D%0A%3Ca+href%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%2Fblog%2Fwp-content%2Fuploads%2F2017%2F06%2FBoarding-Large-File.jpg%22%3E%3Cimg+class%3D%22aligncenter+wp-image-4907+size-large%22+src%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%2Fblog%2Fwp-content%2Fuploads%2F2017%2F06%2FBoarding-Large-File-1024x682.jpg%22+alt%3D%22dog+boarding+in+noida%22+width%3D%22702%22+height%3D%22468%22+%2F%3E%3C%2Fa%3E%0D%0A%0D%0A%26nbsp%3B%0D%0A%0D%0A%3Cstrong%3EAddress%3A%A0+Sector+112%2C+Noida%3C%2Fstrong%3E%0D%0A%3Cstrong%3E+Phone%3A+08076548163%3C%2Fstrong%3E%0D%0A%3Ch4%3E%3Cstrong%3EGoDogee+Pet+services+%3C%2Fstrong%3E%3C%2Fh4%3E%0D%0AGoDogee+is+one+of+the+India%92s+leading+pet+care+services+providing+pet+day+care%2C+pet+hotel%2C+pet+grooming%2C+pet+vaccination%2C+pet+treatment%2C+pet+mating+and+other+interesting+and+unique+sort+of+services.%0D%0A%0D%0A%3Cimg+class%3D%22aligncenter+size-full+wp-image-4905%22+src%3D%22https%3A%2F%2Fwww.whatsuplife.in%2Fnoida%2Fblog%2Fwp-content%2Fuploads%2F2017%2F06%2Fgodogee.jpg%22+alt%3D%22%22+width%3D%221920%22+height%3D%22790%22+%2F%3E%0D%0A%0D%0A%3Cstrong%3EAddress%3A+J-10%2C+Noida+Rd%2C+H+Block%2C+Sector+8%2C+Noida%3C%2Fstrong%3E%0D%0A%3Cstrong%3E+Phone%3A+09910664343%3C%2Fstrong%3E
What kind of format is this and how do I convert it into text with html tags ?
I'm currently using this method but I'm getting a nil return value :
func urlDecode(_ htmlString: String) -> String {
var decodedURL = htmlString.replacingOccurrences(of: "+", with: " ")
decodedURL = decodedURL.removingPercentEncoding!
return decodedURL
}
So you are getting nil, which means that there is something in your string that is invalid. How could we find out what? Well it's certainly not spaces, so let's break your string into "words":
var decodedURL = htmlString.replacingOccurrences(of: "+", with: " ")
let chunks = decodedURL.components(separatedBy: " ")
and now try to decode each "word" and see which ones fail:
for chunk in chunks
{
let decoded = chunk.removingPercentEncoding
if decoded == nil
{
print("\(chunk)")
}
}
this outputs:
rel%3D%22noopener%22%3EWhat%92s
%A0They
%2F%3E%3C%2Fa%3E%0D%0A%0D%0A%3Cstrong%3EAddress%3A%A0
well.%A0
%91no-cage%92
%91alpha%92
here.%0D%0A%0D%0A%3Cstrong%3EAddress%3A%A0
%2F%3E%3C%2Fa%3E%0D%0A%0D%0A%26nbsp%3B%0D%0A%0D%0A%3Cstrong%3EAddress%3A%A0
India%92s
Now removingPercentEncoding decodes UTF-8, so checking each of those % sequences to see if they are valid UTF-8 shows that %91, %92 & %A0 are not. However they are valid Windows-1252 encodings - single curly quotes and the non-breaking space.
So you need to decode the string as Windows-1252 not UTF-8. Time for you to look in the documentation...
HTH
From apple,
A new string with the percent-encoded sequences removed, or nil if the
receiver contains an invalid percent-encoding sequence.You must call
this method only on strings that you know to be percent-encoded.
Calling this method on strings that are not percent-encoded can lead
to misinterpreting a percent character as the beginning of a
percent-encoded sequence.
You get nil because removingPercentEncoding does not recognize some of your percent encoding. I pasted it onto online parser and find out that %A0 and %92 seem to be suspicious.

Encode String/NSString to Code Page 850 Format

I need to encode a regular string (String or NSString) to a Code Page 850 format.
There's an external String enconding who supports this format (It's called dosLatin1 in the CFStringEncoding enum). I don't know if it's can really do the work, but it's the only reference that I found to Code Page 850 in the whole iOS documentation.
How can I use the CFStringEnconding to convert a "regular" string to a string at a CP850 format? Is it the best way to do it?
If you can get by with CP 1252 which is the "modern" replacement for 850, then you can use Swift String's built in conversion. Otherwise, you can try using Core Foundation's conversion method.
let swiftString = "This is a string"
// Easy way -- use Swift String plus "modern" CP 1252 eoncding to get a block of data. Note: does not include BOM
if let data = swiftString.data(using: .windowsCP1252, allowLossyConversion: true) {
print(data) // Do something with the resulting data
}
// The more thorough way to use CP 850 (enum value = 1040) -- use Core Foundation. This will produce a BOM if necessary.
let coreFoundationString = swiftString as CFString
let count = CFStringGetLength(coreFoundationString) * 2
var buffer = [UInt8](repeating: 0, count: count)
let resultCount = CFStringGetBytes(coreFoundationString as CFString, CFRangeMake(0, CFStringGetLength(coreFoundationString)), 1040, 0x41, true, &buffer, count, nil)
print(buffer)

What is the iOS proper URL encoding of "+" character?

Is there seriously not a way natively to URL Encode the value of a query string parameter that has a "+" character in it?
e.g.
me+blah#domain.net
to
me%2Bblah%40#domain.net?
I tried solutions like posted in these other questions, but those do not properly encode that email.
Swift - encode URL
How do I URL encode a string
A swift solution would be preferred as that is what I am working in at the moment, but I am capable of translating Objective-C Code to swift code for the most part.
Specifically I am trying to x-www-form-urlencoded encode query string values in the body of POST request.
let email = "me+blah#domain.net"
let output = CFURLCreateStringByAddingPercentEscapes(nil, email as NSString, nil, ":/?#!$&'()*+,;=" as NSString, CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding))
// output = "me%2Bblah%40domain.net"
CFURLCreateStringByAddingPercentEscapes doesn't escape + or # by default, but you can specify it (as I did along with other characters, in the ":/?#!$&'()*+,;=" string).
Edit: If you want output to be a Swift string:
let output = (CFURLCreateStringByAddingPercentEscapes(nil, email as NSString, nil, ":/?#!$&'()*+,;=" as NSString, CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) as NSString) as String
println(("me+blah#domain.net" as NSString)
.stringByAddingPercentEncodingWithAllowedCharacters(
NSCharacterSet.alphanumericCharacterSet()))
Output:
Optional("me%2Bblah%40domain%2Enet")
In Objective-C:
NSString *encodedString =
["me+blah#domain.net" stringByAddingPercentEncodingWithAllowedCharacters:
[NSCharacterSet alphanumericCharacterSet]];

Resources