Treehouse Intermediate Course - Part 13 (Closures 5)
OK so I wasn't able to code on the coach back but a bit of closures before bed! Let's go!
Start Time - 21:28
Throwing From Inside A Closure
Start Time - 21:28
Throwing From Inside A Closure
extension Int {
func apply(_ value: Int, operation: (Int, Int) -> Int) -> Int {
return operation(self, value)
}
}
So this extension gives the function of adding or another operator with an integer.
10.apply(12) { $0 + $1 }
That's all good! But with something like divide, there would be an error!
Right before we go any further let's just review what Pasan has shown...
extension Int {
func apply(_ value: Int, operation: (Int, Int) throws -> Int) -> Int {
do {
return try operation(self, value)
} catch {
}
}
}
We have now the 'throws' keyword in the top line, as there may be an error. The do and try keywords are part of the error handling code. Catch block is empty at the moment... An issue is that we don't have the error code to use to show an error has occurred. Yes! I knew he would create an enum for this custom error. Also here is how the code looks with the resolution - to use ANOTHER throws keyword in the function declaration part...
extension Int {
func apply(_ value: Int, operation: (Int, Int) throws -> Int) throws -> Int {
return try operation(self, value)
}
}
So much simpler in terms of the error handling part of it.
do {
try 10.apply(0) {
if $1 == 0 {
throw MathError.divideBy0
} else {
return $0 / $1
}
}
} catch MathError.divideBy0 {
print("Error")
}
So above is the testing of errors - another part of error handling.
Rethrowing An Error
Rethrows - use in conjunction with closures that can throw errors. This keyword shows that the outer function becomes a throwing function only if an error occurs in the current scope...
Well, the code that had an error on Pasan's code worked fine. So probably a case of a Swift update!
OK that was pretty confusing. I'm leaving rethrowing for now and cracking on to the last video!
Memory Considerations
class NetworkSessionManager {
typealias CompletionHandler = () -> Void
var completionHandlers: [CompletionHandler] = []
func dataTask (with handler: @escaping CompletionHandler) {
completionHandlers.append(handler)
}
}
One of the key bits here is the @escaping keyword. It means that the closure is allowed to escape. It needs to go BEFORE the signature. Pasan doesn't go into more detail. Something about asynchronous code.
Fibonacci example..
This is all very confusing. Pasan is using lots of technical terms without clear explanation.
class Fibonacci {
var value: Int
init(value: Int) {
self.value = value
}
lazy var fibonacci: () -> Int = { [unowned self] in
// Some temporary variables.
var a = 0
var b = 1
// Add up numbers to the desired iteration.
for _ in 0..<self.value {
let temp = a
a = b
b = temp + b
}
return a
}
deinit {
print("\(value) is being deinitialized. Memory deallocated")
}
}
let f = Fibonacci(value: 7)
f.fibonacci()
All code from Pasan (copied from Teacher's Notes).
One point is that you don't want reference cycles - they clog up memory, cause confusion.... so deinit is used.
Weak vs unowned -
We use weak when the other instance has a shorter lifetime. Delegate - used as weak while parent object survives. Clear as mud to be honest!
Good thing is that Pasan says don't worry! Seriously, there will be opportunities to see this in practice more. For now, I get the idea that we want to avoid reference cycles and there are times to use deinit, along with using weak/unowned and other certain keywords. But no use in doing more reading on something I need to actually be using in practice first!
Finish Time - 22:06 (38 minutes)
A short but useful little session. Closures are done! I have a MUCH better understanding of these now, in terms of syntax, use and purpose. Definitely feeling more confident. Next time I think I'm going to do one of the Xcode projects as I've spent a while on generics/closures all within playgrounds. So that will be tomorrow morning at some point!
Comments
Post a Comment