DispatchQueue.main.sync returning exc_bad_instruction Swift 3

19,448

Solution 1

What you are trying to do here is to launch the main thread synchronously from a background thread before it exits. This is a logical error.

You should do it like this:

DispatchQueue.global().async(execute: {
    print("teste")
    DispatchQueue.main.sync{
        print("main thread")
    }
})

Solution 2

Maybe it's because you are trying to DispatchQueue.main.sync from the Main thread. You can check if you are already in the main thread like:

if Thread.isMainThread {
  // do stuff
} else {
  DispatchQueue.main.sync {
    // do stuff
  }
}

Solution 3

If you want to read the value from the main thread, here is a handy function:

func syncMain<T>(_ closure: () -> T) -> T {
    if Thread.isMainThread {
        return closure()
    } else {
        return DispatchQueue.main.sync(execute: closure)
    }
}

Usage:

// we are in BG or Main, does not matter
let value = syncMain {
    // we are in Main for sure
    return ...
}
Share:
19,448

Related videos on Youtube

Rodrigo Costa
Author by

Rodrigo Costa

Updated on July 01, 2022

Comments

  • Rodrigo Costa
    Rodrigo Costa almost 2 years

    I want to display an ActivityIndicatorView in my app, but when I call the sync method from the main thread, the app crashes with the error: exc_bad_instruction (code=exc_i386_invop subcode=0x0) I'm using xcode 8.0 and swift 3

    Can someone please help me?

     func POST(endpoint:NSString!,body:NSString!,vc:UIViewController? = nil)->NetworkResult{
        let result = NetworkResult()
        DispatchQueue.main.sync {
            self.displayActivityIndicator(viewController: vc)
        }
        let urlStr = self.url.appending(endpoint as String).appending(self.getHashAutenticacao() as String)
        print(urlStr)
        let request = NSMutableURLRequest(url: URL(string: urlStr)!, cachePolicy: NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 20)
        print(request.debugDescription)
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = body.data(using: String.Encoding.utf8.rawValue, allowLossyConversion: true)
    
        // send the request
        var data: NSData!
        do {
            data = try NSURLConnection.sendSynchronousRequest(request as URLRequest, returning: &self.response) as NSData!
        } catch let error1 as NSError {
            self.error = error1
            data = nil
        }
        if let httpResponse = self.response as? HTTPURLResponse {
            result.resultCode = httpResponse.statusCode
    
            if httpResponse.statusCode == 200{
                if data != nil{
                    if data.length > 0{
                        let json = (try! JSONSerialization.jsonObject(with: data as Data, options: JSONSerialization.ReadingOptions.mutableContainers))
                        if let jsonArray:NSArray = json as? NSArray{
                            result.data = jsonArray
                        }else{
                            if let jsonDict:NSDictionary = json as? NSDictionary{
                                result.data = [jsonDict]
                            }
                        }
                    }
                }
            }
        }else {
            result.message = self.error!.debugDescription as NSString?
        }
    
        DispatchQueue.main.sync {
            self.hideActivityIndicator(viewController: vc)
        }
        return result
    }
    
    • holex
      holex over 7 years
      what is -displayActivityIndicator(_:) method doing?
    • vadian
      vadian over 7 years
      Do not load data form a server synchronously, it causes bad user experience. Get used to the asynchronous pattern.
    • Cristi Băluță
      Cristi Băluță about 7 years
      I just noticed this too, i have a method that can return from main or secondary thread (which probably is not such a good idea but it makes sense for my case). I think is something new because i never worried about dispatching main thread from main thread till now.
  • Max Pevsner
    Max Pevsner over 7 years
    @RodrigoCosta what are you trying to achieve with DispatchQueue.main.sync { self.displayActivityIndicator(viewController: vc) }?
  • Rodrigo Costa
    Rodrigo Costa over 7 years
    The method POST needs to return data to the caller, the method displayActivityIndicator, displays an UIActivityIndicatorView into vc.view. I can't use async because i need data returned from the post.
  • Rodrigo Costa
    Rodrigo Costa over 7 years
    The method POST needs to return data to the caller, the method displayActivityIndicator, displays an UIActivityIndicatorView into vc.view. I can't use async because i need data returned from the post.
  • Max Pevsner
    Max Pevsner over 7 years
    @RodrigoCosta it will never work. Read the accepted answer to this question: stackoverflow.com/questions/31776114/…. It is the proper way to do it.
  • Max Pevsner
    Max Pevsner over 7 years
    @RodrigoCosta welcome. I would appreciate, if you accept it.
  • Ting Yi Shih
    Ting Yi Shih almost 6 years
    Why does DispatchQueue.main.sync mean I launch it from a background thread?
  • Wizard
    Wizard over 5 years
    Thanks, saved me some time. I find it kind of strange though that calling DispatchQueue.main.sync on the main thread leads to an error.
  • GeoSD
    GeoSD over 4 years
    There is nothing strange. You put block of code to be executed on main thread. So, if it already on main thread, that's obvious error..)