在iOS中,我收到以下错误:
“此应用程序正在从后台线程修改autolayout引擎”
有人知道如何调试吗?
EDIT1:分享我的代码和日志:
//
class AlertViewController: UIViewController, CLLocationManagerDelegate{
@IBOutlet weak var token: UILabel!
@IBOutlet weak var alertTable: AlertTableVC!
@IBOutlet weak var alertTypeColl: AlertTypeCollection!
@IBOutlet weak var goHome: UIButton!
@IBOutlet weak var goNewAlert: UIButton!
@IBOutlet weak var goProfile: UIButton!
@IBOutlet weak var goNotifications: UIButton!
@IBOutlet weak var goMap: UIButton!
@IBOutlet weak var alertActions: UIView!
static let locationManager: CLLocationManager = CLLocationManager()
@IBOutlet var GestureGoNewAlert: UITapGestureRecognizer!
var x: String = "0.0"
var y: String = "0.0"
var tokenUser: String = ""
var userName: String = ""
var refreshControl: UIRefreshControl = UIRefreshControl()
var doSearchByLocation: Bool = true; // es falso cuando se hace pull to refresh dado que se encuentra buscando actualizaciones
var isFirstSearch: Bool = true;
static var isSearchByLocation: Bool = false;
var lastSearchDate:NSDate = NSDate()
var lastSearchCal: NSCalendar = NSCalendar.currentCalendar()
var pleaseWait: UIAlertController = UIAlertController(title: nil, message:"Registrando Percepción de la zona. \n\n\n", preferredStyle: UIAlertControllerStyle.Alert)
let spinner: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
override func viewDidLoad() {
super.viewDidLoad()
//alertTable.contentInset = UIEdgeInsetsMake(0, 0, 20, 0);
let bottomBorder = CALayer()
let bgColor = UIColor(colorLiteralRed: 0.827, green: 0.827, blue: 0.827, alpha: 1)
bottomBorder.frame = CGRectMake(0.0, 0.0, self.alertActions.frame.size.width, 0.5);
bottomBorder.backgroundColor = bgColor.CGColor
refreshControl.addTarget(self, action: "refreshAlerts:", forControlEvents: .ValueChanged)
alertTable.addSubview(refreshControl)
spinner.center = CGPointMake(130.5, 85.5);
spinner.color = UIColor(colorLiteralRed: 0, green: 0, blue: 0, alpha: 1);
spinner.startAnimating();
pleaseWait.view.addSubview(spinner)
alertTable.vc = self
alertTable.showGeoProfile = true
alertTypeColl.alertController=self
self.alertTable.rowHeight = UITableViewAutomaticDimension
self.alertTable.estimatedRowHeight = 160
self.alertTable.separatorStyle = UITableViewCellSeparatorStyle.None
//self.alertTypeColl.
//self.AlertCommentsTable.rowHeight = UITableViewAutomaticDimension
dispatch_async(dispatch_get_main_queue(), {
self.alertActions.layer.addSublayer(bottomBorder)
self.goHome.titleLabel?.text = vooffKeys.homeIcon
self.goHome.setTitle( vooffKeys.homeIcon, forState: UIControlState.Normal)
self.goNotifications.titleLabel?.text = vooffKeys.notificationIcon
self.goNotifications.setTitle( vooffKeys.notificationIcon, forState: UIControlState.Normal)
self.goProfile.titleLabel?.text = vooffKeys.profileIcon
self.goProfile.setTitle( vooffKeys.profileIcon, forState: UIControlState.Normal)
self.goNewAlert.titleLabel?.text = vooffKeys.newAlertIcon
self.goNewAlert.setTitle( vooffKeys.newAlertIcon, forState: UIControlState.Normal)
self.goMap.titleLabel?.text = vooffKeys.mapAlertIcon
self.goMap.setTitle( vooffKeys.mapAlertIcon, forState: UIControlState.Normal)
})
// firstName.layer.addSublayer(bottomBorder)*/
// Do any additional setup after loading the view.
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
AlertViewController.locationManager.stopUpdatingLocation()
if let lastLoc = locations.last {
let locValue: CLLocationCoordinate2D = lastLoc.coordinate
if AlertViewController.isSearchByLocation && self.x != String(locValue.longitude) && self.y != String(locValue.latitude){
AlertViewController.isSearchByLocation = false
self.x = String(locValue.longitude)
self.y = String(locValue.latitude)
// print("lat: \(locValue.latitude) lng: \(locValue.longitude)")
let searchDate:NSDateComponents = lastSearchCal.components([NSCalendarUnit.Day , NSCalendarUnit.Month , NSCalendarUnit.Year , NSCalendarUnit.Hour , NSCalendarUnit.Minute , NSCalendarUnit.Second], fromDate: lastSearchDate)
let searchDateStr = "\(String(format: "%02d", searchDate.day))-\(String(format: "%02d", searchDate.month))-\(searchDate.year)%20\(String(format: "%02d",searchDate.hour)).\(String(format: "%02d", searchDate.minute)).\(String(format: "%02d", searchDate.second))"
self.isFirstSearch = false
print (" .... locationManager ....")
self.getAlerts (self.tokenUser, x: self.x, y: self.y, username: self.userName , lastsearch: searchDateStr)
lastSearchDate = NSDate()
lastSearchCal = NSCalendar.currentCalendar()
//do_table_refresh()
//crear una variable y setear la ultima vez que se busca por location
}
}
}
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation) {
print (" .... locationManager fromLocation ....")
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print ("No se pudo obtener la ubicacion: " + error.localizedDescription)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func refreshAlerts (refreshControl: UIRefreshControl) {
AlertViewController.isSearchByLocation = false;
AlertViewController.locationManager.stopUpdatingLocation()
self.getAlerts (self.tokenUser, x: self.x, y: self.y, username: self.userName , lastsearch: "")
lastSearchDate = NSDate()
lastSearchCal = NSCalendar.currentCalendar()
//do_table_refresh()
refreshControl.endRefreshing()
//print("estamos refrescando la info !!")
}
override func viewDidAppear(animated: Bool) {
let userDefaults = NSUserDefaults.standardUserDefaults()
self.alertTable.delegate = self.alertTable
self.alertTable.dataSource = self.alertTable
self.alertTypeColl.delegate = self.alertTypeColl
self.alertTypeColl.dataSource = self.alertTypeColl
if let userToken = userDefaults.objectForKey(vooffKeys.accessToken) {
AlertViewController.isSearchByLocation = false
if let userTokenStr: String = userToken as? String {
let userData = Functions.obtainUserData()
self.userName = userData[vooffKeys.profileUser]!
self.tokenUser = userTokenStr
RestApiManager.sharedInstance.setPushToken (self.tokenUser, username: self.userName, pushToken: userData[vooffKeys.pushToken]!, onCompletition: { json -> Void in
print ("Push notification seteado")
print (json)
})
// print ("TokenLogin: " + userTokenStr)
AlertViewController.locationManager.requestAlwaysAuthorization()
AlertViewController.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
AlertViewController.locationManager.delegate = self
AlertViewController.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
AlertViewController.locationManager.requestAlwaysAuthorization()
if let usrLoc = AlertViewController.locationManager.location {
self.x = String(usrLoc.coordinate.longitude)
self.y = String(usrLoc.coordinate.latitude)
// print ("locationServicesEnabled " + self.x + ";" + self.y)
self.getAlerts (self.tokenUser, x: self.x, y: self.y, username: self.userName , lastsearch: "")
self.getAlertTypes(self.tokenUser, username: self.userName )
}
}
} else {
print ("No se encontro str")
}
} else {
print ("No se encontro en defaults: " + vooffKeys.accessToken)
}
}
func getAlerts (token: String, x: String, y: String, username: String, lastsearch:String) {
RestApiManager.sharedInstance.getAlerts(token, x: x, y: y, username: username, lastsearch: lastsearch, onCompletition: {json -> Void in
dispatch_async(dispatch_get_main_queue(), {
// print(json)
if json["hasAccess"] == nil || json["hasAccess"]["isValid"].boolValue {
self.alertTable.userPos = CGPoint(x: CGFloat(Double(x)!), y: CGFloat(Double(y)!))
if lastsearch != "" {
if var alertArray = self.alertTable.alertsData {
if let newArray = json.array {
alertArray.insertContentsOf(newArray, at: 1)
self.alertTable.alertsData = alertArray
}
} else {
self.alertTable.alertsData = [json]
}
} else {
self.alertTable.alertsData = [json]
}
self.do_table_refresh()
}
else {
if json["hasAccess"]["gotologin"].boolValue {
Functions.openLoginPage(self)
}
}
})
// print("Registros Encontrados: \(json.array?.count) ")
})
}
func do_table_refresh() {
dispatch_async(dispatch_get_main_queue(), {
self.alertTable.reloadData()
//self.locationManager.startUpdatingLocation()
return
})
}
func getAlertTypes (token: String, username: String) {
RestApiManager.sharedInstance.getAlertTypes(token, username: username, onCompletition: {json -> Void in
dispatch_async(dispatch_get_main_queue(), {
if json["hasAccess"] == nil || json["hasAccess"]["isValid"].boolValue {
//print("Registros Encontrados: \(json.array?.count) ")
self.alertTypeColl.criminalTypes = [json]
self.alertTypeColl.reloadData()
//self.locationManager.startUpdatingLocation()
return
}
else {
if json["hasAccess"]["gotologin"].boolValue {
Functions.openLoginPage(self)
}
}
})
})
}
@IBAction func doGoNewAlert(sender: UIButton) {
print("dogoalert")
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.8, options: UIViewAnimationOptions.CurveEaseOut, animations: ({
if self.alertTypeColl.frame.maxY < 0 {
self.alertTypeColl.frame.offsetInPlace(dx: 0, dy: 470)
} else {
self.alertTypeColl.frame.offsetInPlace(dx: 0, dy: -470)
}
}), completion: {
(value: Bool) in
print("termino!!")
}
)
}
@IBAction func doRedPerception(sender: UITapGestureRecognizer) {
if let usrLoc = AlertViewController.locationManager.location {
self.x = String(usrLoc.coordinate.longitude)
self.y = String(usrLoc.coordinate.latitude)
self.presentViewController(pleaseWait, animated: false, completion: nil)
RestApiManager.sharedInstance.setGeoProfile (self.tokenUser, x: String(usrLoc.coordinate.longitude), y: String(usrLoc.coordinate.latitude), username: self.userName , geoType: "0", onCompletition: {json -> Void in
dispatch_async(dispatch_get_main_queue(), {
if json["hasAccess"] == nil || json["hasAccess"]["isValid"].boolValue {
if let perceptionWrap = json.array {
self.resetVooffPreceptions()
self.setVooffPerceptions (perceptionWrap)
}
self.dismissViewControllerAnimated(true, completion: nil)
}
else {
if json["hasAccess"]["gotologin"].boolValue {
Functions.openLoginPage(self)
}
}
})
})
}
}
@IBAction func doYellowPerception(sender: UITapGestureRecognizer) {
if let usrLoc = AlertViewController.locationManager.location {
self.x = String(usrLoc.coordinate.longitude)
self.y = String(usrLoc.coordinate.latitude)
self.presentViewController(pleaseWait, animated: false, completion: nil)
RestApiManager.sharedInstance.setGeoProfile (self.tokenUser, x: String(usrLoc.coordinate.longitude), y: String(usrLoc.coordinate.latitude), username: self.userName , geoType: "1", onCompletition: {json -> Void in
dispatch_async(dispatch_get_main_queue(), {
if json["hasAccess"] == nil || json["hasAccess"]["isValid"].boolValue {
if let perceptionWrap = json.array {
self.resetVooffPreceptions()
self.setVooffPerceptions (perceptionWrap)
}
self.dismissViewControllerAnimated(true, completion: nil)
}
else {
if json["hasAccess"]["gotologin"].boolValue {
Functions.openLoginPage(self)
}
}
})
})
}
}
@IBAction func doGreenPerception(sender: UITapGestureRecognizer) {
if let usrLoc = AlertViewController.locationManager.location {
self.x = String(usrLoc.coordinate.longitude)
self.y = String(usrLoc.coordinate.latitude)
self.presentViewController(pleaseWait, animated: true, completion: nil)
RestApiManager.sharedInstance.setGeoProfile (self.tokenUser, x: String(usrLoc.coordinate.longitude), y: String(usrLoc.coordinate.latitude), username: self.userName , geoType: "2", onCompletition: {json -> Void in
dispatch_async(dispatch_get_main_queue(), {
if json["hasAccess"] == nil || json["hasAccess"]["isValid"].boolValue {
if let perceptionWrap = json.array {
self.resetVooffPreceptions()
self.setVooffPerceptions (perceptionWrap)
}
self.dismissViewControllerAnimated(true, completion: nil)
}
else {
if json["hasAccess"]["gotologin"].boolValue {
Functions.openLoginPage(self)
}
}
})
})
}
}
func resetVooffPreceptions () {
let geoCell :AlertViewGeoProfileCell = self.alertTable.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0)) as! AlertViewGeoProfileCell
geoCell.redCount.text = "0 vooffers"
geoCell.yellowCount.text = "0 vooffers"
geoCell.greenCount.text = "0 vooffers"
}
func setVooffPerceptions (perceptionArr:[JSON]) {
let geoCell :AlertViewGeoProfileCell = self.alertTable.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0)) as! AlertViewGeoProfileCell
for var p in perceptionArr {
if p["type"].stringValue == "0" {
geoCell.redCount.text = "\(p["vooffers"].stringValue) vooffers"
}
else {
if p["type"].stringValue == "1" {
geoCell.yellowCount.text = "\(p["vooffers"].stringValue) vooffers"
}
else {
if p["type"].stringValue == "2" {
geoCell.greenCount.text = "\(p["vooffers"].stringValue) vooffers"
}
}
}
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let alertCell = sender as? AlertTypeCell {
let vc = segue.destinationViewController as? NewAlertVC
vc?.alertType = alertCell
if let usrLoc = AlertViewController.locationManager.location {
vc?.location = usrLoc
}
} else {
if let vc = segue.destinationViewController as? AlertMapVC {
if let usrLoc = AlertViewController.locationManager.location {
vc.location = usrLoc
}
} else {
print ("Cell no encontrado")
}
}
}
func openAlertDetail (sender: UITapGestureRecognizer) {
let userData = Functions.obtainUserData()
let alertSB: UIStoryboard = UIStoryboard (name: "AlertFriends", bundle: nil)
if let targetAlertDetailVC = alertSB.instantiateViewControllerWithIdentifier("alertDetail") as? AlertDetailVC {
targetAlertDetailVC.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
if let alertCell = sender.view as? AlertEvidenceImg {
let index = alertCell.indexAlertRow
if let alertArrWrap = self.alertTable.alertsData {
if alertArrWrap.count > 0 {
let alertArr = alertArrWrap[0].arrayValue
if alertArr.count > (index ) {
targetAlertDetailVC.alertData = alertArr[index]
targetAlertDetailVC.isCommentsTable = false
RestApiManager.sharedInstance.getUserData(userData[vooffKeys.accessToken]!, username: userData[vooffKeys.profileUser]!, usernameToView: userData[vooffKeys.profileUser]!, onCompletition: { json -> Void in
dispatch_async(dispatch_get_main_queue(), {
if json["hasAccess"] == nil || json["hasAccess"]["isValid"].boolValue {
targetAlertDetailVC.userProfileData = json
self.showViewController(targetAlertDetailVC, sender: alertCell)
}
else {
if json["hasAccess"]["gotologin"].boolValue {
Functions.openLoginPage(self)
}
}
})
})
}
}
}
}
}
}
func openAlertDetailComments(alertCell: AlertViewCell) {
let userData = Functions.obtainUserData()
let alertSB: UIStoryboard = UIStoryboard (name: "AlertFriends", bundle: nil)
if let targetAlertDetailVC = alertSB.instantiateViewControllerWithIdentifier("alertDetail") as? AlertDetailVC {
targetAlertDetailVC.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
let index = self.alertTable.indexPathForCell(alertCell)?.row
if let alertArrWrap = self.alertTable.alertsData {
if alertArrWrap.count > 0 {
let alertArr = alertArrWrap[0].arrayValue
if alertArr.count > (index ) {
targetAlertDetailVC.alertData = alertArr[index!]
targetAlertDetailVC.isCommentsTable = true
if self.alertTable.profileData == nil {
RestApiManager.sharedInstance.getUserData(userData[vooffKeys.accessToken]!, username: userData[vooffKeys.profileUser]!, usernameToView: userData[vooffKeys.profileUser]!, onCompletition: { json -> Void in
dispatch_async(dispatch_get_main_queue(), {
if json["hasAccess"] == nil || json["hasAccess"]["isValid"].boolValue {
targetAlertDetailVC.userProfileData = json
self.showViewController(targetAlertDetailVC, sender: self)
}
else {
if json["hasAccess"]["gotologin"].boolValue {
Functions.openLoginPage(self)
}
}
})
})
} else {
dispatch_async(dispatch_get_main_queue(), {
targetAlertDetailVC.userProfileData = self.alertTable.profileData![0]
self.showViewController(targetAlertDetailVC, sender: self)
})
}
}
}
}
}
}
func addUserPushToken () {
Functions.obtainUserData()
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
这是我得到的日志:
此应用程序正在从后台线程修改autolayout引擎,这可能导致引擎损坏和奇怪的崩溃。这将在将来的版本中引发异常。
Stack:(
0 CoreFoundation 0x0000000183142dc8 <redacted> + 148
1 libobjc.A.dylib 0x00000001827a7f80 objc_exception_throw + 56
2 CoreFoundation 0x0000000183142cf8 <redacted> + 0
3 Foundation 0x0000000183bf3b2c <redacted> + 88
4 Foundation 0x0000000183a74c3c <redacted> + 36
5 UIKit 0x00000001883a8d98 <redacted> + 64
6 UIKit 0x00000001883a98b0 <redacted> + 244
7 UIKit 0x0000000188b377f0 <redacted> + 268
8 UIKit 0x00000001885b4aa0 <redacted> + 176
9 UIKit 0x000000018829c210 <redacted> + 700
10 QuartzCore 0x0000000185c2e994 <redacted> + 148
11 QuartzCore 0x0000000185c295d0 <redacted> + 292
12 QuartzCore 0x0000000185c29490 <redacted> + 32
13 QuartzCore 0x0000000185c28ac0 <redacted> + 252
14 QuartzCore 0x0000000185c28820 <redacted> + 500
15 QuartzCore 0x0000000185c57bd4 <redacted> + 236
16 libsystem_pthread.dylib 0x0000000182da61e0 <redacted> + 584
17 libsystem_pthread.dylib 0x0000000182da5d58 <redacted> + 136
18 libsystem_pthread.dylib 0x0000000182da553c pthread_mutex_lock + 0
19 libsystem_pthread.dylib 0x0000000182da5020 start_wqthread + 4
)