Invalid escape sequence in literal: "\b" - ios

I need to be able to create a String that is "\b". But when I try to, Xcode throws a compile-time error: Invalid escape sequence in literal. I don't understand why though, "\r" works just fine. If I put "\\b" then that's what is actually stored in the String, which is not what I need - I only need one backslash. To me, this seems to be a Swift oddity because it works just fine in Objective-C.
let str = "\b" //Invalid escape sequence in literal
NSString *str = #"\b"; //works great
I need to generate this string because "\b" is the only way to detect when the user pressed 'delete' when using UIKeyCommand:
let command = UIKeyCommand(input: "\b", modifierFlags: nil, action: "didHitDelete:")
How can I work around this issue?
EDIT: It really doesn't want to generate a String that is only "\b", this does not work - it stays the original value:
var delKey = "\rb"
delKey = delKey.stringByReplacingOccurrencesOfString("r", withString: "", options: .LiteralSearch, range: nil)

The Swift equivalent of \b is \u{8}. It maps to ASCII control code 8, just like \b in Objective C. I've tested this and found it to work fine with UIKeyCommand, in this earlier answer of mine.
Example snippet:
func keyCommands() -> NSArray {
return [
UIKeyCommand(input: "\u{8}", modifierFlags: .allZeros, action: "backspacePressed")
]
}

I don't believe it is supported.
Based on the Swift documentation https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html:
String literals can include the following special Unicode characters:
The escaped special characters \0 (null character), \ (backslash), \t
(horizontal tab), \n (line feed), \r (carriage return), \" (double
quote) and \' (single quote)
An arbitrary Unicode scalar, written as
\u{n}, where n is between one and eight hexadecimal digits
The ASCII for the \b is 8. If you do the following, you'll see these results
let bs = "\u{8}"
var str = "Simple\u{8}string"
println(bs) // Prints ""
println("bs length is \(bs.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))") // Prints 1
println(str) // Prints Simplestring
let space = "\u{20}"
println(space) // Prints " "
println("space length is \(space.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))") // Prints 1
str = "Simple\u{20}string"
println(str) // Prints Simple string
It looks like while ASCII 8 "exists", it is "ignored".

Related

Regex to not allow staring whitespace in string swift ios

I want to create regex thats allows characters numbers and spaces but not at the begning of string , i have created below one but its not working "^\\S.*[^A-Za-z0-9_ ].*".
Swift:
func containsAllowedCharacters(regex: String?, stringToCheck: String) -> Bool {
var isValid = false
if let regex = regex {
let testString = NSPredicate(format: "SELF MATCHES %#", regex)
isValid = testString.evaluate(with: stringToCheck)
}
return !isValid
}
Your pattern, ^\S.*[^A-Za-z0-9_ ].*, matches start of string with ^, then matches any non-whitespace char with \S (note it matches any punctuation, letters and digits), then matches any zero or more chars other than line break chars as many as possbile with .*, then matches any char other than an ASCII letter, digit, _ or space, and then again matches any zero or more chars other than line break chars as many as possbile with .*.
As you see, all the pattern parts match more than you allow. Also, pay attention you actually require at least two chars to be present with this pattern while your code implies you need to support zero length string, too.
You can use
let FileNameRegex = #"^(?!\s)[A-Za-z0-9_\s]*$"#
NOTE: As you are using it with MATCHES in the NSPredicate.evaluate, you do not need the ^ and $ anchors on both ends since MATCHES requires a full string match:
let FileNameRegex = #"(?!\s)[A-Za-z0-9_\s]*"#
let testString = NSPredicate(format: "SELF MATCHES %#", regex)
Note the use of #"..."# notation that makes a raw string literal, where a single backslash is parsed as a literal backslash.
The pattern matches
^ - start of string
(?!\s) - a negative lookahead that matches a location in string that is not immediately followed with a whitespace
[A-Za-z0-9_\s]* - zero or more (due to the * quantifier) ASCII letters, digits, underscores and whitespaces
$ - end of string.
You are looking for lookaheads:
^(?! )[ \w]+$
\w is a short form for [\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\u200c\u200d] (see here and here for more information) as it is used very often, but see #Wiktor's comment for a more precise clarification.
Also,see a demo on regex101.com.

How to replace unicode escape character in Dart

I need to clean up a string that has an escape character but couldn't do so.
Here is my test code:
test('Replace unicode escape character', () {
String originalText = 'Jeremiah 52:1\\u201334';
String replacedText = originalText.replaceAll(r'\\', r'\');
expect(replacedText, 'Jeremiah 52:1\u201334');
});
It fails with an error:
Expected: 'Jeremiah 52:1–34'
Actual: 'Jeremiah 52:1\\u201334'
Which: is different.
Expected: ... miah 52:1–34
Actual: ... miah 52:1\\u201334
Unicode characters and escape characters aren't stored the way you write them when you wrote the string -- they are converted to their own values. This is evident when you run the following code:
print('\\u2013'.length); // Prints: 6
print('\u2013'.length); // Prints: 1
Here, what happened was: the first stored the following characters: '\', 'u', '2', '0', '1', and '3' -- while the latter stored '–' only.
Hence, your attempt to change the first by replacing two slashes \\ with one slashes \ wouldn't work, as the compiler isn't converting your unicode escape characters any longer.
That doesn't mean that you won't be able to convert your unicode codes into unicode characters though. You could use the following code:
final String str = 'Jeremiah 52:1\\u2013340';
final Pattern unicodePattern = new RegExp(r'\\u([0-9A-Fa-f]{4})');
final String newStr = str.replaceAllMapped(unicodePattern, (Match unicodeMatch) {
final int hexCode = int.parse(unicodeMatch.group(1), radix: 16);
final unicode = String.fromCharCode(hexCode);
return unicode;
});
print('Old string: $str');
print('New string: $newStr');

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?

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

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)")
}

Swift regex to match unicodes

I am new to swift and want to match all the unicode strings using regex
For example:
var s="😀 emoji 😀"
When I decoded the above string the result is:
"\ud83d\ude00 emoji \ud83d\ude00"
I want to replace each emoji with say *
In java I used the regex as:
"[\uD800-\uDBFF\uDC00-\uDFFF]" and was working
In swift I am using the same regex but its replacing every character with *
I want the result as * emoji *
Help is highly appreciated
The Unicode code point of the emoji you have shown is U+1F600.
(Unicode 9.0 Character Code Charts - Emoticons)
And your regex pattern (which may work for UTF-16 representation) [\uD800-\uDBFF\uDC00-\uDFFF] matches all non-BMP characters -- U+10000...U+10FFFF, which contains most of all emojis but also contains huge non-emoji characters.
So, as you say "[\uD800-\uDBFF\uDC00-\uDFFF]" was working, the equivalent pattern in NSRegularExpression is "[\\U00010000-\\U0010FFFF]".
var s="😀 emoji 😀"
let regex = try! NSRegularExpression(pattern: "[\\U00010000-\\U0010FFFF]", options: [])
let replaced = regex.stringByReplacingMatchesInString(s, options: [], range: NSRange(0..<s.utf16.count), withTemplate: "*") //->"* emoji *"
(Addition)
To see Unicode code points in your string literal:
s.unicodeScalars.forEach {
print(String(format: "U+%04X ", Int($0.value)))
}
For your example string, I get:
U+1F600
U+0020
U+0065
U+006D
U+006F
U+006A
U+0069
U+0020
U+1F600

Resources