插入NSManagedObject时出现EXC_BAD_ACCESS错误

时间:2017-06-23 12:36:07

标签: ios core-data

在超类EXC_BAD_ACCESS调用中插入NSManagedObject时出现init错误。错误并不总是发生,所以我的猜测是它与线程有关,但是我对iOS开发很新,所以我可能完全错了。

在下面的代码中,我用注释标记出错的行。

import Foundation
import CoreData

@objc(Measurement)
public class Measurement: NSManagedObject {
    convenience init(sensorId: Int32, fromDatetime: Int64, pm10: Float, pm25: Float, airQualityIndex: Float32, pollutionLevel: Int16,
                     latitude: Double, longitude: Double, source: String, windDeg: Float32, windSpeed: Float32,
                     context: NSManagedObjectContext) {
        if let ent = NSEntityDescription.entity(forEntityName: "Measurement", in: context) {
            self.init(entity: ent, insertInto: context) // Thread 10: EXC_BAD_ACCESS (code=1, address=0xfffffffc)
            self.fromDatetime = fromDatetime
            self.pm10 = pm10
            // omitted value asignments
        } else {
            fatalError("Unable to find entity name Measurement")
        }
    }
}

在for循环中调用api后发生插入。

    let task = session.dataTask(with: request) { (data, response, error) in
        // if an error occurs, print it and re-enable the UI
        func displayError(_ error: String) {
            print(error)
        }

        /* GUARD: Was there an error? */
        guard (error == nil) else {
            displayError("There was an error with your request: \(String(describing: error))")
            return
        }

        /* GUARD: Did we get a successful 2XX response? */
        guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 else {
            displayError("Your request returned a status code other than 2xx!")
            return
        }

        /* GUARD: Was there any data returned? */
        guard let data = data else {
            displayError("No data was returned by the request!")
            return
        }

        // parse the data
        let parsedResult: [[String:AnyObject]]!
        do {
            parsedResult = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [[String:AnyObject]]
        } catch {
            displayError("Could not parse the data as JSON: '\(data)'")
            return
        }
        let delegate = UIApplication.shared.delegate as! AppDelegate
        let stack = delegate.stack
        var counter = 0
        for measurement in parsedResult {

            if counter == 0 {
                print(measurement)
            }

            guard let sensorId = measurement[Constants.MeasurementModelKeys.sensorId] as? Int32 else {
                print("Cannot find key 'sensor_id' in \(measurement)")
                continue
            }

            // other guarded assignments ...

            _ = Measurement(sensorId: sensorId, fromDatetime: fromDatetime, pm10: pm10, pm25: pm25,
                            airQualityIndex: airQualityIndex, pollutionLevel: pollutionLevel, latitude: latitude, longitude: longitude,
                            source: source, windDeg: windDeg, windSpeed: windSpeed,
                            context: stack.context) // << this is where the insertion happens

            counter += 1
        }
        print("counter counted: \(counter) elements")

    }

    // start the task!
    task.resume()
}

非常感谢任何帮助(包括如何追踪错误的确切原因的提示)。

1 个答案:

答案 0 :(得分:1)

核心数据在线程方面确实非常敏感。应在该上下文队列中执行在上下文中插入新对象。

试试这个:

/Job/Step/Category/Item[@name='NumberOfEngines' and @commarea='Y']

请注意,现在这是一个异步调用。确保这不会在其他地方破坏您的代码。