Swift alternative to performSelectorOnMainThread
Asked Answered
P

6

18

I want to reload my table data inside a block in this method:

import UIKit
import AssetsLibrary

class AlbumsTableViewController: UITableViewController {

    var albums:ALAssetsGroup[] = []

    func loadAlbums(){
        let library = IAAssetsLibraryDefaultInstance

        library.enumerateGroupsWithTypes(ALAssetsGroupType(ALAssetsGroupAll),
            usingBlock: {(group, stop) in
                if group {
                    self.albums.append(group)
                }
                else {
                    dispatch_async(dispatch_get_main_queue(), {

                        self.tableView.reloadData()

                    })
                }
            }, failureBlock: { (error:NSError!) in println("Problem loading albums: \(error)") })

    }

    override func viewDidLoad() {
        super.viewDidLoad()
        loadAlbums()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        //self.navigationItem.rightBarButtonItem = self.editButtonItem
    }

But the else block will not execute. The error I get is:

'performSelectorOnMainThread' is unavailable: 'performSelector' methods are unavailable

So what is the alternative to 'performSelectorOnMainThread' in swift?

UPDATE:

I am now getting an abort error.

Philosophy answered 9/6, 2014 at 18:12 Comment(1)
GCD has been preferred over performSelectorOnMainThread in Objective-C for a while now, check out the docs here:developer.apple.com/library/ios/documentation/Performance/…Pallet
D
41

This simple C-function:

dispatch_async(dispatch_get_main_queue(), {

        // DO SOMETHING ON THE MAINTHREAD
        self.tableView.reloadData()
        })

What about launching your function with:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {

        loadAlbums()

})

in viewDidLoad()?

Doomsday answered 9/6, 2014 at 18:14 Comment(8)
You're welcome. Please mark the answer as your right answer, so that other people see the answer right away :)Doomsday
I spoke too soon - I am now getting an error that I don't even know how to debug: cl.ly/image/1d272E263V2N - please have a lookPhilosophy
What do you see in the console log when the exception happens (The exception just means that abort() was called)Bullnecked
I tried this in my own project and also looked for the performOnThrad-methods, they are all deprecated..Doomsday
Update your question with the code you're currently using then, because the answer provided should certainly work.Bullnecked
does your loadAlbums() function even is in another thread than the main-thread? That shouldn't create this error, but just wondering..Doomsday
Are you having problems on the simulator, or live device? I'm seeing the problem only the simulator.Bullnecked
I had a problem with a resizable cell in a tableview, it resizes depending on if it has a thumbnail or not, and it worked perfect on each device except iPhone 6 Plus, but with that it works perfect! thanks!Hibbitts
P
5

Swift 3

DispatchQueue.main.async(execute:
{
    //Code to execute on main thread
})
Piperpiperaceous answered 28/6, 2017 at 15:39 Comment(0)
R
2

Use GCD in lieu of performSelector variations.

dispatch_async(dispatch_get_main_queue()) {
        () -> Void in
        self.doSomething()
    }
Rehabilitate answered 28/6, 2014 at 1:28 Comment(0)
P
1

You are calling performSelectorOnMainThread on UIViewController instead of UITableView's object

May be your code:

self.performSelectorOnMainThread(Selector(reloadData), withObject: self.tblMainTable, waitUntilDone: true)

Instead of:

self.tblMainTable.performSelectorOnMainThread(Selector("reloadData"), withObject: nil, waitUntilDone: true)

you are getting that message because UIViewController does't have any method named "performSelectorOnMainThread"

Pedicel answered 6/8, 2015 at 10:19 Comment(0)
D
1

//Xcode 8.2 // swift 3.0

I am accessing an API which gives the data regarding weather i.e 'temperature', 'humidity', 'pressure' etc after submitting the name or zipcode of any city. So, That data need to be shown(It must be on Main Thread) on UI (the tableView)

self.performSelector(onMainThread: #selector(Home.DataOnUI), with: nil, waitUntilDone: true)

//

func DataOnUI() {

     self.tblView.reloadData()
}

P.S. Home is the class of UIViewController

Donald answered 29/12, 2016 at 12:27 Comment(1)
Please also describe your solution in a few words.Revalue
B
-1

Swift 3 / Xcode 8.2

Here is a Swift 3 way of doing things. Simply insert the time (in seconds) that you would like the code to execute after.

let delayTime = DispatchTime.now() + Double(Int64(20.0 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
    DispatchQueue.main.asyncAfter(deadline: delayTime) {
        //Your code to run after 20 seconds
    }

Alternatively you could simply place your time delay in one-line notation like so:

DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) {
    // Your code to run after 10 seconds
}
Briant answered 11/1, 2017 at 17:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.