Creating ASYNC task in Swift 2 - ios

I want to show users current location in map and I know it's not instantaneous task. I want to call my showCurrentLocation() function in the ASYNC task. I was trying to learn call back closures but i could not understand how can I create ASYNC task for this. I know this is not a best question template for stackoverflow but I don't know how can I ask differently.
Thank you for any help.
Have a nice coding.

In the past I've made a class called AsyncTask for usage purposes like the one you described here.
Lately I've updated it for swift 3
It has 2 generic types:
BGParam - the type of the parameter sent to the task upon execution.
BGResult - the type of the result of the background computation.
If one of them(or both) isn't needed you can set it to Optional or just ignore.
In code example I refer the functions showCurrentLocation() & getCurrentLocation() that you mentioned in OP & comments.
BGParam is set to Int & BGResults is set to CLLocationCoordinate2D
AsyncTask(backgroundTask: {(param:Int)->CLLocationCoordinate2D in
print(param);//prints the Int value passed from .execute(1)
return self.getCurrentLocation();//the function you mentioned in comment
}, afterTask: {(coords)in
//use latitude & longitude at UI-Main thread
print("latitude: \(coords.latitude)");
print("latitude: \(coords.longitude)");
self.showCurrentLocation(coords);//function you mentioned in OP
}).execute(1);//pass Int value 1 to backgroundTask

There is a technology called GCD (Grand Central Dispatch) which you can use to perform such tasks.
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// do some task
dispatch_async(dispatch_get_main_queue()) {
// update some UI
}
}

Related

Can I use actors in Swift to always call a function on the main thread?

