Swift - Capturing closures - Apple's swift programming guide snippet - ios

In Apple's Swift programming guide, "Automatic Reference Counting" section, at "Resolving Strong Reference Cycles for Closures",
This snippet is mentioned:
lazy var someClosure: () -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
}
What is the point of the exclamation mark in the assignment "weak delegate = self.delegate!"?
I mean, why do you care if there is a value or not? In either ways, you will be receiving an optional delegate inside the closure body since delegate is declared weak, which must be optional, and you will have to access it as an optional.
On the other hand, if you know for sure there 'self.delegate' wont be nil when you access it, why not declaring it as unowned?
Therefore, why is the force unwrapping necessary here?
Can someone shed some light on this?

As there is not really any more context in the text around this example the only person who can know for sure is the author or maintainer of the Swift programming guide.
But here are some possible reasons that I can think of (in no particular order)
The author made a mistake (it happens)
It was required in an older version of Swift and the documentation has not been updated (keeping documentation up to date is hard)
The author wanted to make it obvious to others that creating the block if the delegate does not exist is a bug
The author wants to make it easier to track cases when a delegate was deallocated between creating the block and calling it (maybe for analytics purposes?)

Related

Swift 4 Using KVO to listen to volume changes

I just updated to Swift 4 and Xcode 9 and got a (swiftlint) warning for the following code telling me that I should use KVO now:
Warning:
(Block Based KVO Violation: Prefer the new block based KVO API with
keypaths when using Swift 3.2 or later. (block_based_kvo))
The old code:
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
if keyPath == "outputVolume"{
guard let newKey = change?[NSKeyValueChangeKey.newKey] as? NSNumber else {
fatalError("Could not unwrap optional content of new key")
}
let volume = newKey.floatValue
print("volume " + volume.description)
}
}
My attempt to fix:
let audioSession = AVAudioSession.sharedInstance()
audioSession.observe(\.outputVolume) { (av, change) in
print("volume \(av.outputVolume)")
}
Apple claims here that most of the properties should be dynamic (I know that this is AVPlayer and not AVAudioSession). I looked it up but couldn't find any dynamic statements inside AVPlayer properties and was wondering how that could possibly work (If I'm not mistaken those are required for KVO to work).
EDIT:
I'm not certain if it doesn't trigger because it simply doesn't work or if it's due to what I try to archive. In general I'll want to get notified on volume changes triggered by pushing the hardware-volume-rockers.
I assume you're referring to the line:
You can use Key-value observing (KVO) to observe state changes to many of the player’s dynamic properties...
This use of "dynamic" isn't the same thing as Objective-C's #dynamic or Swift's dynamic. The docs just mean "properties that change" in this context, and they're telling you that the AVPlayer is generally very KVO-compliant and intended to be observed that way. "KVO compliant" means it follows the change notification rules. There are many ways to achieve that, both automatic and manual. The docs are just promising that AVPlayer does.
(An important point about Cocoa that distinguishes it from many other systems is that Cocoa handles many things "by convention". There's no way to say in code "this is KVO compliant" and there is no way for the compiler to enforce it, but Cocoa developers tend to be very good about following the rules. When ARC was developed, it relied heavily on the fact that Cocoa developers had for years named methods following very specific rules that indicate how memory management is handled. It just added complier enforcement of the rules Cocoa developers had always followed by hand. This is why Cocoa developers get very noisy about naming conventions and capitalization. There are major parts of Cocoa that rely entirely on following consistent naming rules.)
Remembering that the AVPlayer interface is an Objective-C API that happens to be bridged to Swift, there's no equivalent of the Swift keyword dynamic in that case. That's a keyword that tells Swift that this property may be observed and so its accessors can't be optimized to static dispatch. That's not something Objective-C requires (or can do; all ObjC properties are "dynamic" in this sense).
The Objective-C #dynamic is a completely different thing, only weakly related to KVO (though it comes up in a lot of KVO-heavy contexts like Core Data). It just means "even though you can't find an accessor implementation for this property anywhere, trust me, by the time this runs an implementation will be available." This relies on the ability of ObjC's runtime to generate implementations dynamically or dispatch in programmer-controlled ways (this still kind of exists in Swift by manipulating the ObjC runtime, but it isn't really a "Swift" feature).
As for how KVO works, it's one of the few true "magic tricks" in Cocoa. For a quick intro, see Key-Value Observing Implementation Details. The short version is:
When you observe an object, a subclass for that object is dynamically created (yes, a new class is invented at runtime).
The subclass adds calls to willChangeValue... and didChangeValue... around all calls to the superclass's property accessors.
The object is "ISA-swizzled" to be that new class.
Magic! (Ok, not really magic; it's just code, but it's quite a trick.)
EDIT: The original question never mentioned that it wasn't working. The reason it's not working is because you're not assigning the returned NSKeyValueObservation in a property; you're just throwing it away. I'm surprised there's not a warning about that; I may open a radar.
When the returned NSKeyValueObservation deallocates, the observation goes away, so this creates an observation and immediately destroys it. You need to store it in a property until you want the observation to go away.
Solution by OP.
It needs to be stored in a property. Not a variable, not _ but a property. Otherwise it won't work. Like this:
class YourViewController: UIViewController {
var obs: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
let audioSession = AVAudioSession.sharedInstance()
self.obs = audioSession.observe( \.outputVolume ) { (av, change) in
print("volume \(av.outputVolume)")
}
}
}

