swift Using predicate - swift

request.predicate=NSPredicate( format:"lnameID= \(light.valueForKey("lnameID"))",nil);
When using the request.predicate in Swift,it goes wrong.
How to solve the problem in the format " xx "xx" xx" ?

You should not use string interpolation when building predicates. This will give wrong
results or crash at runtime as soon as there are any special characters (like
single or double quotes) in the values.
Better use the %# placeholder, for example:
let lnameID = light.valueForKey("lnameID") as String // assuming that it is a string
request.predicate = NSPredicate(format: "lnameID = %#", lnameID)

You can put escaped quotes around and the escaped variable within the string like so:
request.predicate=NSPredicate( format:"lnameID= \"\(light.valueForKey("lnameID"))\"",nil)
Or you can use a placeholder, %#, where quotes are generated, as seen in Martin R's answer. Using escaped quotes is the more native way to do it in swift.

Related

Why I cannot use \ or backslash in a String in Swift?

I have a string like this in below and I want replace space with backslash and space.
let test: String = "Hello world".replacingOccurrences(of: " ", with: "\ ")
print(test)
But Xcode make error of :
Invalid escape sequence in literal
The code in up is working for any other character or words, but does not for backslash. Why?
Backslash is used to escape characters. So to print a backslash itself, you need to escape it. Use \\.
For Swift 5 or later you can avoid needing to escape backslashes using the enhanced string delimiters:
let backSlashSpace = #"\ "#
If you need String interpolation as well:
let value = 5
let backSlashSpaceWithValue = #"\\#(value) "#
print(backSlashSpaceWithValue) // \5
You can use as many pound signs as you wish. Just make sure to mach the same amount in you string interpolation:
let value = 5
let backSlashSpaceWithValue = ###"\\###(value) "###
print(backSlashSpaceWithValue) // \5
Note: If you would like more info about this already implemented Swift evolution proposal SE-0200 Enhancing String Literals Delimiters to Support Raw Text

How can I read characters of a String with String format in Swift?

I am trying use String(format:, ) for reading some characters from left or right, do we have something for this job?
for example reading 2 characters from left would be: "AB" like this: "%2L#"
my code:
let stringOfText = String(format: "%#", "ABCDEF")
String(format:) is usually to transform a different value type into a string.
Since you already have a string, you don't really need this method.
try:
https://developer.apple.com/documentation/swift/string/2894830-prefix

How do I format a string from a string with %# in Swift

I am using Swift 4.2. I am getting extraneous characters when formatting one string (s1) from another string(s0) using the %# format code.
I have searched extensively for details of string formatting but have come up with only partial answers including the code in the second line below. I need to be able to format s1 so that I can customize output from a Swift process. I ask this because I have not found an answer while searching for ways to format a string from a string.
I tried the following three statements:
let s0:[String] = ["abcdef"]
let s1:[String] = [String(format:"%#",s0)]
print(s1)
...
The output is shown below. It may not be clear, here, but there are four leading spaces to the left of the abcdef string.
["(\n abcdef\n)"]
How can I format s1 so it does not include the brackets, the \n escape characters, and the leading spaces?
The issue here is you are using an array but a string in s0.
so the following index will help you.
let s0:[String] = ["abcdef"]
let s1:[String] = [String(format:" %#",s0[0])]
I am getting extraneous characters when formatting one string (s1) from another string (s0) ...
The s0 is not a string. It is an array of strings (i.e. the square brackets of [String] indicate an array and is the same as saying Array<String>). And your s1 is also array, but one that that has one element, whose value is the string representation of the entire s0 array of strings. That’s obviously not what you intended.
How can I format s1 so it does not include the brackets, the \n escape characters, and the leading spaces?
You’re getting those brackets because s1 is an array. You’re getting the string with the \n and spaces because its first value is the string representation of yet another array, s0.
So, if you’re just trying to format a string, s0, you can do:
let s0: String = "abcdef"
let s1: String = String(format: "It is ‘%#’", s0)
Or, if you really want an array of strings, you can call String(format:) for each using the map function:
let s0: [String] = ["abcdef", "ghijkl"]
let s1: [String] = s0.map { String(format: "It is ‘%#’", $0) }
By the way, in the examples above, I didn’t use a string format of just %#, because that doesn’t accomplish anything at all, so I assumed you were formatting the string for a reason.
FWIW, we generally don’t use String(format:) very often. Usually we do “string interpolation”, with \( and ):
let s0: String = "abcdef"
let s1: String = "It is ‘\(s0)’"
Get rid of all the unneccessary arrays and let the compiler figure out the types:
let s0 = "abcdef" // a string
let s1 = String(format:"- %# -",s0) // another string
print(s1) // prints "- abcdef -"

NSPredicate with regEx, returns wrong result [duplicate]

This question already has an answer here:
regex in swift is not working with this example?
(1 answer)
Closed 4 years ago.
I wrote the following regular expression to validate usernames:
/^[a-zA-Z0-9\\._]+$/
However, when I try to use it, something messes up, since it gives me the wrong result. The input I tried is the same as my SO handle: ilikecode. This is how I apply the regex:
let regex = "/^[a-zA-Z0-9\\._]+$/"
let usernameTest = NSPredicate(format: "SELF MATCHES %#", regex)
print("username is valid", usernameTest.evaluate(with: username), username)
However, the regex always returns false.
Does anybody know how this is possible?
Thanks!
In some languages /.../ is used to delimit a regular expression
pattern, separating the pattern from an action and the options,
for example
if ($userName =~ m/^[a-zA-Z0-9\\._]+$/i)
in Perl. But NSPredicate (or NSRegularExpression) take just a pattern
as argument, without enclosing slashes.
Also the anchors are implicit for the MATCHES operator, and
the [c] option can be used to specify case-insensitive matching:
let regex = "[a-z0-9\\._]+"
let usernameTest = NSPredicate(format: "SELF MATCHES[c] %#", regex)

NSPredicate, with quotes / without quotes

In my iPhone app, I'm reading a csv file. The relevant line is this:
NSString *countrycode = [[[NSString alloc] initWithFormat:#"%#", [arr objectAtIndex:2]]
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
This returns "CN" (which stands for China).
When I do this:
NSLog(#"Manual: %#, country code: %#",#"CN",countryCode);
I get:
Manual: CN, country code: "CN"
One has quotes and the other does not. I don't know why this is.
The reason this is tripping me up is the following:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"countrycode == %# ", #"CN"];
This works fine, and returns China from Core Data.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"countrycode == %# ", countrycode];
This fails to return anything. I am assuming this is because it has quotes around it, or something, although perhaps I am incorrect.
What am I doing wrong here?
Actually the correct way to format a predicate to exclude quotes is the to use %K versus %#. See Predicate Format String Syntax.
Your countryCode variable must have quotes inside of it when it's read back. The first time you assign the literal #"CN" the quotes are removed as they specify that your variable is an NSString. They aren't really inside of the literal string. If you wanted strings inside of the first CN, you'd need to explicitly specify the quotation marks, e.g. #"""CN"""
However, if you want to get rid of any quotations in the second string, you could always do this to the string prior to putting it into your predicate:
[countryCode stringByReplacingOccurrencesOfString:#"""" withString:#""];