Ambiguous use of DispatchQueue on trying to use main thread - swift

This is a weird issue and I can't seem to find any help. On Swift 3, trying to make a call on the main thread I try to use DispatchQueue.main.async, but it doesn't compile.
Any ideas would be helpful.

Try this code instead, this is the Swift 3.0 syntax:
DispatchQueue.main.async(execute: { () -> Void in
})
For Swift 4.x you can also use:
DispatchQueue.main.async {
}

Related

Generic typealias with Void gives error missing argument in Swift 4

When I tried to migrate to Swift 4 an error occurred with my generic typealias for closures if you give it Void as an input. This worked fine in Swift 3 but not so much now, anybody know why, and is this a bug or a feature?
There is a workaround by defying another closure that explicit handles this case. But would be nice to not have to use this workaround and to understand why this error arose in Swift 4.
typealias Handler<T> = (T) -> Void
func foo(completion: Handler<String>) {
completion("fooing")
}
// This worked in Swift 3, but not in Swift 4
func bar(completion: Handler<Void>) {
completion() // Missing argument for parameter #1 in call
}
It seems that this is not a bug but how Swift works now. You cannot omit an associated value of type Void anymore.
I have found two passable workarounds:
The first one just explicitly just pass the value.
func bar(completion: Handler<Void>) {
completion(())
}
The second solution is to declare another typealias for void cases.
typealias VoidHandler = () -> Void
func barbar(completion: VoidHandler) {
completion()
}

How do I dispatch_sync, dispatch_async, dispatch_after, etc in Swift 3, Swift 4, and beyond?

