What is the usage of guard let self = self else { return } - swift

I just learned how to use the Result type recently from Sean Allen's video, and I get the idea of using it. However, while I was writing a code, there is a line I don't understand.
The line is 87 in the picture (or this -> guard let self = self else { return } )
At first, I was just doing the same stuff as he did, but I wonder why he add the line in the code. I think he wrote it because the self can be nil and wanted to make sure if the self is not nil and return from the function if it gets nil.
And my question is
when or in which situation the self can be nil?
and
if self gets nil, I think it won't trigger the following line (the one for checking the result), so both of the updateUI function and presentGFAlert... function won't be triggered and nothing shows up on the screen, right?

Its because the closure defines its reference to self as being weak, this means if self is released, the block closure will not prevent self from being destructed, getting a reference count of 0. You can deal with this in the code in the closure, by using all references to self as self?, but this mean self could became nil mid way being executed, by using guard let self = self else { return }, you are saying if execution gets here, I want a strong reference to it, so the object will continue being available until the execution of the of the closure complete, basically all or nothing. This in the past could only happen with multi threaded apps, but with apples new async thread model making cooperative threads more common this is potential more possible.

Your concern is correct. Because getFollowers is an async task, user could go back to previous screen while the task is running. In that case, self could be nil and the return is okay.
On the other hand, to make sure there's no problem with completion block of getFollowers task, self will be captured as strong reference, that could cause memory leak even if user already leave that screen.
He uses weak self to prevent that happens.

Related

Swift Closures: Must Capture Lists Be Exhaustive?