Precondition Swift 3

I am following the last conference of Apple about the GCD on this link:https://developer.apple.com/videos/play/wwdc2016-720/?time=33
I got to the point where it speaks of the precondition here: https://developer.apple.com/videos/play/wwdc2016-720/?time=1267, a new feature in Swift 3.
Arrived at this point: https://developer.apple.com/videos/play/wwdc2016-720/?time=1474 is used this:
.register(observer:, queue:)
my question: how this function retains object BusyController?
https://developer.apple.com/videos/play/wwdc2016/720/?time=1550
You ask how this register(observer:queue:) retains BusyController.
First, let's step back: Let's not get lost in the details of his example. He's not saying that it will establish a strong reference, merely that it could, and therefore you should be cautious about just trying to clean up in deinit.
So, how could DataTransform retain BusyController? It simply could maintain a strong reference to its observer. Note, do not conflate this custom register method example with the standard observer methods: They're just saying "imagine that the DataTransform object established a strong reference to BusyController..."
But, as he goes on to say "but you're skilled developers, and you know how to fix this problem; use a weak reference." So, generally, we wouldn't write observation methods that maintained strong references to their observers.
But, as he goes on to say, even if you're good about avoiding strong reference cycles, the object graph can get pretty complicated, so it's not always a good idea to rely upon deinit to clean up. He's advocating for an explicit invalidate process, and possibly using preconditions to test that the object has been invalidated by the time deinit is called.

Swift - why can't lazy properties be readily made read only

Can anyone please explain this comment re lazy properties by neuburg in iOS 9 swift fundamentals book ...
"There are some minor holes in the language: lazy instance properties can’t have setter observers, and there’s no lazy let (so you can’t readily make a lazy instance property read-only)" .... Particularly about no lazy let preventing ability for read only
From Apple documentation:
You must always declare a lazy property as a variable (with the var keyword), because its initial value might not be retrieved until after instance initialization completes. Constant properties must always have a value before initialization completes, and therefore cannot be declared as lazy.
But if you want do get a value lazy from a class/struct and want to be sure that nobody can write back to that value then simply use a func with a return value. Or like milos said - a private(set) on a lazy property. (which is not the same thing) So somehow everything is possible. :)

Why are there weak _and_ unowned? Why can we just not always use weak?

