Swift Completion Block - swift

I want to achieve the following :
In classB, to reload my database after adding 1 object. reloadDatabase() is called within the completionBlock.
In classB, reloadDatabase() will call getObjects() in classA to get the most updated list of database objects and pass to objectList in classB
Question: How do i ensure that whenever i call getObjectList() in classB, i will always get the most updated list? From my understanding, my objectList might not be update in reloadDatabase() block. I could be calling getObjectList() when reloadDatabase() haven't reach the completion block yet (objectList is still the old objectList).
I am pretty new to closures and blocks. Any guidance is greatly appreciated!
class classA: NSObject {
func addThisObject(object: RLMObject, completionBlock: () -> ())){
...
completionBlock()
}
func getObjects (completionBlock: ((list: [RLMObject]) -> ())){
var recordList = [RLMObject]()
...
completionBlock(list: recordList)
}
}
class classB: NSObject {
var objectList = [RLMObject]()
func addObject (object: RLMObject) {
classA().addThisObject(object, completionBlock: {() -> () in
self.reloadDatabase()
})
}
func reloadDatabase() {
classA().getObjects{(list) -> () in
self.objectList = list
}
}
func getObjectList() -> [RLMObject] {
return objectList
}
}

From your snippets it seems to me there is no asynchronous calls, so you won't be able to call getObjectList() before reloadDatabase() block. Closures are not asynchronous if you don't use them with something that is (e.g. GCD).
If you have asynchronous calls, but they are not in the snippets, then getObjectList() can be called while reloadDatabase() is being executed. Then you have few options:
Remove asynchronous calls
Use serial queue for your methods
Add boolean variable updateInProgress and check it in getObjectList() - how to do it
Ignore the fact that data may be outdated - it is correctness vs speed trade.
Let your database inform its clients that something changed

In your question, you don't say whether you'll be calling any of these functions from different threads. So when you call addObject() in classB, execution wouldn't even continue until the database has been reloaded and objectList was updated.
Using closures and blocks does not automatically imply that code will be executed on a different context.

Related

What's difference between `add(_)` and `add(_) async`?

I don't understand what's the difference between add(_) and add(_) async method. Like the below code, the MyActor has two add methods and one of them uses async keyword. They can exist at the same time. If I comment out the second add method it will output AAAA. If both add methods exist at the same time, output "BBBBB"。
actor MyActor {
var num: Int = 0
func add(_ value: Int) {
print("AAAAA")
num += value
}
func add(_ value: Int) async {
print("BBBBB")
num += value
}
}
let actor = MyActor()
Task {
await actor.add(200)
print(await actor.num)
}
Supplementary:
With the second add method commented out, I defined let actor = MyActor() outside Task and I noticed the add method signed as add(_:). If move let actor = MyActor() inside Task the add method signed as add(_:) async
The difference emerges inside the actor, for example
actor MyActor {
func addSync(_ value: Int) {
}
func addAsync(_ value: Int) async {
}
func f() {
addSync(0)
}
func g() async {
addSync(0)
await addAsync(0)
}
}
In the actor method f and g you can call addSync synchronously. While outside the actor, you need always call an actor method with the await keyword as if the method is asynchronous:
func outside() async {
let actor = MyActor()
await actor.addSync(0)
}
Async in Swift allows for structured concurrency, which will improve the readability of complex asynchronous code. Completion closures are no longer needed, and calling into multiple asynchronous methods after each other is a lot more readable.
Async stands for asynchronous and can be seen as a method attribute making it clear that a method performs asynchronous work. An example of such a method looks as follows:
func fetchImages() async throws -> [UIImage] {
// .. perform data request
}
The fetchImages method is defined as async throwing, which means that it’s performing a failable asynchronous job. The method would return a collection of images if everything went well or throws an error if something went wrong.
How async replaces closure completion callbacks
Async methods replace the often seen closure completion callbacks. Completion callbacks were common in Swift to return from an asynchronous task, often combined with a Result type parameter. The above method would have been written as followed:
func fetchImages(completion: (Result<[UIImage], Error>) -> Void) {
// .. perform data request
}
Defining a method using a completion closure is still possible in Swift today, but it has a few downsides that are solved by using async instead:
You have to make sure yourself to call the completion closure in each possible method exit. Not doing so will possibly result in an app waiting for a result endlessly.
Closures are harder to read. It’s not as easy to reason about the order of execution as compared to how easy it is with structured concurrency.
Retain cycles need to be avoided using weak references.
Implementors need to switch over the result to get the outcome. It’s not possible to use try catch statements from the implementation level.
These downsides are based on the closure version using the relatively new Result enum. It’s likely that a lot of projects still make use of completion callbacks without this enumeration:
func fetchImages(completion: ([UIImage]?, Error?) -> Void) {
// .. perform data request
}
Defining a method like this makes it even harder to reason about the outcome on the caller’s side. Both value and error are optional, which requires us to perform an unwrap in any case. Unwrapping these optionals results in more code clutter which does not help to improve readability.

