2016-03-31 7 views
0

Ich verwende eine Master-Detail-Anwendung. Master-Screen ist ein Armaturenbrett und ein Elements zur Auswahl, bewegt sich auf den detaillierten Bildschirm, wo ich löse eine Alamofire Anfrage im BackendAlamofire-Anforderung gibt Speicher Warnung

unten ist der Schnipsel

class APIManager: NSObject { 

    class var sharedManager: APIManager { 
     return _sharedManager 
    } 

    private var requests = [Request]() 

    // Cancel any ongoing download 
    func cancelRequests() { 
     if requests.count > 0 { 
      for request in requests { 
       request.cancel() 
      } 
     } 
    } 

    func getData(completion: (dataSet: [Data]?, error: NSError?) -> Void) { 
     let request = Alamofire.request(.GET, "http://request") 
      .response { (request, response, data, error) in 
       dispatch_async(dispatch_get_main_queue(), { 
        if(error == nil) { 
         if let response = data, data = (try? NSJSONSerialization.JSONObjectWithData(response, options: [])) as? [NSDictionary] { 

          var dataSet = [Data]() 
          for (_, dictionary) in data.enumerate() { 
           let lat = dictionary["Latitude"] 
           let lng = dictionary["Longitude"] 
           let id = dictionary["ID"] as! Int 
           let data = Data(lat: lat!, long: lng!, id: shuttleID) 
           dataSet.append(data) 
          } 
          completion(dataSet: dataSet, error: nil) 
         } 
        } else { completion(dataSet: nil, error: error) } 
       }) 
     } 
     requests.append(request) 
    } 
} 

ich eine Singleton API-Managerklasse habe und von der Detailansicht Controller Ich rufe getData() Funktion. Alles funktioniert gut.

Aber wenn ich wiederholt drücken und poppen, sehe ich einen schnellen Anstieg im Speicher und nach 10-15 Versuchen bekomme ich Speicherwarnung. In der AppDelegate verwalte ich es jedoch, eine Warnmeldung anzuzeigen und einen Verzögerungs-Timer für 8 Sekunden hinzuzufügen. Aber nach 20-25 Versuchen stürzt App wegen Speicherwarnung ab.

In viewWillDisappear() storniere ich alle laufenden Anfragen auch. Aber ich konnte das Speicherwarnungsproblem nicht stoppen. Ich habe den Teil kommentiert, an dem ich die Anfrage anrufe, ich sehe keine Probleme, selbst der Speicherverbrauch ist geringer.

Ich begrüße Ideen.

Antwort

0

Bei der Analyse fand ich, dass die Speicher Warnung an die zurückzuführen war Alamofire Anfrage. Es war wegen MKMapView. Wenn Sie eine MKMapView laden, vergrößert und verkleinert Sie mehr Speicher. Also, in viewWillDisappear habe ich den Fehler behoben.

override func viewWillDisappear(animated:Bool){ 
    super.viewWillDisappear(animated) 
    self.applyMapViewMemoryFix() 
} 

func applyMapViewMemoryFix(){ 
    switch (self.mapView.mapType) { 
     case MKMapType.Hybrid: 
      self.mapView.mapType = MKMapType.Standard 
      break; 
     case MKMapType.Standard: 
      self.mapView.mapType = MKMapType.Hybrid 
      break; 
     default: 
      break; 
    } 
    self.mapView.showsUserLocation = false 
    self.mapView.delegate = nil 
    self.mapView.removeFromSuperview() 
    self.mapView = nil 
} 

Höflichkeit - Stop iOS 7 MKMapView from leaking memory

0

Das Problem besteht darin, dass Sie nie die Anforderungen entfernen, die Sie an die Mitgliedsvariable "Anforderungen" anfügen.

Sie müssen sicherstellen, dass die Anforderung entfernt wird, wenn Sie sie entweder abbrechen oder wenn die Anforderung erfolgreich ausgeführt wird.

Sie die folgende modifications-

func cancelRequests() { 
     if requests.count > 0 { 
      for request in requests { 
       request.cancel() 
      } 
     } 
     requests.removeAll() //Delete all canseled requests 
    } 

also 

func getData(completion: (dataSet: [Data]?, error: NSError?) -> Void) { 
     let request = Alamofire.request(.GET, "http://request") 
      .response { (request, response, data, error) in 
       dispatch_async(dispatch_get_main_queue(), { 
        if(error == nil) { 
         if let response = data, data = (try? NSJSONSerialization.JSONObjectWithData(response, options: [])) as? [NSDictionary] { 

          var dataSet = [Data]() 
          for (_, dictionary) in data.enumerate() { 
           let lat = dictionary["Latitude"] 
           let lng = dictionary["Longitude"] 
           let id = dictionary["ID"] as! Int 
           let data = Data(lat: lat!, long: lng!, id: shuttleID) 
           dataSet.append(data) 
          } 
          requests.removeObject(request) 
          completion(dataSet: dataSet, error: nil) 
         } 
        } else { 
         requests.removeObject(request) 
         completion(dataSet: nil, error: error) } 
       }) 
     } 
     requests.append(request) 
    } 

dieses handliche Erweiterung hinzufügen auf Array Element, um Ihren Code zu entfernen:

// Swift 2 Array Extension 
extension Array where Element: Equatable { 
    mutating func removeObject(object: Element) { 
     if let index = self.indexOf(object) { 
      self.removeAtIndex(index) 
     } 
    } 

    mutating func removeObjectsInArray(array: [Element]) { 
     for object in array { 
      self.removeObject(object) 
     } 
    } 
} 
Verwandte Themen