I recently saw that Swift had introduced concurrency support with the Actor model in Swift 5.5. This model enables safe concurrent code to avoid data races when we have a shared, mutable state.
I want to avoid main thread data races in my app's UI. For this, I am wrapping DispatchQueue.main.async at the call site wherever I set a UIImageView.image property or a UIButton style.
// Original function
func setImage(thumbnailName: String) {
myImageView.image = UIImage(named: thumbnailName)
}
// Call site
DispatchQueue.main.async {
myVC.setImage(thumbnailName: "thumbnail")
}
This seems unsafe because I have to remember to dispatch the method manually on the main queue. The other solution looks like:
func setImage(thumbnailName: String) {
DispatchQueue.main.async {
myImageView.image = UIImage(named: thumbnailName)
}
}
But this looks like a lot of boilerplate, and I wouldn't say I like using this for complex functions with more than one level of nesting.
The release of Swift support for Actors looks like a perfect solution for this. So, is there a way to make my code safer, i.e. always call UI functions on the main thread using Actors?
Actors in Swift 5.5 🤹‍♀️
Actor isolation and re-entrancy are now implemented in the Swift stdlib. So, Apple recommends using the model for concurrent logic with many new concurrency features to avoid data races. Instead of lock-based synchronisation (lots of boilerplate), we now have a much cleaner alternative.
Some UIKit classes, including UIViewController and UILabel, now have out of the box support for #MainActor. So we only need to use the annotation in custom UI-related classes. For example, in the code above, myImageView.image would automatically be dispatched on the main queue. However, the UIImage.init(named:) call is not automatically dispatched on the main thread outside of a view controller.
In the general case, #MainActor is useful for concurrent access to UI-related state, and is the easiest to do even though we can manually dispatch too. I've outlined potential solutions below:
Solution 1
The simplest possible. This attribute could be useful in UI-Related classes. Apple have made the process much cleaner using the #MainActor method annotation:
#MainActor func setImage(thumbnailName: String) {
myImageView.image = UIImage(image: thumbnailName)
}
This code is equivalent to wrapping in DispatchQueue.main.async, but the call site is now:
await setImage(thumbnailName: "thumbnail")
Solution 2
If you have Custom UI-related classes, we can consider applying #MainActor to the type itself. This ensures that all methods and properties are dispatched on the main DispatchQueue.
We can then manually opt out from the main thread using the nonisolated keyword for non-UI logic.
#MainActor class ListViewModel: ObservableObject {
func onButtonTap(...) { ... }
nonisolated func fetchLatestAndDisplay() async { ... }
}
We don't need to specify await explicitly when we call onButtonTap within an actor.
Solution 3 (Works for blocks, as well as functions)
We can also call functions on the main thread outside an actor with:
func onButtonTap(...) async {
await MainActor.run {
....
}
}
Inside a different actor:
func onButtonTap(...) {
await MainActor.run {
....
}
}
If we want to return from within a MainActor.run, simply specify that in the signature:
func onButtonTap(...) async -> Int {
let result = await MainActor.run { () -> Int in
return 3012
}
return result
}
This solution is slightly less cleaner than the above two solutions which are most suited for wrapping an entire function on the MainActor. However, actor.run also allows for inter threaded code between actors in one func (thx #Bill for the suggestion).
Solution 4 (Block solution that works within non-async functions)
An alternative way to schedule a block on the #MainActor to Solution 3:
func onButtonTap(...) {
Task { #MainActor in
....
}
}
The advantage here over Solution 3 is that the enclosing func doesn't need to be marked as async. Do note however that this dispatches the block later rather than immediately as in Solution 3.
Summary
Actors make Swift code safer, cleaner and easier to write. Don't overuse them, but dispatching UI code to the main thread is a great use case. Note that since the feature is still in beta, the framework may change/improve further in the future.
Since we can easily use the actor keyword interchangeably with class or struct, I want to advise limiting the keyword only to instances where concurrency is strictly needed. Using the keyword adds extra overhead to instance creation and so doesn't make sense when there is no shared state to manage.
If you don't need a shared state, then don't create it unnecessarily. struct instance creation is so lightweight that it's better to create a new instance most of the time. e.g. SwiftUI.

When would a queue consider a task is completed?

In the following code, when would queueT (serial queue) consider “task A” is completed?
The moment when aNetworkRequest switched to another thread?
Or in the doneInAnotherQueue block? ( commented // 1)
In another word, when would “task B” be executed?
let queueT = DispatchQueue(label: "com.test.a")
queueT.async { // task A
aNetworkRequest.doneInAnotherQueue() { // completed in another thread possibly
// 1
}
}
queueT.async { // task B
print("It's my turn")
}
It would much better if you could explain the mechanism how a queue consider a task is completed.
Thanks in advance.
In short, the first example starts an asynchronous network request, so the async call “finishes” as soon as that network request is submitted (but does not wait for that network request to finish).
I am assuming that the real question is that you want to know when the network request is done. Bottom line, GCD is not well suited for managing dependencies between tasks that are, themselves, asynchronous requests. The dispatching the initiation of a network request to a serial queue is undoubtedly not going to achieve what you want. (And before someone suggests using semaphores or dispatch groups to wait for the asynchronous request to finish, note that can solve the tactical issue, but it is a pattern to be avoided because it is inefficient use of resources and, in edge cases, can introduce deadlocks.)
One pattern is to use completion handlers:
func performRequestA(completion: #escaping () -> Void) { // task A
aNetworkRequest.doneInAnotherQueue() { object in
...
completion()
}
}
Now, in practice, we would generally use the completion handler with a parameter, perhaps even a Result type:
func performRequestA(completion: #escaping (Result<Foo, Error>) -> Void) { // task A
aNetworkRequest.doneInAnotherQueue() { result in
guard ... else {
completion(.failure(error))
return
}
let foo = ...
completion(.success(foo))
}
}
Then you can use the completion handler pattern, to process the results, update models, and perhaps initiate subsequent requests that are dependent upon the results of this request. For example:
performRequestA { result in
switch result {
case .failure(let error):
print(error)
case .success(let foo):
// update models or initiate next step in the process here
}
}
If you are really asking how to manage dependencies between asynchronous tasks, there are a number of other, elegant patterns (e.g., Combine, custom asynchronous Operation subclass, the forthcoming async/await pattern contemplated in SE-0296 and SE-0303, etc.). All of these are elegant solutions for managing dependencies between asynchronous tasks, controlling the degree of concurrency, etc.
We probably would need to better understand the nature of your broader needs before we made any specific recommendations. You have asked the question about a single dispatch, but the question probably is best viewed from a broader context of what you are trying to achieve. For example, I'm assuming you are asking because you have multiple asynchronous requests to initiate: Do you really need to make sure that they happen sequentially and lose all the performance benefits of concurrency? Or can you allow them to run concurrently and you just need to know when all of the concurrent requests are done and how to get the results in the correct order? And might you have so many concurrent requests that you might need to constrain the degree of concurrency?
The answers to those questions will probably influence our recommendation of how to best manage your multiple asynchronous requests. But the answer is almost certainly is not a GCD queue.
You can do a simple check
let queueT = DispatchQueue(label: "com.test.a")
queueT.async { // task A
DispatchQueue(label: "com.test2.a").async { // create another queue inside
for i in 0..<6 {
print(i)
}
}
}
queueT.async { // task B
for i in 10..<20 {
print(i)
}
}
}
you'll get different output each run this means yes when you switch thread the task is considered done
A GCD work item is complete when the closure you pass returns. So for your example, I'm going to rewrite it to make the function calls and parameters more explicit (rather than using trailing closure syntax).
queueT.async(execute: {
// This is a function call that takes a closure parameter. Whether this
// function returns, then this closure will continue. Whether that is before or
// after running completionHandler is an internal detail of doneInAnotherQueue.
aNetworkRequest.doneInAnotherQueue(closureParameter: { ... })
// At this point, the closure is complete. What doneInAnotherQueue() does with
// its closure is its business.
})
Assuming that doneInAnotherQueue() executes its closure parameter "sometime in the future", then your task B will likely run before that closure runs (it may not; it's really a race at that point, but probably). If the doneInAnotherQueue() blocks on its closure before returning, then closureParameter will definitely run before task B.
There is absolutely no magic here. The system has no idea what doneInAnotherQueue does with its parameter. It may never run it. It may run it immediately. It may run it sometime in the future. The system just calls doneInAnotherQueue() and passes it a closure.
I rewrote async in normal "function with parameters" syntax to make it even more clear that async() is just a function, and it takes a closure parameter. It also isn't magic. It's not part of the language. It's just a normal function in the Dispatch framework. All it does it take its parameter, put it on a dispatch queue, and return. It doesn't execute anything. There's just closures that get put on queues, scheduled, and executed.
Swift is in the process of adding structured concurrency, which will add more language-level concurrency features that will allow you to express much more advanced things than the simple primitives provided by GCD.
Your task A returns straight away. Dispatching work to another queue is synchronous. Think of the block (the trailing closure) after 'doneInAnotherQueue' as just an argument to the doneInAnotherQueue function, no different to passing an Int or a String. You pass that block along and then you return immediately with the closing brace from task A.

Stop arbitrary function execution

For the purposes of this question, assume that I need to run some function on some object and that function will take a long time to execute (minutes). Also assume that I have no control over this function (*). How do I now cancel this function's execution?
I want to run it in a background thread to keep the main thread free and I could do that with GCD, NSOperation or NSThread. However, as far as I know, none of these support forced stopping. They can all be cancelled, but this cancellation must be implemented in the function itself - but I don't have access to that function, so I can't do that. The closest I got was using NSThread and exit(), but unfortunately it can't be applied to a instance variable (see the code example). My current plan is to try to send a notification and observe that within the object/function and kill the thread from within using Thread.exit(). I'm justing wondering if there is a "cleaner" or easier way, either built-in or 3rd party.
let someObject = Object()
// Using GCD
dispatchQueue.async { someObject.expensiveFunction() }
// Using NSOperation
operationQueue.addOperation { someObject.expensiveFunction() }
// Using NSThread
let thread = Thread { someObject.expensiveFunction() }
thread.exit() // exit is not available on an instance
(*) In this case I do have control over the function and could implement an actual cancellation, but due to the libraries I'm using, this would require a lot of refactoring.

how to use suspendCoroutine to turn java 7 future into kotlin suspending function

What is the best approach to wrap java 7 futures inside a kotlin suspend function?
Is there a way to convert a method returning Java 7 futures into a suspending function?
The process is pretty straightforward for arbitrary callbacks or java 8 completablefutures, as illustrated for example here:
* https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md#suspending-functions
In these cases, there is a hook that is triggered when the future is done, so it can be used to resume the continuation as soon as the value of the future is ready (or an exception is triggered).
Java 7 futures however don't expose a method that is invoked when the computation is over.
Converting a Java 7 future to a Java 8 completable future is not an option in my codebase.
Of course, i can create a suspend function that calls future.get() but this would be blocking, which breaks the overall purpose of using coroutine suspension.
Another option would be to submit a runnable to a new thread executor, and inside the runnable call future.get() and invoke a callback. This wrapper will make the code looks like "non-blocking" from the consumer point of view, the coroutine can suspend, but under the hood we are still writing blocking code and we are creating a new thread just for the sake of blocking it
Java 7 future is blocking. It is not designed for asynchronous APIs and does not provide any way to install a callback that is invoked when the future is complete. It means that there is no direct way to use suspendCoroutine with it, because suspendCoroutine is designed for use with asynchronous callback-using APIs.
However, if your code is, in fact, running under JDK 8 or a newer version, there are high chances that the actual Future instance that you have in your code happens to implement CompletionStage interface at run-time. You can try to cast it to CompletionStage and use ready-to-use CompletionStage.await extension from kotlinx-coroutines-jdk8 module of kotlinx.coroutines library.
Of course Roman is right that a Java Future does not let you provide a callback for when the work is done.
However, it does give you a way to check if the work is done, and if it is, then calling .get() won't block.
Luckily for us, we also have a cheap way to divert a thread to quickly do a poll check via coroutines.
Let's write that polling logic and also vend it as an extension method:
suspend fun <T> Future<T>.wait(): T {
while(!isDone)
delay(1) // or whatever you want your polling frequency to be
return get()
}
Then to use:
fun someBlockingWork(): Future<String> { ... }
suspend fun useWork() {
val result = someBlockingWork().wait()
println("Result: $result")
}
So we have millisecond-response time to our Futures completing without using any extra threads.
And of course you'll want to add some upper bound to use as a timeout so you don't end up waiting forever. In that case, we can update the code just a little:
suspend fun <T> Future<T>.wait(timeoutMs: Int = 60000): T? {
val start = System.currentTimeMillis()
while (!isDone) {
if (System.currentTimeMillis() - start > timeoutMs)
return null
delay(1)
}
return get()
}
You should be now be able to do this by creating another coroutine in the same scope that cancels the Future when the coroutine is cancelled.
withContext(Dispatchers.IO) {
val future = getSomeFuture()
coroutineScope {
val cancelJob = launch {
suspendCancellableCoroutine<Unit> { cont ->
cont.invokeOnCancellation {
future.cancel(true)
}
}
}
future.get().also {
cancelJob.cancel()
}
}
}

How to do multithreading, concurrency or parallelism in iOS Swift?

Is there any way to create a worker thread in Swift?, for example, if there's a major functionality that requires a lot of calculations and hence causes the main thread to delay for a few seconds, if I would like to move that functionality to a separate thread or a thread that do not block the main thread is there any way to do it with Swift?
I've gone through the basic and advanced components of the Apple Documentation for Swift but there's nothing about concurrency or parallelism, do anyone know something about how to do it(if possible)?
Or you can use operation queues, too. In Swift 3:
let queue = OperationQueue()
queue.addOperation() {
// do something in the background
OperationQueue.main.addOperation() {
// when done, update your UI and/or model on the main queue
}
}
Either this, or GCD, which Andy illustrated, work fine.
See Apple's Concurrency Programming Guide for the relative merits of operation queues and dispatch queues (aka Grand Central Dispatch, GCD). While that guide is still illustrating the examples using Objective-C, the API and concepts are basically the same in Swift (just use the Swift syntax). The documentation for GCD and operation queues in Xcode describes both Objective-C and Swift APIs.
By the way, you'll notice that in both the above example as well as Andy's GCD demonstration, we used "trailing closures". For example, if you look at the definition addOperationWithBlock, that is defined as a function with one parameter which is a "closure" (which is analogous to a block in Objective-C):
func addOperation(_ block: #escaping () -> Swift.Void)
That might lead you to assume that you would invoke it as follows:
queue.addOperation({
// do something in the background
})
But when the last parameter of a function is a closure, the trailing closure syntax allows you to take that final closure parameter out of the parentheses of the function, and move it after the function, yielding:
queue.addOperation() {
// do something in the background
}
And because there's nothing left in the parentheses, you can even go one step further, and remove those empty parentheses:
queue.addOperation {
// do something in the background
}
Hopefully that illustrates how to interpret the NSOperationQueue/OperationQueue and/or GCD function declarations and use them in your code.
You can use Grand Central Dispatch (GCD) for such tasks.
This is a basic example:
let backgroundQueue: dispatch_queue_t = dispatch_queue_create("com.a.identifier", DISPATCH_QUEUE_CONCURRENT)
// can be called as often as needed
dispatch_async(backgroundQueue) {
// do calculations
}
// release queue when you are done with all the work
dispatch_release(backgroundQueue)
This library lets you describe concurrency in a super expressive way:
func handleError(_ error) { ... }
HoneyBee.start(on: DispatchQueue.main) { root in
root.setErrorHandler(handleError)
.chain(function1) // runs on main queue
.setBlockPerformer(DispatchQueue.global())
.chain(function2) // runs on background queue
.branch { stem in
stem.chain(func3) // runs in parallel with func4
+
stem.chain(func4) // runs in parallel with func3
}
.chain(func5) // runs after func3 and func4 have finished
.setBlockPerformer(DispatchQueue.main)
.chain(updateUIFunc)
}
Here is the best resource to learn in detail about
Councurrency

Resources