What's the difference between the two closure

I tried comment and uncomment the activity() in the following code. I found when I commented the activity() the result in playground would just show "play tennis" once. However it would show twice if I uncommented activity(). What's the difference between the two statements?
class Baby {
var name = "peter"
var favoriteActivity: (() -> ())!
func outsideActivity(activity: #escaping () -> ()) {
//activity()
favoriteActivity = activity
}
}
var cuteBaby = Baby()
cuteBaby.outsideActivity {
print("play tennis")
}
cuteBaby.favoriteActivity()
This is what’s going on:
Consider this method:
func outsideActivity(activity: #escaping () -> ()) {
//activity()
favoriteActivity = activity
}
All that does is save the closure in the favoriteActivity property
Thus, when you do:
// create `Baby` instance
var cuteBaby = Baby()
// this method saves closure in `favoriteActivity`, but doesn’t call it
cuteBaby.outsideActivity {
print("play tennis")
}
// this now calls the closure
cuteBaby.favoriteActivity()
All the outsideActivity method does is save the closure in a property called favoriteActivity.
Thus you see one print statement.
However, now consider this method:
func outsideActivity(activity: #escaping () -> ()) {
activity()
favoriteActivity = activity
}
This actually calls the closure before saving it in the property.
So, when you do:
// create `Baby` instance
var cuteBaby = Baby()
// this method both calls the closure and then also saves it in `favoriteActivity`
cuteBaby.outsideActivity {
print("play tennis")
}
// this now calls the saved closure a second time
cuteBaby.favoriteActivity()
In this case, you’ll see your print statement being called twice.
That’s why the first rendition calls the closure only once, whereas the second calls the closure twice.
Usually when you pass a closure to a method, you either (a) call the closure from within the method (perhaps in some completion handler or the like); or (b) save the closure in some property so you can call it later.
So, this second example is very unusual, where outsideActivity both calls the closure itself and saves that closure in some property so you can call it again later. You usually do one or the other, but not both.

Invoke code in extension on object deinit?

