call method in main thread from background thread

How do I get code in a completion closure to notify the main thread to run a method in the main thread?

Answered by QuinceyMorris in 247369022

Instead of starting your closure like this:


{(granted, error) in


do this:


{[weak self] (granted, error) in


Then just use "self", instead of the hacky "weakSelf" that Obj-C forces on you. This is documented here:


https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html


under the heading "Resolving Strong Reference Cycles for Closures".

    dispatch_async(dispatch_get_main_queue(), ^{
         //  the code here including [self theMethod]
    });


   

There is the possibility of a retained loop that would capture self in a completion handler and never release it

- it's complicated. You might want, outside the completion handler, something like:

ThisClass *__weak weakSelf=self;

and then refer not to "self" but to "weakSelf"

I should have given more information. I am actually using Swift. I am working with EventKit, and the following is my code:


        eventStore.requestAccess(to: EKEntityType.reminder, completion:
            {(granted, error) in
                if !granted
                {
                    print("Access to store not granted")
                    print(error?.localizedDescription ?? "nil")
                 
                }
                else
                {
                    print("Access granted")
                 
                    let predicate = self.eventStore.predicateForReminders(in: nil)
                 
                    self.eventStore.fetchReminders(matching: predicate, completion: {
                     
                        (arrayReminders) in
                     
                        self.reminders = arrayReminders
                     
                        print("eventStore.fetchReminders() succeeded.")
                     
                        print("-------------------------------------------")
                     
                        self.tableViewEasyReminders.reloadData()
                     
                    })
                }
        })


Line 27 causes a message in the debug window that says:


This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.


I would like the code in line 27 to be called from within the main thread instead in order to solve the problem and make that message go away. When I put that code in a method of it's own in the view controller class outside that completion closure and then I call the method from the completion closure I still get the message in the debug window. That tells me that the code is actually still being called from the background thread.


I need to run that code from outside the completion closure and in the main thread when the completion closure ends.


How do I do that?

I'm actually using Swift. I figured out the asynchronous method call. How do I declare the weakSelf in Swift?

Accepted Answer

Instead of starting your closure like this:


{(granted, error) in


do this:


{[weak self] (granted, error) in


Then just use "self", instead of the hacky "weakSelf" that Obj-C forces on you. This is documented here:


https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html


under the heading "Resolving Strong Reference Cycles for Closures".

call method in main thread from background thread
 
 
Q