How to compare string in swift4 - swift

i wanna solve below error
Thanks for help

As the error states you cannot compare a String (mycheck) with an array of Any (localMsg), you must compare the string directly with something like
if let localMsg = oDict_Fail["message"] as? String, localMsg == mycheck {
NSLog("True")
} else {
NSLog("False")
}
Here we first try to access the oDict_Fail dictionary with the key message, if it exists try to cast it as a String and if it is successful only then do the comparison, if any of this fails the else branch will be executed.
You can read more about optional binding here.

Related

How to get value of a NSSingleObjectArrayI

func responseDataHandler(data: NSDictionary) {
let temperature_c = data.value(forKeyPath: "data.current_condition.temp_C")
DispatchQueue.main.async{
self.Temperature.text = temperature_c as? String
}
}
I have the above code where I am accessing a weather API which returns data in the form of an NSDictionary to this function. I need to access the value in temperature_c which when I try to print it, it says that it is: Optional(<__NSSingleObjectArrayI 0x600002147fd0>(
25
)
). Temperature is the outlet for label on my storyboard which I want to take on the value of 25 however as written now, it doesn't work and I have tried everything to try and access the value in the Single Object Array but nothing is working. I found this stack overflow question that was similar but it doesn't work for my situation because I keep getting the error that temperature_c is of type any and doesn't have subscripts.
The issue is that you can't cast to String an array, you should try to convert it to [String]. So could change your code to:
self.Temperature.text = (temperature_c as? [String])?.first ?? "Not available"
Let's go step by step:
temperature_c as? [String] tries to convert the NSDictionary to a String array which is the expectable type.
Since the previous step may return nil we have to use optional chaining ?. If we got a valid array using first return the the arrays first element.
Since both previous steps can return nil we can use nil coalescing operator to return a default value. In this case I use "Not available" but you can set any value.
You could write it in a more verbose way like this:
var text2Display2 = "Not available"
if let theArray = temperature_c as? [String] {
if let element = theArray.first {
text2Display2 = element
}
}
self.Temperature.text = text2Display2

Swift: if is let redundancy

I just joined a project that has a lot of existing code. The previous programmer was perhaps unfamiliar with Swift or began development in the early stages of the Swift language. They seemed to be using the if let statement in an odd way. They seemed to want to use the statement as a if is let. Before I edit the code I would like to know if there is any valid use for this:
// In JSON parser
if value is String, let string = value as? String {
document.createdBy = string
}
First checking if value is of type String seems redundant to me. Doesn't Swift check for this in the let string = value as? String portion of the statement?
QUESTION
Why would this need to be checked twice? Or would there be a reason for this?
You're correct, this is redundant. If value is not a string, then value as? String would return nil, and the conditional binding would fail.
To check the type, and not use the casted result:
if value is String {
// Do something that doesn't require `value` as a string
}
To check the type and use the result:
if let value = value as? String { // The new name can shadow the old name
document.createdBy = value
}
Doing both makes no sense.

Retrieve original argument name in function

I have a function that takes a dictionary key (parsed from a JSON file) and returns the value if it can be cast as a string, or an empty string if it can't be cast or doesn't exist. The function itself works fine, but I want to have it log a warning if the value is invalid/missing and I'm not sure what the best way to do it is. I know I could just pass the text of the key as a second argument, but the function is going to be running many times so I was hoping for something more elegant. Is it possible to retrieve the original argument/key from within the function, or might there be some better way of doing this?
let someDict = [String:Any]()
func getStringObject (fromKey: Any?) -> String {
if let object = fromKey as? String {
return object
} else {
print("Invalid or missing value for ???, using default.") // want to print the original argument or at least the key string
return ""
}
}
let someString = getStringObject(someDict["someInvalidKey"]) // should print someDict["someInvalidKey"] or someInvalidKey

swift using guard and typechecking in one line

I like using guard and came across the situation where I want to use where for a typecheck as well:
guard let status = dictionary.objectForKey("status") as! String! where status is String else { ...}
xCode complains correctly that it's always true.
My goal is to have an unwrapped String after the guard in one line.
How can I do this?
Probably you want this?
guard let status = dictionary["status"] as? String else {
// status does not exist or is not a String
}
// status is a non-optional String
When you use as! String! you tell Swift that you know that the object inside your dictionary must be a String. If at runtime the object is not a String, you let Swift throw a cast exception. That is why the where part of your check is not going to fail: either the status is going to be a String, or you would hit an exception prior to the where clause.
You can do an optional cast instead by using as? operator instead of as!. Coupled with guard let, this approach produces
guard let status = dictionary.objectForKey("status") as? String else { ... }
... // If you reached this point, status is of type String, not String?

How can I test if an integerForKey is equal to nil? Using NSUserDefaults

So far, I have a function that tries to see if someone already has a code, and if they do not already have one, then it would generate one for them.
func checkID() -> Int{
if (NSUserDefaults.standardUserDefaults().integerForKey("Code") != nil) {
}
else{
var code = Int(arc4random_uniform(1000000000))
NSUserDefaults.standardUserDefaults().setInteger(code, forKey: "Code")
}
return NSUserDefaults.standardUserDefaults().integerForKey("Code")
}
I get an error message when I try to to say NSUserDefaults.standardUserDefaults().integerForKey("Code") != nil
The error message I get is "Type 'Int' does not conform to protocol 'NilLiteralConvertible'"
What can I do to try to get around this? What am I doing wrong?
The integerForKey always returns a value. If nothing's there, just 0.
So you should check like that:
if let currentValue = NSUserDefaults.standardUserDefaults().objectForKey("Code"){
//Exists
}else{
//Doesn't exist
}
The short answer is "you can't." There's no way to tell if a zero result for integerForKey represents a stored zero value, or no value.
Christian's answer of using objectForKey (which returns an optional) and optional binding is the correct answer.
Edit:
It would be quite easy to add an extension to UserDefaults with a function that returned an Optional Int:
extension UserDefaults {
func int(forKey key: String) -> Int? {
return object(forKey: key) as? Int
}
}
(I suspect that if Apple were designing the Foundations framework today, using Swift, integer(forKey:) would return an Optional(Int).)
You should be able to remove the '!= nil'. For instance,
if (NSUserDefaults.standardUserDefaults().integerForKey("Code")) {
}
else{
var code = Int(arc4random_uniform(1000000000))
NSUserDefaults.standardUserDefaults().setInteger(code, forKey: "Code")
}
return NSUserDefaults.standardUserDefaults().integerForKey("Code")
Simply retrieving the value of the key should return false if the integer is not found.