I've been playing around with Swift, and just came across an issue.
I have the following Dictionary in:
var locations:Dictionary<String,CLLocationCoordinate2D> = ["current":CLLocationCoordinate2D(latitude: lat, longitude: lng) ];
println("current locaition is \(locations["current"])")
but the compiler is complaining about double quotes around current which represent the a key in my dictionary.
I tried escaping it with \ but it wasn't the right way.
Appreciate any help.
Xcode 7.1+
Since Xcode 7.1 beta 2, we can now use quotations within string literals. From the release notes:
Expressions interpolated in strings may now contain string literals. For example, "My name is (attributes["name"]!)" is now a valid expression. (14050788)
Xcode <7.1
I don't think you can do it that way.
From the 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.
You'd have to use
let someVar = dict["key"]
println("Some words \(someVar)")
You can use string concatenation instead of interpolation:
println("Some words " + dict["key"]! + " some more words.")
Just mind the spaces around the + signs.
UPDATE:
Another thing you can do is to use string format specifiers the same way how it was done back in the objective-c days:
println( String(format: "Some words %# some more words", dict["1"]!) )
I've had this problem too with interpolating strings. The best solution I found was just to split it into two lines like so:
let location = locations["current"]
println("current locaition is \(location)")
It may be a bug with Swift. From what I found in the docs, you should be able to use \ to escape quotes.
Swift doesn't accept quote in \(). Therefore you need to separate the one-line code into two.
Here is a blog showing example for Chinese readers:
http://tw.gigacircle.com/321945-1
Since Swift 2.1 you can use double quotes on interpolation. println("current location is \(locations["current"])")
Related
I've been trying to figure out the best way to validate a user entry which is a string with comma separated RGB values. It should only allow strings with no whitespaces and in formats such as these (1,12,123; 225,225,2; 32,42,241...).
I've never used Regex before, but i'm guessing it would be the best solution? I've been playing around on RegexPal and have gotten this string working:
(#([\da-f]{3}){1,2}(\d{1,3}%?,\s?){3}(1|0?\.\d+)\)|\d{1,3}%?(,\s?\d{1,3}%?){2})
However, not having much luck using it in Swift. I get the error "Invalid escape sequence in literal".
Would appreciate any help with using that regex in Swift, or if there's a better regex string/solution to validating the entry. Thanks!
You can use hashtag before the first double quote and after the last double quote in Swift to avoid having to manually add a backslash before any special character. Regarding the regex you are using it would allow the user to enter values above the 255 limit.
The regex below adapted from this post would limit the values from 0-255 and would allow the user enter 1 or more rgb values followed by ";" or "; "
#"^\((((([1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])),){2}(([1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]))(;|; )?){1,}\)$"#
extension StringProtocol {
var isValidRGB: Bool { range(of: #"^\((((([1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])),){2}(([1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]))(;|; )?){1,}\)$"#,
options: .regularExpression) != nil }
}
"(200,55,1)".isValidRGB // true
"(10,99,255; 0,0,10)".isValidRGB // true
"(2,2,2;)".isValidRGB // true
"(2,2,2;2)".isValidRGB // false
"(2,2,2;2,2)".isValidRGB // false
"(2,2,254;0,0,0)".isValidRGB // true
"(2,2,256;0,0,0)".isValidRGB // false
Add the Swift code where you define the RegEx to your question.
The other poster likely has identified the problem. (#manzarhaq, you should really post your reply as an answer so the OP can accept it.)
The backslash is a special character in Swift strings. It tells the compiler that the character next is a special character. If you want a literal backslash, you need 2 backslashes in a row. So your regEx string might look like this:
let regExStrin = "(#([\\da-f]{3}){1,2}(\\d{1,3}%?,\\s?){3}(1|0?\\.\\d+)\\)|\\d{1,3}%?(,\\s?\\d{1,3}%?){2})"
Note that using backslashes this way is common to most languages that derive, even loosely, from C. Swift does have some C in its ancestry.
In many C-like languages, \n is a newline character, \t is a tab character, \f is a form-feed, \" is a quotation mark, and \\ is a literal backslash.
(I don't think the \f form feed character is defined in Swift. That harks back to the days of ASCII driven serial printers.)
How to print all special characters without inserting escape sign before every of them? I have very large textiles with many special characters and I'm looking for something like # in c# which prints string literally as it is
What you're referring to, is called a verbatim string literal in C# and that concept does not translate exactly to Swift.
However, with the introduction of multiline string Literals in Swift 4, you can get close.
let multilineString = """
Here you can use \ and newline characters.
Also single " or double "" are allowed.
"""
For reference, find the grammar of a Swift String literal here.
this is maybe stupid question but I'm new to swift and i actually can't figure this out.
I have API which returns url as string "http:\/\/xxx". I don't know how to store URL returned from API in this format. I can't store it to variable because of backslash.
From apple doc:
...string cannot contain an unescaped backslash (\), ...
Is there any way how to store string like this or how remove these single backslashes or how to work with this?
Thank you for every advice.
You can just replace those backslashes, for example:
let string2 = string1.stringByReplacingOccurrencesOfString("\\", withString: "")
Or, to avoid the confusion over the fact that the backslash within a normal string literal is escaped with yet another backslash, we can use an extended string delimiter of #" and "#:
let string2 = string1.stringByReplacingOccurrencesOfString(#"\"#, withString: "")
But, if possible, you really should fix that API that is returning those backslashes, as that's obviously incorrect. The author of that code was apparently under the mistaken impression that forward slashes must be escaped, but this is not true.
Bottom line, the API should be fixed to not insert these backslashes, but until that's remedied, you can use the above to remove any backslashes that may occur.
In the discussion in the comments below, there seems to be enormous confusion about backslashes in strings. So, let's step back for a second and discuss "string literals". As the documentation says, a string literal is:
You can include predefined String values within your code as string literals. A string literal is a fixed sequence of textual characters surrounded by a pair of double quotes ("").
Note, a string literal is just a representation of a particular fixed sequence of characters in your code. But, this should not be confused with the underlying String object itself. The key difference between a string literal and the underlying String object is that a string literal allows one to use a backslash as an "escape" character, used when representing special characters (or doing string interpolation). As the documentation says:
String literals can include the following special 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 a 1–8 digit hexadecimal number with a value equal to a valid Unicode code point
So, you are correct that in a string literal, as the excerpt you quoted above points out, you cannot have an unescaped backslash. Thus, whenever you want to represent a single backslash in a string literal, you represent that with a \\.
Thus the above stringByReplacingOccurrencesOfString means "look through the string1, find all occurrences of a single backslash, and replace them with an empty string (i.e. remove the backslash)."
Consider:
let string1 = "foo\\bar"
print(string1) // this will print "foo\bar"
print(string1.characters.count) // this will print "7", not "8"
let string2 = string1.stringByReplacingOccurrencesOfString("\\", withString: "")
print(string2) // this will print "foobar"
print(string2.characters.count) // this will print "6"
A little confusingly, if you look at string1 in the "Variables" view of the "Debug" panel or within playground, it will show a string literal representation (i.e. backslashes will appear as "\\"). But don't be confused. When you see \\ in the string literal, there is actually only a single backslash within the actual string. But if you print the value or look at the actual characters, there is only a single backslash in the string, itself.
In short, do not conflate the escaping of the backslash within a string literal (for example, the parameters to stringByReplacingOccurrencesOfString) and the single backslash that exists in the underlying string.
I found I was having this same issue when trying to encode my objects to JSON. Depending on if you're using the newer JSONEncoder class to parse your JSON and you're supporting a minimum of iOS 13, you can use the .withoutEscapingSlashes output formatting:
let encoder = JSONEncoder()
encoder.outputFormatting = .withoutEscapingSlashes
try encoder.encode(yourJSONObject)
Please check the below code.
let jsonStr = "[{\"isSelected\":true,\"languageProficiencies\":[{\"isSelected\":true,\"name\":\"Advance\"},{\"isSelected\":false,\"name\":\"Proficient\"},{\"isSelected\":false,\"name\":\"Basic\"},{\"isSelected\":false,\"name\":\"Below Basic\"}],\"name\":\"English\"},{\"isSelected\":false,\"languageProficiencies\":[{\"isSelected\":false,\"name\":\"Advance\"},{\"isSelected\":false,\"name\":\"Proficient\"},{\"isSelected\":false,\"name\":\"Basic\"},{\"isSelected\":false,\"name\":\"Below Basic\"}],\"name\":\"Malay\"},{\"isSelected\":false,\"languageProficiencies\":[{\"isSelected\":false,\"name\":\"Advance\"},{\"isSelected\":false,\"name\":\"Proficient\"},{\"isSelected\":false,\"name\":\"Basic\"},{\"isSelected\":false,\"name\":\"Below Basic\"}],\"name\":\"Chinese\"},{\"isSelected\":false,\"languageProficiencies\":[{\"isSelected\":false,\"name\":\"Advance\"},{\"isSelected\":false,\"name\":\"Proficient\"},{\"isSelected\":false,\"name\":\"Basic\"},{\"isSelected\":false,\"name\":\"Below Basic\"}],\"name\":\"Tamil\"}]"
let convertedStr = jsonStr.replacingOccurrences(of: "\\", with: "", options: .literal, range: nil)
print(convertedStr)
I've solved with this piece of code:
let convertedStr = jsonString.replacingOccurrences(of: "\\/", with: "/")
To remove single backslash,try this
let replaceStr = backslashString.replacingOccurrences(of: "\"", with: "")
Include a backslash in a string by adding an extra backslash.
I have tried to print it but it just by passes because it's an escaped character.
e.g output should be as follows.
\correct
For that and also future reference:
\0 – Null character (that is a zero after the slash)
\\ – Backslash itself. Since the backslash is used to escape other characters, it needs a special escape to actually print itself.
\t – Horizontal tab
\n – Line Feed
\r – Carriage Return
\” – Double quote. Since the quotes denote a String literal, this is necessary if you actually want to print one.
\’ – Single Quote. Similar reason to above.
Use the following code for Swift 5, Xcode 10.2
let myText = #"This is a Backslash: \"#
print(myText)
Output:
This is a Backslash: \
Now not required to add a double slash to use a single slash in swift 5, even now required slash before some character, for example, single quote, double quote etc.
See this post for latest update about swift 5
https://www.hackingwithswift.com/articles/126/whats-new-in-swift-5-0
var s1: String = "I love my "
let s2: String = "country"
s1 += "\"\(s2)\""
print(s1)
It will print I love my "country"
The backslash character \ acts as an escape character when used in a string. This means you can use, for example, double quotes, in a string by pre-pending them with \. The same also applies for the backslash character itself, which is to say that println("\\") will result in just \ being printed.
How do I remove this backslash?
s = "\""
I have tried s.gsub("\\", "") and that doesn't remove it, it returns the same string.
there's actually no backslash character in your String. The Backslash in your example simply escapes the following double quote and prevent's that it would terminate the string and thereby resulting in a syntax error (unterminated double quote ).
So what you see when you print that string in IRB is actually not the backslash as is, but the backslash in combination with the following dobule quote as an indication that the double quote is escaped. Kind of hard to grasp when you encounter it the first time. Have a look at http://en.wikibooks.org/wiki/Ruby_Programming/Strings#Escape_sequences
long story short: there is no backslash in your string so you can't remove it :)
gsub takes a regular expression as the first parameter. I believe that if you pass it a string, it will first convert it into a regex. This means you need extra escaping:
s.gsub("\\\\", "")
If you use regex notation, you can stop it from doubling up:
s.gsub(/\\/, "")
This is because you don't have to escape twice: once because double-quoted strings need you to escape the \ character, and once because the regular expression requires you to as well.
that's actually an escape quote sign (do a print s to see it)
I'm not sure if this is a solution to YOUR problem, but seeing that this is one of the first SO questions I looked at when trying to solve my problem and have in fact, solved it, here is what I did to fix my problem.
So I had some CSV.read output with a load of \ (backslashes) and unwanted quotation marks.
arr_of_arrays = CSV.read("path/to/file.csv")
processed_csv = arr_of_arrs.map {|t| eval(t)}
the key here is the eval() method.