Suppose I have a Swift class like this:
#objc final MyClass : NSObject
{
let classPropertyString = "A class property"
func doStuff()
{
let localString = "An object local to this function"
DispatchQueue.global(qos: .userInitiated).async { [classPropertyString] in
// Do things with 'classPropertyString' and 'localString'
}
}
}
My question is: when I write a capture list, am I responsible for EXHAUSTIVELY listing all the things to which I want the closure to hold a strong reference?
In other words, if I omit localString from my capture list (as I've done here), will the closure still automatically capture a strong reference to it or am I in for a bad time?
There are several minor quirks with your question that make it tricky to answer clearly, but I think I understand the underlying concern, and the short answer is "no." But your example is impossible, so the answer is "it's impossible." And if it were possible, there'd be no strong reference (nor would there be a need for one), so the question still would be kind of "it's impossible." Even so, let's walk through what's going on here.
First, closure can't reference localString unless it's reassigned somehow in the comment inside doStuff(). closure is assigned at a level where localString is not in scope. Closures can only capture variables that are in scope when they are assigned, not when they're called. But let's go back to the original version of this question, before it was edited. That version did have the case you're describing:
#objc final myClass : NSObject
{
let classPropertyString = "A class property"
func doStuff()
{
let localString = "An object local to this function"
DispatchQueue.global(qos: .userInitiated).async { [classPropertyString] in // (1)
// Do things with 'classPropertyString' and 'localString'
}
// (2)
}
}
There's no problems here. classPropertyString is copied into the closure, avoiding any retain loops. localString is referenced by the closure, and so it's preserved as long as the closure exists.
Because you listed classPropertyString in the capture list, it is evaluated at point (1) and copied into the closure. Because you implicitly captured localString, it is treated as a reference. See Capture Lists in the Swift Programming Language Reference for some excellent examples of exactly how this works in different cases.
In no case (*) will Swift allow the underlying storage for something you're using in a closure to disappear behind your back. That's why the typical concern is excessive retains (memory leaks) rather than dangling references (crashes).
(*) "In no case" here is a lie. There are several ways that Swift will allow it, but almost all of them involve "Unsafe" which is your warning about that. The major exception is unowned, and of course anything involving ! types. And Swift is not typically thread-safe, so you need to be careful about that...
The last comment about thread-safety is a place where the subtle distinctions between implicit and explicit captures can really matter. Consider this case where you modify an implicitly captured value on two queues:
func doStuff() -> String
{
var localString = "An object local to this function"
DispatchQueue.global(qos: .userInitiated).async {
localString = "something else"
callFunction(localString)
}
localString = "even more changes"
return localString
}
What happens in that case? Good grief, never do that. I believe it's undefined behavior and that localString could be anything including corrupted memory, at least in the most general case (it might be defined behavior for calling .async; I'm not sure). But don't do it.
But for your normal cases, there is no reason to explicitly capture local variables. (I sometimes wish Swift had gone the C++ way and said it was required, but it isn't.)
Ok, one more way implicit and explicit are different that might drive home how they work. Consider a stateful closure like this (I build these pretty often):
func incrementor() -> () -> Int {
var n = 0
return {
n += 1
return n
}
}
let inc = incrementor()
inc() // 1
inc() // 2
inc() // 3
let inc2 = incrementor()
inc2() // 1
See how the local variable n is captured by the closure, and can be modified after it goes out of scope. And see how inc2 has its own version of that local variable. Now try that with explicit capture.
func incrementor() -> () -> Int {
var n = 0
return { [n] in // <---- add [n]
n += 1 // Left side of mutating operator isn't mutable: 'n' is an immutable capture
return n
}
}
Explicit captures are copies and they're immutable. Implicit captures are references, and so have the same mutability as the thing they reference.

Trouble delaying function with variables passed to it in swift 4

I'm very new to swift and am having trouble with calling this function again on the 6th line after a delay, Xcode is telling me that
Argument of '#selector' does not refer to an '#objc' method, property, or initializer
I know what the problem is and have tried searching around but haven't been able to make anything work.
#objc func attemptToIdentify(_ user: String) {
if manager.status == .connected {
socket.emit("identify", user) //This functions correctly
} else {
print(manager.status, "... will attempt subscription in 1 second")
self.perform(#selector(attemptToIdentify(user)), with: nil, afterDelay: 1)
}
}
The problem is that attemptToIdentify(user) is a call. This is not the place for a call; you need a selector, i.e. the name of a function. So just put attemptToIdentify. If you need to pass something, you can pass it in the with parameter.
Even better, don't use perform:afterDelay: at all. If the idea is to add a delay to a call, just use asyncAfter (or my delay encapsulation of it).

How can you mark a method that it is fatal, like `fatalError`?

We have a special logging function that represents a particular type of crash, and as such, internally it calls fatalError. However, unlike fatalError, when we use it in a guard statement, it still complains we haven't exited the scope of the guard.
I checked the source code and fatalError returns -> Never so I tried that, but that didn't work either. I also didn't see any attributes applied to it that may be telling the compiler 'this is the end of the road'.
So is it possible to have your own fatalError-like method?
func myFatalError(memberName:String = #function) -> Never {
let message = "Failed in \(memberName)"
NSLog(message)
fatalError(message)
}
As pointed out by others, the issue was something on my machine specifically. The following (returning 'Never') works as expected.
func myFatalError() -> Never {
print("Doing something fatal")
}

Can I make self.entity a non optional for certian functions in a GKComponent using swift?

I'm using the GameplayKit entity component system to develop a game.
I have a number of GKComponent. Most of the instance functions require that self.entity is not nil, but it is an optional, as a component may be initialised before being attached to an entity.
If I "do things properly", I understand I should use guard (or if) to check that self.entity is not nil, for each function where I require it. This adds a chunk of extra code for each function, and in addition a function may require the entity has specific components to function.
Problem statement:
For some functions in a GKComponent, I want to specify that the function requires self.entity is not nil, and has some specific components, without needing a number of guard or if statements which bulks up my code.
Things I've tried:
I tried creating an extension to GKComponent.
The extension contains a function which throws an error if the entity is nil, returns true if it is not nil.
import Foundation
import GameplayKit
extension GKComponent {
enum ComponentExtensionError: Error {
case hasNoEntity
}
func requiresEntity() throws -> Bool {
if (self.entity != nil) {
return true
} else {
throw ComponentExtensionError.hasNoEntity
}
}
}
GKComponent function:
func setTileWalls () {
try? self.requiresEntity()
# Some stuff
}
This compiles, but doesn't solve my problem, as I still have to access the entity as self.entity?.somefunc().
I figured now I know that self.entity is not nil, I could proceed to set it as unwrapped...
func setTileWalls () {
try? self.requiresEntity()
self.entity = self.entity!
# Some stuff
}
But alas, you cannot SET self.entity.
I considered I could in stead modify the extension to return the entity, and then do something like...
func stTileWalls () {
guard let entity = self.requiresEntity() else { throw }
}
but then I'd need to modify each functions code to use entity rather than self.entity. I don't feel like this is optimal solution, but maybe an acceptable one.
My ideal solution would be to be able to call a function which checks that self has an entity, and some components, making them non optional for the scope, and throwing an error if any are nil.
Why? I'm frustrated by entity and any component always being optional (when I know it shouldn't be). If I understand correctly, "doing things properly" requires that I guard and throw (or return maybe?). Syntactically I feel it looks ugly and I feel like I'm missing something in terms of fixing this in an elegent way with Swift.
There is no easy solution to solve this issue if you want a safe solution that requires less boilerplate code than unwrapping an optional.
Throwing an error instead of returning nil is definitely a bad idea, since handling an error requires even more boilerplate code than safely unwrapping an optional.
You cannot override existing variables types, so you cannot make GKComponent.entity non-optional either.
Use guard statements for optional binding, that way you can minimise the boilerplate code for unwrapping the value.

