Swift: how to suppress interpretation of special characters and provide string literal - ios

The goal is to serialize a Swift object by converting it to a JSON object then converting the JSON object into a JSON string that can be passed over the wire and decoded on the other side.
The problem is producing a valid JSON string.
Newlines must be escaped in a JSON string, but Swift interprets special characters in the escaped string instead of treating the string as a literal.
For example:
let a = "foobar\nhello\nworld"
let escapedString = a.replacingOccurrences(of: "\n", with: "\\n")
print(escapedString)
What gets printed is foobar\nhello\nworld instead of the desired foobar\\nhello\\nworld.
How do you tell Swift to treat a string as a literal and not to interpret special characters within?
UPDATE
As OOPer points out, using debugPrint shows the \\n characters remaining intact.
However, when paired with evaluateJavaScript in WKWebView, the \\n characters are turned into \n, which is the root issue. For example:
let script = "\(callback)(\'\(escapedString)\')"
webView!.evaluateJavaScript(script) { (object: Any?, error: Error?) -> Void in
print("Done invoking \(callback)")
}

There is no unescaped string syntax like in javascript template literals which is probably what you are looking for; maybe they will add it in the future. Unfortunately you therefore have to escape each back slash which sometimes looks very scray, as in your example.
//This is the same as `foobar\nhello\nworld` where each char is a literal
let a = "foobar\\nhello\\nworld"
let escapedString = a.replacingOccurrences(of: "\\n", with: "\\\\n")
//This outputs `foobar\\nhello\\nworld`
print(escapedString)

Maybe you are just mistaking to interpret the output from print.
When you get foobar\nhello\nworld from print(escapedString), escapedString contains 20 characters -- f o o b a r \ n h e l l o \ n w o r l d.
This is a valid JSON string when enclosed between "s.
If you want to check the escaped result in String-literal-like notation, you can use debugPrint:
let a = "foobar\nhello\nworld"
let escapedString = a.replacingOccurrences(of: "\n", with: "\\n")
print(escapedString) //->foobar\nhello\nworld
debugPrint(escapedString) //->"foobar\\nhello\\nworld"
For UPDATE
When using with evaluateJavaScript, you'd better think what is the right code as JavaScript, if you want to represent a JSON escaped string in JavaScript, you would write in .js file (or in <script>...</script>):
someFunc('foobar\\nhello\\nworld');
So, you may need to write something like this:
let a = "foobar\nhello\nworld"
let escapedForJSON = a.replacingOccurrences(of: "\n", with: "\\n")
//In actual code, you may need a little more...
let escapedForJavaScriptString = escapedForJSON.replacingOccurrences(of: "\\", with: "\\\\")
let script = "\(callback)(\'\(escapedForJavaScriptString)\')"
webView!.evaluateJavaScript(script) { (object: Any?, error: Error?) -> Void in
print("Done invoking \(callback)")
}

Related

Combine multiple replacingOccurrences() with Swift

