核心数据:即使在手动故障并在大型mb文件的xml解析期间执行托管对象重置后,内存仍未释放

时间:2017-06-10 14:06:43

标签: core-data

我正在使用NSXMLParser解析大型kml文件(18 MB)并同时存储核心数据中每个位置的坐标,我观察到的是在解析文件内存堆积的3/4并且应用程序崩溃后内存未被释放,我已经尝试了stackoverflow上给出的大部分答案,但没有用。任何帮助都受到欢迎。

    var currentElement : String = ""
var place:Place?
var polygon:Polygon?
var placeName = ""
var shouldAddCoordinates = false
private lazy var privateManagedObjectContext: NSManagedObjectContext = {
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext.persistentStoreCoordinator
    return managedObjectContext
}()
override init() {
    super.init()
}

// Xml Parser delegate methods

func parserDidStartDocument(_ parser: XMLParser) {
    print("..Xml parsing has started")
}

func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
    currentElement = elementName
    if elementName == "Placemark" {
        place = NSEntityDescription.insertNewObject(forEntityName: "Place", into: privateManagedObjectContext) as? Place
        place?.placeName = ""
    }
    if elementName == "Polygon" {
        polygon = NSEntityDescription.insertNewObject(forEntityName: "Polygon", into: privateManagedObjectContext) as? Polygon
        let fetchRequest = NSFetchRequest<Place>(entityName: "Place")
        fetchRequest.predicate = NSPredicate(format: "placeName == %@", placeName)
        do{
            let fetchResult = try privateManagedObjectContext.fetch(fetchRequest) as [Place]
            polygon?.place = place
            polygon?.placeName = placeName
            shouldAddCoordinates = fetchResult.first?.placeName == placeName  ? true:false
        }
        catch{}
    }
    if elementName == "coordinates" {
        let fetchRequest = NSFetchRequest<Place>(entityName: "Place")
        fetchRequest.predicate = NSPredicate(format: "placeName == %@", placeName)
        let fetchResult = try? privateManagedObjectContext.fetch(fetchRequest) as [Place]
        shouldAddCoordinates = fetchResult?.first?.placeName == placeName  ? true:false
    }
    if elementName == "name"{
        placeName = ""
    }
}

func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
    currentElement = elementName
    if elementName == "coordinates" {
        let fetchRequest = NSFetchRequest<Place>(entityName: "Polygon")
        let sortDescriptor = NSSortDescriptor(key: "polygonID", ascending: true )
        fetchRequest.sortDescriptors = [sortDescriptor]
        let fetchResult = try? privateManagedObjectContext.fetch(fetchRequest as! NSFetchRequest<NSFetchRequestResult>) as! [Polygon]
        if fetchResult?.count == 0{
            polygon?.polygonID = 1
        }
        else{
            polygon?.polygonID = Int64(fetchResult!.count)
        }
        polygon?.place = place
    }
    if elementName == "coordinates" || elementName == "Polygon" || elementName == "name"{
        if self.privateManagedObjectContext.hasChanges{
            privateManagedObjectContext.performAndWait {
                do{
                    try self.privateManagedObjectContext.save()
                }
                catch{}
            }
        }
    }
    else if elementName == "Placemark"{
        placeName = ""
        privateManagedObjectContext.performAndWait {
            do{
                try self.privateManagedObjectContext.save()
            }
            catch{}
        }
        privateManagedObjectContext.reset()
    }
}

func parser(_ parser: XMLParser, foundCharacters string: String) {
    if currentElement == "name" {
        if string == "\n" {
            return
        }
        place?.placeName? += string
        placeName += string
    }
    if currentElement == "coordinates"{
        if shouldAddCoordinates {
            privateManagedObjectContext.performAndWait{
                if string == "\n" {
                    return
                }
                else{
                let coordinates = NSEntityDescription.insertNewObject(forEntityName: "Coordinates", into: self.privateManagedObjectContext) as! Coordinates
                let longitude = (string.components(separatedBy: ",") as [NSString]).first!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) as NSString
                let latitude = (string.components(separatedBy: ",") as [NSString]).last!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) as NSString
                let latitudeDegrees : CLLocationDegrees = latitude.doubleValue
                let longitudeDegrees: CLLocationDegrees = longitude.doubleValue
                coordinates.latitude = latitudeDegrees as NSNumber?
                coordinates.longitude = longitudeDegrees as NSNumber?
                coordinates.coordinatesDate = Date() as NSDate
                coordinates.polygon = self.polygon
                print("\(String(describing: coordinates.polygon?.placeName!)) has coordinates \(coordinates.latitude!),\(coordinates.longitude!)")
                }
            }
        }
    }
}


func parserDidEndDocument(_ parser: XMLParser) {
    print("..Parser has finished parsing..")
}

func getManagedObject() -> NSManagedObjectContext{
    let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
    return managedObjectContext
}

func saveCoordinates(){
    let url = Bundle.main.url(forResource: "IND_adm1_1", withExtension: "kml")
    let xmlParser = XMLParser(contentsOf: url!)
    xmlParser?.delegate = self
    _ = xmlParser?.parse()
}

0 个答案:

没有答案