In Swift (I'm using 4.1), is there a way to do some clean-up in an extension when an object is being destructed? I have in mind the kind of code that would go in deinit(), but an extension can't declare deinit(). (Besides which, if several extensions needed to do this, there would be multiple deinit() declarations.)
I did not find a way to exactly get what you want, but maybe this code will help. I have never tried it, so maybe use it more as an inspiration. In a nutshell, it allows you to add bits of code that will excute on deinitialization.
/// This is a simple object whose job is to execute
/// some closure when it deinitializes
class DeinitializationObserver {
let execute: () -> ()
init(execute: #escaping () -> ()) {
self.execute = execute
}
deinit {
execute()
}
}
/// We're using objc associated objects to have this `DeinitializationObserver`
/// stored inside the protocol extension
private struct AssociatedKeys {
static var DeinitializationObserver = "DeinitializationObserver"
}
/// Protocol for any object that implements this logic
protocol ObservableDeinitialization: AnyObject {
func onDeinit(_ execute: #escaping () -> ())
}
extension ObservableDeinitialization {
/// This stores the `DeinitializationObserver`. It's fileprivate so you
/// cannot interfere with this outside. Also we're using a strong retain
/// which will ensure that the `DeinitializationObserver` is deinitialized
/// at the same time as your object.
fileprivate var deinitializationObserver: DeinitializationObserver {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.DeinitializationObserver) as! DeinitializationObserver
}
set {
objc_setAssociatedObject(
self,
&AssociatedKeys.DeinitializationObserver,
newValue,
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
}
/// This is what you call to add a block that should execute on `deinit`
func onDeinit(_ execute: #escaping () -> ()) {
deinitializationObserver = DeinitializationObserver(execute: execute)
}
}
How it works
Now let's assume you have your object, let's call it A and you want to create some code inside an extension, you can use onDeinit to add your clean-up code like this:
extension A {
func someSetup() {
// Do your thing...
onDeinit {
/// This will be executed when A is deinitialized
print("Execute this")
}
}
}
You can also add it from outside the extension,
let a = A()
a.onDeinit {
print("Deinitialized")
}
Discussion
This is different than what you want in that instead of definition a function (deinit) you need to call one. But anyway in protocol extensions, you can never really use the underlying object's life cycle, so it should be okay for most cases.
I am not sure about the order of execution between A's deinit and the DeinitializationObserver's deinit. You might need to drop the assumption that A is still in memory when you write the code inside the closure.
If you need more than one onDeinit you can update the associated object to retain an array of DeinitializationObserver
In my code, I usually use ReactiveCocoa's Lifetime for this kind of things. However, it is more complicated than what I wrote here. Instead, it looks like they swizzle the dealloc selector. If you're interested you can take a look inside - https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/ReactiveCocoa/NSObject+Lifetime.swift

Swift #escaping and Completion Handler

I am trying to understand 'Closure' of Swift more precisely.
But #escaping and Completion Handler are too difficult to understand
I searched many Swift postings and official documents, but I felt it was still not enough.
This is the code example of official documents
var completionHandlers: [()->Void] = []
func someFunctionWithEscapingClosure(completionHandler: #escaping ()->Void){
completionHandlers.append(completionHandler)
}
func someFunctionWithNoneescapingClosure(closure: ()->Void){
closure()
}
class SomeClass{
var x:Int = 10
func doSomething(){
someFunctionWithEscapingClosure {
self.x = 100
//not excute yet
}
someFunctionWithNoneescapingClosure {
x = 200
}
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
completionHandlers.first?()
print(instance.x)
I heard that there are two ways and reasons using #escaping
First is for storing a closure, second is for Async operating purposes.
The following are my questions:
First, if doSomething executes then someFunctionWithEscapingClosure will executing with closure parameter and that closure will be saved in global variable array.
I think that closure is {self.x = 100}
How self in {self.x = 100} that saved in global variable completionHandlers can connect to instance that object of SomeClass ?
Second, I understanding someFunctionWithEscapingClosure like this.
To store local variable closure completionHandler to global variable 'completionHandlerswe using#escaping` keyword!
without #escaping keyword someFunctionWithEscapingClosure returns, local variable completionHandler will remove from memory
#escaping is keep that closure in the memory
Is this right?
Lastly, I just wonder about the existence of this grammar.
Maybe this is a very rudimentary question.
If we want some function to execute after some specific function. Why don't we just call some function after a specific function call?
What are the differences between using the above pattern and using an escaping callback function?
Swift Completion Handler Escaping & Non-Escaping:
Assume the user is updating an app while using it. You definitely want
to notify the user when it is done. You possibly want to pop up a box
that says, “Congratulations, now, you may fully enjoy!”
So, how do you run a block of code only after the download has been
completed? Further, how do you animate certain objects only after a
view controller has been moved to the next? Well, we are going to find
out how to design one like a boss.
Based on my expansive vocabulary list, completion handlers stand for
Do stuff when things have been done
Bob’s post provides clarity about completion handlers (from a developer point of view it exactly defines what we need to understand).
#escaping closures:
When one passes a closure in function arguments, using it after the function’s body gets executed and returns the compiler back. When the function ends, the scope of the passed closure exist and have existence in memory, till the closure gets executed.
There are several ways to escaping the closure in containing function:
Storage: When you need to store the closure in the global variable, property or any other storage that exist in the memory past of the calling function get executed and return the compiler back.
Asynchronous execution: When you are executing the closure asynchronously on despatch queue, the queue will hold the closure in memory for you, can be used in future. In this case you have no idea when the closure will get executed.
When you try to use the closure in these scenarios the Swift compiler will show the error:
For more clarity about this topic you can check out this post on Medium.
Adding one more points , which every ios developer needs to understand :
Escaping Closure : An escaping closure is a closure that’s called after the function it was passed to returns. In other words,
it outlives the function it was passed to.
Non-escaping closure : A closure that’s called within the function it was passed into, i.e. before it returns.
Here's a small class of examples I use to remind myself how #escaping works.
class EscapingExamples: NSObject {
var closure: (() -> Void)?
func storageExample(with completion: (() -> Void)) {
//This will produce a compile-time error because `closure` is outside the scope of this
//function - it's a class-instance level variable - and so it could be called by any other method at
//any time, even after this function has completed. We need to tell `completion` that it may remain in memory, i.e. `escape` the scope of this
//function.
closure = completion
//Run some function that may call `closure` at some point, but not necessary for the error to show up.
//runOperation()
}
func asyncExample(with completion: (() -> Void)) {
//This will produce a compile-time error because the completion closure may be called at any time
//due to the async nature of the call which precedes/encloses it. We need to tell `completion` that it should
//stay in memory, i.e.`escape` the scope of this function.
DispatchQueue.global().async {
completion()
}
}
func asyncExample2(with completion: (() -> Void)) {
//The same as the above method - the compiler sees the `#escaping` nature of the
//closure required by `runAsyncTask()` and tells us we need to allow our own completion
//closure to be #escaping too. `runAsyncTask`'s completion block will be retained in memory until
//it is executed, so our completion closure must explicitly do the same.
runAsyncTask {
completion()
}
}
func runAsyncTask(completion: #escaping (() -> Void)) {
DispatchQueue.global().async {
completion()
}
}
}
/*the long story short is that #escaping means that don't terminate the function life time until the #escaping closure has finished execution in the opposite of nonEscaping closure the function can be terminated before the closure finishes execution Ex:
*/
func fillData(completion: #escaping: () -> Void){
/// toDo
completion()
}
//___________________________
//The call for this function can be in either way's #escaping or nonEscaping :
fillData{
/// toDo
}
/* again the deference between the two is that the function can be terminated before finish of execution nonEscaping closure in the other hand the #escaping closure guarantees that the function execution will not be terminated before the end of #escaping closure execution. Hope that helps ***#(NOTE THAT THE CLOSURE CAN BE OF ANY SWIFT DATA TYPE EVEN IT CAN BE TYPEALIAS)*/

"Closure cannot implicitly capture a mutating self parameter" - after updating to Swift 3 [duplicate]

I am using Firebase to observe event and then setting an image inside completion handler
FirebaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
if let _ = snapshot.value as? NSNull {
self.img = UIImage(named:"Some-image")!
} else {
self.img = UIImage(named: "some-other-image")!
}
})
However I am getting this error
Closure cannot implicitly capture a mutating self parameter
I am not sure what this error is about and searching for solutions hasn't helped
The short version
The type owning your call to FirebaseRef.observeSingleEvent(of:with:) is most likely a value type (a struct?), in which case a mutating context may not explicitly capture self in an #escaping closure.
The simple solution is to update your owning type to a reference once (class).
The longer version
The observeSingleEvent(of:with:) method of Firebase is declared as follows
func observeSingleEvent(of eventType: FIRDataEventType,
with block: #escaping (FIRDataSnapshot) -> Void)
The block closure is marked with the #escaping parameter attribute, which means it may escape the body of its function, and even the lifetime of self (in your context). Using this knowledge, we construct a more minimal example which we may analyze:
struct Foo {
private func bar(with block: #escaping () -> ()) { block() }
mutating func bax() {
bar { print(self) } // this closure may outlive 'self'
/* error: closure cannot implicitly capture a
mutating self parameter */
}
}
Now, the error message becomes more telling, and we turn to the following evolution proposal was implemented in Swift 3:
SE-0035: Limiting inout capture to #noescape contexts
Stating [emphasis mine]:
Capturing an inout parameter, including self in a mutating
method, becomes an error in an escapable closure literal, unless the
capture is made explicit (and thereby immutable).
Now, this is a key point. For a value type (e.g. struct), which I believe is also the case for the type that owns the call to observeSingleEvent(...) in your example, such an explicit capture is not possible, afaik (since we are working with a value type, and not a reference one).
The simplest solution to this issue would be making the type owning the observeSingleEvent(...) a reference type, e.g. a class, rather than a struct:
class Foo {
init() {}
private func bar(with block: #escaping () -> ()) { block() }
func bax() {
bar { print(self) }
}
}
Just beware that this will capture self by a strong reference; depending on your context (I haven't used Firebase myself, so I wouldn't know), you might want to explicitly capture self weakly, e.g.
FirebaseRef.observeSingleEvent(of: .value, with: { [weak self] (snapshot) in ...
Sync Solution
If you need to mutate a value type (struct) in a closure, that may only work synchronously, but not for async calls, if you write it like this:
struct Banana {
var isPeeled = false
mutating func peel() {
var result = self
SomeService.synchronousClosure { foo in
result.isPeeled = foo.peelingSuccess
}
self = result
}
}
You cannot otherwise capture a "mutating self" with value types except by providing a mutable (hence var) copy.
Why not Async?
The reason this does not work in async contexts is: you can still mutate result without compiler error, but you cannot assign the mutated result back to self. Still, there'll be no error, but self will never change because the method (peel()) exits before the closure is even dispatched.
To circumvent this, you may try to change your code to change the async call to synchronous execution by waiting for it to finish. While technically possible, this probably defeats the purpose of the async API you're interacting with, and you'd be better off changing your approach.
Changing struct to class is a technically sound option, but doesn't address the real problem. In our example, now being a class Banana, its property can be changed asynchronously who-knows-when. That will cause trouble because it's hard to understand. You're better off writing an API handler outside the model itself and upon finished execution fetch and change the model object. Without more context, it is hard to give a fitting example. (I assume this is model code because self.img is mutated in the OP's code.)
Adding "async anti-corruption" objects may help
I'm thinking about something among the lines of this:
a BananaNetworkRequestHandler executes requests asynchronously and then reports the resulting BananaPeelingResult back to a BananaStore
The BananaStore then takes the appropriate Banana from its inside by looking for peelingResult.bananaID
Having found an object with banana.bananaID == peelingResult.bananaID, it then sets banana.isPeeled = peelingResult.isPeeled,
finally replacing the original object with the mutated instance.
You see, from the quest to find a simple fix it can become quite involved easily, especially if the necessary changes include changing the architecture of the app.
If someone is stumbling upon this page (from search) and you are defining a protocol / protocol extension, then it might help if you declare your protocol as class bound. Like this:
protocol MyProtocol: class {
...
}
You can try this! I hope to help you.
struct Mutating {
var name = "Sen Wang"
mutating func changeName(com : #escaping () -> Void) {
var muating = self {
didSet {
print("didSet")
self = muating
}
}
execute {
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 15, execute: {
muating.name = "Wang Sen"
com()
})
}
}
func execute(with closure: #escaping () -> ()) { closure() }
}
var m = Mutating()
print(m.name) /// Sen Wang
m.changeName {
print(m.name) /// Wang Sen
}
Another solution is to explicitly capture self (since in my case, I was in a mutating function of a protocol extension so I couldn't easily specify that this was a reference type).
So instead of this:
functionWithClosure(completion: { _ in
self.property = newValue
})
I have this:
var closureSelf = self
functionWithClosure(completion: { _ in
closureSelf.property = newValue
})
Which seems to have silenced the warning.
Note this does not work for value types so if self is a value type you need to be using a reference type wrapper in order for this solution to work.