I have a String, I would like to add backslash to specific characters, because I use markdown and I don't wand to add style it's not wanted.
I tried to make a function, and it's working, but it's not efficient I guess:
func escapeMarkdownCharacters(){
let myString = "This is #an exemple #of _my_ * function"
var modString = myString.replacingOccurrences(of: "#", with: "\\#")
modString = modString.replacingOccurrences(of: "*", with: "\\*")
modString = modString.replacingOccurrences(of: "_", with: "\\_")
print(modString) // Displayed: This is \#an exemple \#of \_my\_ \* function
}
I would like to only have one "replacingOccurences" that work for multiple characters. I think I could do that with regex but I didn't figure out how. If you have an idea, please share it with me.
You may use
var modString = myString.replacingOccurrences(of: "[#*_]", with: "\\\\$0", options: [.regularExpression])
With a raw string literal:
var modString = myString.replacingOccurrences(of: "[#*_]", with: #"\\$0"#, options: [.regularExpression])
Result: This is \#an exemple \#of \_my\_ \* function
The options: [.regularExpression] argument enables the regex search mode.
The [#*_] pattern matches #, * or _ and then each match is replaced with a backslash (\\\\) and the match value ($0). Note that the backslash must be doubled in the replacement string because a backslash has a special meaning inside a replacement pattern (it may be used to make $0 a literal string when $ is preceded with a backslash).

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.

I receive an improperly formatted unicode in a String

I am working with a web API that gives me strings like the following:
"Eat pok\u00e9."
Xcode complains that
Expected Hexadecimal code in braces after unicode escape
My understanding is that it should be converted to pok\u{00e9}, but I do not know how to achieve this.
Can anybody point me in the right direction for me develop a way of converting these as there are many in this API?
Bonus:
I also need to remove \n from the strings.
You may want to give us more context regarding what the raw server payload looked like, and show us how you're displaying the string. Some ways of examining strings in the debugger (or if you're looking at raw JSON) will show you escape strings, but if you use the string in the app, you'll see the actual Unicode character.
I wonder if you're just looking at raw JSON.
For example, I passed the JSON, {"foo": "Eat pok\u00e9."} to the following code:
let jsonString = String(data: data, encoding: NSUTF8StringEncoding)!
print(jsonString)
let dictionary = try! NSJSONSerialization.JSONObjectWithData(data, options: []) as! [String: String]
print(dictionary["foo"]!)
And it output:
{"foo": "Eat pok\u00e9."}
Eat poké.
By the way, this standard JSON escape syntax should not be confused with Swift's string literal escape syntax, in which the hex sequence must be wrapped in braces:
print("Eat pok\u{00e9}.")
Swift uses a different escape syntax in their string literals, and it should not be confused with that employed by formats like JSON.
#Rob has an excellent solution for the server passing invalid Swift String literals.
If you need to convert "Eat pok\u00e9.\n" to Eat poké it can be done as follows with Swift 3 regex.
var input = "Eat pok\\u00e9.\n"
// removes newline
input = String(input.characters.map {
$0 == "\n" ? " " : $0
})
// regex helper function for sanity's sake
func regexGroup(for regex: String!, in text: String!) -> String {
do {
let regex = try RegularExpression(pattern: regex, options: [])
let nsString = NSString(string: text)
let results = regex.matches(in: text, options: [], range: NSMakeRange(0, nsString.length))
let group = nsString.substring(with: results[0].range)
return group
} catch let error as NSError {
print("invalid regex: \(error.localizedDescription)")
return ""
}
}
let unicodeHexStr = regexGroup(for:"0\\w*", in: input)
let unicodeHex = Int(unicodeHexStr, radix: 16)!
let char = Character(UnicodeScalar(unicodeHex)!)
let replaced = input.stringByReplacingOccurrencesOfString("\\u"+unicodeHexStr, withString: String(char))
// prints "Eat poké"
print(replaced)
\u{00e9} is a formatting that's specific to Swift String literals. When the code is compiled, this notation is parsed and converted into the actual Unicode Scalar it represents.
What you've received is a String that escapes Unicode scalars in a particlar way. Transform those escaped Unicode Scalars into the Unicode Scalars they represent, see this answer.

String literal as argument for func within println?

Is there anyway to use a string literal as an argument to a function within a println statement.
func greetings(name: String) -> String {
return "Greetings \(name)!"
}
What I was trying to do: (I tried escaping the quotes around Earthling.)
println("OUTPUT: \(greetings("Earthling"))")
You can alternatively do this:
let name = "Earthling"
println("OUTPUT: \(greetings(name))")
And this works too:
println(greetings("Earthling"))
I tried escaping the quotes in the first example but with no luck, its not super important as its only a test, I was just curious if there was a way to do this, using a function call with a string literal as an argument within a print or println statement that contains other text.
From the Apple docs:
The expressions you write inside parentheses within an interpolated
string cannot contain an unescaped double quote (") or backslash (\),
and cannot contain a carriage return or line feed.
The problem is of course not with println but with the embedding of expressions with quotes in string literals.
Thus
let b = false
let s1 = b ? "is" : "isn't"
let s2 = "it \(b ? "is" : "isn't")" // won't compile
However NSLog as a one-liner'' works quite well here
NSLog("it %#", b ? "is" : "isn't")
Note %#, not %s. Try the latter in a playground to see why.

F# GetDigitValue value or construct not valid

I am new to F# and would like to have an advice.
I would like to use the GetDigitValue function.
open System
open System.Drawing
open System.Globalization
let getSubscript ichar =
match ichar with
|1 -> GetDigitValue(843)
| _ -> GetDigitVale(852)
I have the following error: The value or constructor 'getDigitValue" is not defined.
Without further information I can't really tell what you are trying to do.
GetDigitValue is a static method of the CharUnicodeInfo class.
It is used like this:
let testString = "1234567890"
let digitValue = CharUnicodeInfo.GetDigitValue(testString, 3)
This returns the digit value for the 3rd character in the string. It also works with a single character too.
let test = '5'
let digitvalue = CharUnicodeInfo.GetDigitValue(test)
Update:
To get the superscript of a string I think the Numeric value will return this:
let superscriptTwo ="U+00B2"
let numericvalue = CharUnicodeInfo.GetNumericValue(superscriptTwo)
I would like to get the superscript of numbers.
Then I think you want this function that gives a unicode character that is the superscript of the given digit:
let superscriptOf n =
if 0<=n && n<10 then "⁰¹²³⁴⁵⁶⁷⁸⁹".[n] else
invalidArg "n" "Not a single digit number"
Note that F# supports unicode in F# code. You can even use unicode variable names like λ in F# code!

Resources