I just read the ARC section in the Swift book and a few other related posts concerning weak and unowned references.
After my readings, I do have a clear understanding on what they are and in what situations each of them are to be used (see also this SO post which gives a great explanation of this).
However, I fail to understand why Apple even came up with these two solutions? Essentially, from a MM perspective, both come down to not creating a strong reference to the referred object (i.e. not increasing its retainCount). So, why even bother and provide two MM primitives here?
Now, developers need to understand when to use which of the two, and Apple did a great job in explaining the different scenarios, but they didn't say why. Wouldn't it have been simpler to e.g. only provide weak so that developers don't need to dig into the docs and understand the different use cases?
I guess, another way to phrase the question is, why at all should we use unowned, except for Apple telling us so? At least from a MM standpoint, this wouldn't make a difference and using weak where according to the docs we should use unowned wouldn't create a memory leak?!
The difference is in the optionality of variables. Like Apple says in the Unowned References section of the link you provided:
Unlike a weak reference, however, an unowned reference is assumed to
always have a value. Because of this, an unowned reference is always
defined as a nonoptional type.
The usage of this is more visible in a closure block. Here you do not have to use ? operator or get a reference on the object if you use it inside the closure.
Instead of writing this:
UIView.animateWithDuration(0.2) {
[weak self]
() -> Void in
self?.view.layoutIfNeeded()
}
However, if you can be sure that the reference to self will not be released before the animation and you can simply write unowned and do not have to use the ? operator or unwrap it with an if let statement:
UIView.animateWithDuration(0.2) {
[unowned self]
() -> Void in
self.view.layoutIfNeeded()
}
#Kádi's answer about weak variables being optional is correct, but incomplete.
Weak and unowned have a difference in meaning outside of Swift's Optional semantics. A weak reference is more accurately named an auto-zeroing weak reference. The system knows about an object stored in a weak variable, and when the object is deallocated, goes to the extra work to zero out the value. As a consequence of that, weak variables are optionals in Swift.
Unowned pointers are not memory managed at all. They are a raw memory pointer that can take any value. (They can still be typed to point to a particular type of structure, so they aren't always "raw" in the way a C void pointer is raw.) Unowned pointers are useful for pointing to malloc'ed memory, pointer arithmetic, and the like. Declaring a pointer type as unowned basically tells the compiler "Don't worry about it. I know what I'm doing." The burden is then on you to make sure the pointer is always valid, before you try to dereference it, and also manage the memory behind the pointer yourself.

What does this block mean in Swift - Alamofire?

This is a code block in Alamofire/Manager.swift:
It is inside a class named "public class Manager"
public static let sharedInstance: Manager = {
let configuration: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = Manager.defaultHTTPHeaders
return Manager(configuration: configuration)
}()
Obviously, this is "let something equals the closure," but what I don't get is what does the "()" in the end of the line mean?
To defer the execution of the code? How? (It seems to me that the execution won't be deferred as it has the "()"? And I am wondering why this is not causing the existing of a memory circle? It returns the Manger itself and the returned new instance will also do the same, returning a new self...
Why not a key word "lazy"?
I have a strange feeling that i've seem this usage somewhere else too. I'm learning Swift for 60 days now. Am I fast or slow? How to be a iOS developer also?(I mean how to be a real one, not enroll the program)
For now I'm kind of confused and reading all the source code I could get. Sometimes I feel the official docs and Xcode sucks and I don't know how to read a source code scratch. Any tips and advice?
This initializes sharedInstance with the result of the closure (without the parens at the end it would just initialize it to the closure itself) It's a standard syntax for initializing variable with an initializer too complex for a simple expression. In this multiple statements are required so that the HTTPAdditionalHeaders can be initialized.
Okay, I've made a mistake. The trick lies that the sharedInstance used a key word "static" This is common, but in python, which I am most familiar with, do not use this key word.
According to the official guide:
“You can also define properties that belong to the type itself, not to any one instance of that type. There will only ever be one copy of these properties, no matter how many instances of that type you create. These kinds of properties are called type properties.”
Apple Inc. “The Swift Programming Language”. iBooks. https://itun.es/cn/jEUH0.l
the answer is at the session name "Setting a Default Property Value with a Closure or Function": https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID231

Resources