What is the advantage of force unwrapping an optional? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
If a variable is an Optional what is the advantage of force unwrapping it.
class Button: UIButton {
var title: UILabel? = nil
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override init(frame: CGRect) {
super.init(frame: frame)
}
func addTitle(text: String) {
title = UILabel(frame: CGRect())
self.addSubview(title!)
}
}
let a: Button = Button(frame: CGRect())
a.addTitle("Hello World")
// Case 1
a.title?.text = "Goodbye"
// Case 2
a.title!.text = "Hello World"
Question
In Case 1 I know its safer but is there any performance improvements or reason to use Case 2?
So, if we know that Case 1 is more safe why should we ever use Case 2?
Performance-wise there might be a very to very very small no difference between forced and optional binding/chaining, as the optional version might have an extra if somewhere.
But nonetheless when talking about performance issues, the performance bottlenecks come from other parts of the code, like non-improved loops, lots of accumulation NSNotification's sent in a short amount of time, unnecessary redraws of the UI, etc.
So it's best to stay on the safer side and use optional binding/casting/chaining and focus on the parts of the code that adds actual performance penalties. Even if at the time you write the code the value is guaranteed to be non-nil, in the future in might be that the conditions will change and you'll suddenly end up with crashes that you didn't expect they'll occur.
Swift has made it very easy to deal with optionals, without writing a lot of boilerplate code, you should take advantage of those features.
As per the comment, your example isn't actually valid. Putting that aside: force unwrapping means "I work only with a concrete value; I want to fail immediately if I don't have one". So it's often preferable to proceeding through that section of code with a nil value and then having some other problem sometime later once the causal nexus has been substantially eroded.
So: it allows you to be explicit about who owns responsibility for guaranteeing that a value is present.
Good (or at least defensible) reasons to use implicitly unwrapped Optionals, or to force unwrap an Optional using !:
#IBOutlets: These are normally implicitly unwrapped for a couple of reasons. You don't want to have to manually unwrap them every time you access them. But more importantly, if your outlets aren't hooked up right, you want to know immediately.
Other instances where you make a conscious decision that you want the app to crash if a value is nil. For example, if you are instantiating a view controller from a storyboard and it is required to be a particular subclass of UIViewController called MyViewController in order for your app to function at all, you might force cast it using return vc as! MyViewController. That way you discover right away that something is off.
Honestly, that's it, as far as I can tell. Just my own approach, but I reserve the ! for declaring #IBOutlets. Otherwise, 99.999% of the time I unwrap with if let or guard, or ? in an an optional chaining situation. There are other ways to know that the value is nil. If the optional fails to unwrap, print a message to the console telling you that it failed. To me, a short descriptive message is easier to debug than a crash and an unexpectedly found nil while unwrapping an optional value error. If I want the program to fail, I can still use fatalError with a descriptive message:
guard let x = someOptional else { fatalError("someOptional is nil in awakeFromNib.") }
By reserving ! for #IBOutlets, every time I get one of those unexpectedly found nil while unwrapping an optional value errors I know exactly where to look to find the source of my problem. I look at my #IBOutlet connections in interface builder. Sticking to that policy, and using other tools to identify other values that are nil when they shouldn't be, works for me.
Some alternatives (avoid force unwrapping !). Try these out using an non-nil value of a as well as when a contains nil.
var a: String? = nil
a = "Hello World"
// Case 1 : nil coalescing operator
print(a ?? "a has value nil, let's not unwrap it!")
// Case 2 : if-let clause
if let a = a {
print(a)
}
else {
print("a has value nil, let's not unwrap it!")
}
// Case 3 : guard-let-else clause
func foo(a: String?) {
guard let a = a else {
print("a has value nil, let's not unwrap it!")
return
}
print(a)
}
foo(a)