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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Amit Erandole
  • 11,995
  • 23
  • 65
  • 103
  • GCD has been preferred over `performSelectorOnMainThread` in Objective-C for a while now, check out the docs here:https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html – Jack Jun 09 '14 at 18:16

6 Answers6

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()?

Ben
  • 3,455
  • 3
  • 26
  • 31
  • You're welcome. Please mark the answer as your right answer, so that other people see the answer right away :) – Ben Jun 09 '14 at 18:17
  • I spoke too soon - I am now getting an error that I don't even know how to debug: http://cl.ly/image/1d272E263V2N - please have a look – Amit Erandole Jun 09 '14 at 18:29
  • What do you see in the console log when the exception happens (The exception just means that abort() was called) – David Berry Jun 09 '14 at 18:36
  • I tried this in my own project and also looked for the performOnThrad-methods, they are all deprecated.. – Ben Jun 09 '14 at 18:46
  • Update your question with the code you're currently using then, because the answer provided should certainly work. – David Berry Jun 09 '14 at 18:50
  • does your loadAlbums() function even is in another thread than the main-thread? That shouldn't create this error, but just wondering.. – Ben Jun 09 '14 at 20:03
  • Are you having problems on the simulator, or live device? I'm seeing the problem only the simulator. – David Berry Jun 09 '14 at 21:00
  • 1
    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! – diegomen Sep 12 '14 at 08:47
5

Swift 3

DispatchQueue.main.async(execute:
{
    //Code to execute on main thread
})
Tom Howard
  • 4,672
  • 2
  • 43
  • 48
2

Use GCD in lieu of performSelector variations.

dispatch_async(dispatch_get_main_queue()) {
        () -> Void in
        self.doSomething()
    }
Ah Ryun Moon
  • 370
  • 5
  • 4
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"

Anand Suthar
  • 3,678
  • 2
  • 30
  • 52
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

Pankaj Nigam
  • 318
  • 3
  • 7
-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
}
Richard Hope
  • 251
  • 3
  • 6