15

I am getting this error This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes.This will cause an exception in a future release. I don't know what is causing this error. Can anybody help me.

func getUserDataFromTwitterWithUser(user : PFUser)
 {
//NRLoader.showLoader()
let strTwURL = "https://api.twitter.com/1.1/users/show.json?     screen_name="+PFTwitterUtils.twitter()!.screenName! + "&access_token="+PFTwitterUtils.twitter()!.authToken!
let twURL = NSURL (string: strTwURL)

let request = NSMutableURLRequest(URL: twURL!, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 2.0) as NSMutableURLRequest

PFTwitterUtils.twitter()?.signRequest(request)

let session = NSURLSession.sharedSession()

session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
  if error == nil {
    var  jsonOptional = Dictionary<String, AnyObject>()

    do {
      jsonOptional = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers ) as! Dictionary<String, AnyObject>
      // use jsonData
    } catch {
      // report error
    }
    var userName = ""
    if let screenName = jsonOptional["screen_name"] as? String{
      userName = screenName
    }
    else if let name = jsonOptional["name"] as? String{
      userName = name
    }

    var profilePicUrl = ""


    if let picUrl = jsonOptional["profile_image_url"] as? String{
      profilePicUrl = picUrl
    }
    AppUser.currentUser()?.username = userName
    AppUser.currentUser()?.profileAwsURL = profilePicUrl
    //NRLoader.hideLoader()
    //if ParseUtils.isLoggedInUserIsAnonymous() {
      let signUpVC:SignMeUpViewController = self.storyboard!.instantiateViewControllerWithIdentifier("SignMeUpViewController") as! SignMeUpViewController
      signUpVC.isFromLogin = true
      self.navigationController!.pushViewController(signUpVC, animated: true)

    //} else {
     // self.pushToSubmitDreamViewController()
    //}
  }
  else {
    //NRLoader.hideLoader()
    NRToast.showToastWithMessage(error!.description)
  }


}).resume()
 }
Ganesh Kumar
  • 1,631
  • 2
  • 21
  • 35
  • 1
    Possible duplicate of [This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes](http://stackoverflow.com/questions/31951704/this-application-is-modifying-the-autolayout-engine-from-a-background-thread-wh) – Sohil R. Memon Feb 24 '16 at 06:08
  • Please check the above answer, it works for everyone. – Sohil R. Memon Feb 24 '16 at 06:08
  • Refer to this [post](http://stackoverflow.com/q/28302019/6521116) – LF00 May 17 '17 at 07:36

5 Answers5

35

The dataTaskWithRequest call runs in the background and then calls your completion handler from the same thread. Anything that updates the UI should run on the main thread, so all of your current handler code should be within a dispatch_async back onto the main queue:

dispatch_async(dispatch_get_main_queue()) {
  // Do stuff to UI
}

Swift 3:

DispatchQueue.main.async() {
  // Do stuff to UI
}

Therefore, ideally all the code you currently have within if error == nil should be off in another function, say called handleRequest, so your current code becomes:

session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
    if error == nil {
        dispatch_async(dispatch_get_main_queue(), {
            self.handleRequest(...)I
        })
    }
Dimitar Nestorov
  • 2,411
  • 24
  • 29
Michael
  • 8,891
  • 3
  • 29
  • 42
17

Swift 3

session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if error == nil {
    DispatchQueue.main.async {
        self.handleRequest(...)I
    }
}
Vimal Saifudin
  • 1,815
  • 1
  • 21
  • 28
7

Should try Symbolic Breakpoint to detect the issue:-enter image description here

Then put your UI Update code in main thread

DispatchQueue.main.async {}
Abdul Hameed
  • 1,025
  • 13
  • 17
  • 2
    For me, I need to catch `[CALayer layoutIfNeeded]` because I'm trying to call `[myLayer renderInContext:context];` from a background thread. – vmeyer Jul 24 '17 at 12:51
  • Won't it cause the app run slow seriously when debugging? – Itachi Sep 06 '17 at 09:30
1

You'd better change UI only in the main thread

swift3,

    let liveInfoUrl = URL(string: "http://192.168.1.66/api/cloud/app/liveInfo/7777")
    let task = URLSession.shared.dataTask(with: liveInfoUrl! as URL) {data, response, error in
        guard let data = data, error == nil else { return }
        DispatchQueue.main.async {
            print(String(data: data, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) ?? "aaaa")

            //do some ui work
        }
    }
LF00
  • 27,015
  • 29
  • 156
  • 295
0

if the above suggestions still give you no joy then the sure-est way is to redesign your functions so that getting what you need with

 URLSession.shared.dataTask

then hands over so a variable declared outside that function, then a separate UIControl ( button, swipe etc ) displays it to a label or textview or whatever.

After all that is what the error message is telling you. they're separate concerns

aremvee
  • 179
  • 1
  • 13