I'm using NSRegularExpression in my Swift code because it needs to run on older platforms. The factory method throws, so we need to trap the error - which does indeed occur in my code (I feed in some crazy patterns). I call it using:
let regex: NSRegularExpression
do {
regex = try NSRegularExpression(pattern: pattern, options: [.caseInsensitive])
} catch {
return false
}
For handling optionals, Swift offers the guard let pattern which makes this much more clear and self-documenting as it exposes the variable to the enclosing scope and one-lines the logic. guard case is also useful. Is there some similar syntactic sugar for throws?
You probably mean
guard let regex = try? NSRegularExpression(...) else { return false }
Related
What is the difference between:
guard let json_data = Data(contentsOf: path) else {return nil}
and
let json_data = try? Data(contentsOf: path)
I dont want to use optional while loading the data into the variable. I want other ways to try it.
Thanks in advance.
The options are:
Your first example, unwrapping it with guard, is missing a try?:
func foo() -> Bar? {
guard let jsonData = try? Data(contentsOf: path) else { return nil }
// if you get here, `jsonData` is not `Optional`
…
}
This will safely unwrap your optional and let you do whatever you want if the unwrapping failed. (In your example, you are returning nil.)
Your second example, yields an optional, which you presumably need to unwrap with an if statement.
func foo() -> Bar? {
let jsonData = try? Data(contentsOf: path)
// jsonData is `Optional` in this example
if let jsonData {
…
} else {
return nil
}
}
We would generally favor the first option over this, where the “early exit” of the guard makes it a little easier to read the code, but there are cases where you might use this pattern.
An option that hasn’t been considered is to actually throw the error (using try instead of try?):
func foo() throws -> Bar {
let jsonData = try Data(contentsOf: path)
// `jsonData` is not `Optional`
…
}
Now, this only passes the buck of handling the error to the caller (i.e., a do-catch block). But it does have a few virtues over the prior two examples, namely that (a) the useful information of the error object is not just discarded, thereby making it easier to diagnose problems during the development process; and (b) you don’t have to return an optional.
Yet another option (to be used only if you know that this will always succeed, e.g., you are reading a well-known file from your bundle that you know must always succeed) is try!, a “force-try”:
func foo() -> Bar {
let jsonData = try! Data(contentsOf: path)
// `jsonData` is not `Optional`
…
}
Now, this will crash if the Data(contentsOf:) can ever fail, so only use this in scenarios where you know that this is impossible.
Personally, I would generally favor option 3 (where I capture what went wrong) in cases where the Data(contentsOf:) might ever plausibly fail at runtime, and I might consider option 4 (where it crashes with a meaningful error message) when I know it is impossible for it to ever fail at runtime. That having been said, more than once I found myself using option 4 and I later regretted not using option 3, simply because there was some weird edge-case that I neglected to consider.
In short, nowadays I tend to defensively catch errors, log the full error in the console and show a nice localized message in the UI (i.e., option 3). I almost never use try?, because if something can fail, it’s rarely a good idea to discard the useful diagnostic information.
It will be better to be optional once you are loading the data to avoid application crash in and problems in case there was no data there. This is consider as a safe feature.
Trying to make this common swift pattern more functional.
for object in objects.allObjects {
guard let _object = object as? SomeTypeOfObject else { continue }
_object.subObject(subObject, objectStateChanged: changedState)
}
I'd love to use something like "any" (instead of map) to get rid of the for loop - like in Kotlin - but that dose not seem to be possible in Swift.
Trying to figure out a way to include the guard in the functional representation of this block.
Feels like I'm missing something. Am I?
Thanks
A common functional pattern is to compactMap and then call the method with side-effect in a forEach. This eliminates the guard entirely:
objects.allObjects // Add `.lazy` if you don’t want to build the intermediary array
.compactMap { $0 as? SomeTypeOfObject }
.forEach { $0.subObject(subObject, objectStateChanged: changedState) }
I am doing the weak strong dance in swift this way:
dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), { [weak self] in
guard let `self` = self else {
return
}
self.doSomething(1)
})
Before this, I was using strongSelf instead of `self`. On a website I've seen that I can use this character ` .
But what does this character do in Swift? Without this I cannot assign to self. Why does this work? Is it a good practice to use it?
A bit of an update (I will not refer here when to use it but rather how).
From Swift 4.2 the use should be like:
guard let self = self else { return }
Using ` is basically based on the compiler bug thus not advised.
For more information there is no better source than this. Explaining all reasoning behind and other considerations.
In short the above is more consistent with other cases seen in the code like:
if let myVariable = myVariable
So does not create confusion/discrepancies.
Swift Programming Language
Presents a note that says the following:
If you need to give a constant or variable the same name as a reserved
Swift keyword, surround the keyword with backticks (`) when using it
as a name. However, avoid using keywords as names unless you have
absolutely no choice.
EDIT:
The way I do this is using any other name for example strongSelf like you previously did. Because in the end, both `self` and strongSelf will be some variable to act upon. So I suggest if we can use some other variable name that is fine.
I have encountered numerous situations where a coder have used the guard keyword. And then later, in a seemingly almost identical situation the same coder in the same code does not use the guard keyword. I am aware that this may be a stupid question, so please don't bash it. When should I use the guard keyword and where shouldn't I?
Here is an example (there are many more). This is part of a script that is requesting data form an API.
//Here I am using guard
guard let json = json else {
//Now I am not using guard
if let error = error {
completion(.Failure(error))
} else {
//Error handling
}
return
}
Why not use the:
if let var1 = var1 {
//Keep on going
} else {
//Don't crash
}
syntax all the time instead of the guard syntax? At first glance it even seems to have more functionality, but I am certain that does not have to be the case.
One great benefit of the guard statement is that you know that if the condition is not satisfied then the execution flow gets stopped.
This is important for several reasons
Unwrapping
You can define unwrapped values which don't need a new scope { ... } to be available
func next(num:Int?) -> Int? {
guard let num = num else { return nil }
return num + 1
}
Readability
When you read the code you know that if the guard condition is not satisfied then the following lines won't be executed.
Semantics
You know a guard statement is there to check conditions required for the following block of code.
But I can replace every guard with an if
Sure. We could also replace every while and for with a goto in some languages. And we could always replace recursion with iteration (and viceversa).
But this doesn't necessarily means it is always a good idea.
Despite we can implement some behaviours with more then one programming "tool", we should still use the one that better fits that specific scenario.
Swift 2.0 added do {} catch {} which can be used like so:
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(params, options: []);
} catch let jsonError as NSError {
print(jsonError);
}
but I've also seen in in my 2.0 converted classes the catch implemented with an underscore:
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(params, options: []);
} catch _ {
}
what makes it especially confusing is why not just provide nothing after catch which is perfectly valid code:
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(params, options: []);
} catch {
}
What is that underscore _, what can I do with it, how would I implement that in my own function signatures? In the previous Swift 1.2 declaration I didn't use the NSError so it makes sense that the conversion is throwing the error away but why use _?
You're asking a question about an automatic conversion. It's just a starting place! Apple doesn't know what you want to do, so they provide a completely minimal neutral catch-all catch block — it does nothing at all, but we compile because there's a catch-all. Obviously if you want to capture the error variable, you will delete the _ and capture the error variable. You might want to do much more, e.g. write a more focused catch block. It's up to you to build on the foundation you've been given.
If the variable declared before the catch block isn't actually used in the following block then Xcode will automatically convert this to an _ since it is not used. So in your example above, if jsonError wasn't actually used in the catch block, Xcode may automatically convert this to _. This isn't just for do {} catch {} but also things such as if let ... { }.
I think because it does this convert with other things too, like the if let ... {}, if they were to not put the _ in these places the code wouldn't actually work. Hence it does _ everywhere to be safe, even though in some places you may not actually need it.