I have lots of code in Swift 2.x (or even 1.x) projects that looks like this:
// Move to a background thread to do some long running work
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let image = self.loadOrGenerateAnImage()
// Bounce back to the main thread to update the UI
dispatch_async(dispatch_get_main_queue()) {
self.imageView.image = image
}
}
Or stuff like this to delay execution:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
print("test")
}
Or any of all kinds of other uses of the Grand Central Dispatch API...
Now that I've opened my project in Xcode 8 (beta) for Swift 3, I get all kinds of errors. Some of them offer to fix my code, but not all of the fixes produce working code. What do I do about this?
Since the beginning, Swift has provided some facilities for making ObjC and C more Swifty, adding more with each version. Now, in Swift 3, the new "import as member" feature lets frameworks with certain styles of C API -- where you have a data type that works sort of like a class, and a bunch of global functions to work with it -- act more like Swift-native APIs. The data types import as Swift classes, their related global functions import as methods and properties on those classes, and some related things like sets of constants can become subtypes where appropriate.
In Xcode 8 / Swift 3 beta, Apple has applied this feature (along with a few others) to make the Dispatch framework much more Swifty. (And Core Graphics, too.) If you've been following the Swift open-source efforts, this isn't news, but now is the first time it's part of Xcode.
Your first step on moving any project to Swift 3 should be to open it in Xcode 8 and choose Edit > Convert > To Current Swift Syntax... in the menu. This will apply (with your review and approval) all of the changes at once needed for all the renamed APIs and other changes. (Often, a line of code is affected by more than one of these changes at once, so responding to error fix-its individually might not handle everything right.)
The result is that the common pattern for bouncing work to the background and back now looks like this:
// Move to a background thread to do some long running work
DispatchQueue.global(qos: .userInitiated).async {
let image = self.loadOrGenerateAnImage()
// Bounce back to the main thread to update the UI
DispatchQueue.main.async {
self.imageView.image = image
}
}
Note we're using .userInitiated instead of one of the old DISPATCH_QUEUE_PRIORITY constants. Quality of Service (QoS) specifiers were introduced in OS X 10.10 / iOS 8.0, providing a clearer way for the system to prioritize work and deprecating the old priority specifiers. See Apple's docs on background work and energy efficiency for details.
By the way, if you're keeping your own queues to organize work, the way to get one now looks like this (notice that DispatchQueueAttributes is an OptionSet, so you use collection-style literals to combine options):
class Foo {
let queue = DispatchQueue(label: "com.example.my-serial-queue",
attributes: [.serial, .qosUtility])
func doStuff() {
queue.async {
print("Hello World")
}
}
}
Using dispatch_after to do work later? That's a method on queues, too, and it takes a DispatchTime, which has operators for various numeric types so you can just add whole or fractional seconds:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // in half a second...
print("Are we there yet?")
}
You can find your way around the new Dispatch API by opening its interface in Xcode 8 -- use Open Quickly to find the Dispatch module, or put a symbol (like DispatchQueue) in your Swift project/playground and command-click it, then brouse around the module from there. (You can find the Swift Dispatch API in Apple's spiffy new API Reference website and in-Xcode doc viewer, but it looks like the doc content from the C version hasn't moved into it just yet.)
See the Migration Guide for more tips.
In Xcode 8 beta 4 does not work...
Use:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
print("Are we there yet?")
}
for async two ways:
DispatchQueue.main.async {
print("Async1")
}
DispatchQueue.main.async( execute: {
print("Async2")
})
This one is good example for Swift 4 about async:
DispatchQueue.global(qos: .background).async {
// Background Thread
DispatchQueue.main.async {
// Run UI Updates or call completion block
}
}
in Xcode 8 use:
DispatchQueue.global(qos: .userInitiated).async { }
Swift 5.2, 4 and later
Main and Background Queues
let main = DispatchQueue.main
let background = DispatchQueue.global()
let helper = DispatchQueue(label: "another_thread")
Working with async and sync threads!
background.async { //async tasks here }
background.sync { //sync tasks here }
Async threads will work along with the main thread.
Sync threads will block the main thread while executing.
Swift 4.1 and 5. We use queues in many places in our code. So, I created Threads class with all queues. If you don't want to use Threads class you can copy the desired queue code from class methods.
class Threads {
static let concurrentQueue = DispatchQueue(label: "AppNameConcurrentQueue", attributes: .concurrent)
static let serialQueue = DispatchQueue(label: "AppNameSerialQueue")
// Main Queue
class func performTaskInMainQueue(task: #escaping ()->()) {
DispatchQueue.main.async {
task()
}
}
// Background Queue
class func performTaskInBackground(task:#escaping () throws -> ()) {
DispatchQueue.global(qos: .background).async {
do {
try task()
} catch let error as NSError {
print("error in background thread:\(error.localizedDescription)")
}
}
}
// Concurrent Queue
class func perfromTaskInConcurrentQueue(task:#escaping () throws -> ()) {
concurrentQueue.async {
do {
try task()
} catch let error as NSError {
print("error in Concurrent Queue:\(error.localizedDescription)")
}
}
}
// Serial Queue
class func perfromTaskInSerialQueue(task:#escaping () throws -> ()) {
serialQueue.async {
do {
try task()
} catch let error as NSError {
print("error in Serial Queue:\(error.localizedDescription)")
}
}
}
// Perform task afterDelay
class func performTaskAfterDealy(_ timeInteval: TimeInterval, _ task:#escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: (.now() + timeInteval)) {
task()
}
}
}
Example showing the use of main queue.
override func viewDidLoad() {
super.viewDidLoad()
Threads.performTaskInMainQueue {
//Update UI
}
}

Swift 2 : Try/Catch a non-throwing function

I'm refactoring a Obj-c class where there was a #try/#catch block around removeObserver:.
Doing the same thing in swift triggers a warning since removeObserver might fail (when there is no observer) but it doesn't throw any errors.
Any idea how I could achieve the same behaviour ?
edit : My code :
try {
self.removeObserver(self, forKeyPath: "LineDisplayChanged")
}
The func removeObserver(_ anObserver: NSObject,forKeyPath keyPath: String) you are calling is from the NSKeyValueObserving protocol and does not throws any exceptions.
Also, note that in Swift 2 the syntax for exception(that are actually ErrorType enum subclasses) has changed and is now something like this:
do{
try functionThrowingExceptions()
}catch ErrorTypeSubclassEnum.Value {
// Do something
}catch ErrorType {
// Do something, catches everything else
}
See this post for more info.
Note: I'm using KVO with the latest beta of XCode7, doing a self.removeObserver(self, forKeyPath: "path") does not trigger any error/warning.
To remove warning just remove try { }. removeObserver:forKeyPath: is throwing an exception and not an error. And you cannot catch exceptions in Swift so make sure you call this method only if you observing it otherwise it will crash and there is no way around it in Swift.
You could write a category in Objective-C that wraps this call and capture the exception and returns an error instead.

Why doesn't throw work in Swift?

Any ideas why the following doesn't work?
func someFunction() throws {
print ("this is a test")
}
I believe that throws was introduced in swift 2.0, if you are using an earlier version then you will not be able to use it.
https://developer.apple.com/swift/blog/?id=29

dispatch_async in Swift

I am really new to this programming language called swift.
I use
dispatch_async(dispatch_get_main_queue(), ^{
});
this method for async-dispatch-queue in xcode 5.
I want implement it in swift language.
how do i implement dispatch queue in or swift?
For those of you viewing this post three years later as I did, the Swift functions have been improved. Now you can write:
DispatchQueue.main.async(execute: { () -> Void in
// Your code here
})
You can use this syntax:
dispatch_async(dispatch_get_main_queue(), {
println("hello")
})
However, when the last argument is a block, Swift lets you put it outside the parentheses. This makes the function seem more like a control structure (like a for or if statement). Thus you can do this:
dispatch_async(dispatch_get_main_queue()) {
println("hello")
}
Xcode gives you an easy help with that....
Just type in
dispatch_async and hit enter... Than XCode gives you something like this...
dispatch_async(queue: dispatch_queue_t!, block: dispatch_block_t! () -> Void)
now take your mouse and double-click on block: dispatch_block_t! () -> Void and XCode will automatically change this to a working closure expression :-)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
//Your Code here
})