2017-01-11 71 views
13

Próbuję oczyścić moją aplikację z wycieków pamięci i mam kilka problemów ze zrozumieniem tegopamięć Alamofire przecieki Instruments

enter image description here

  • Dlaczego Alamofire funkcja Request.serializeResponseJSON nazywa się 30 sekund po tym, jak rozpoczęła Aplikacja: niczego nie dotykałem ani nie nawigowałem w dowolnym miejscu, ekran był statyczny.

  • Dlaczego to wycieka?

  • Dlaczego mój kod wycieka?

Te same wycieki pojawiają się po załadowaniu ekranu.

Co próbowałem dotąd:

  • Autoreleasepool;

  • Dołączanie i inicjowanie tablic w każdy możliwy sposób;

  • Zmiana wszystkich zmiennych (class, func) na opcjonalne/nie opcjonalne/słabe;

  • Inicjowanie klas w UIViewController;

  • Inicjowanie zajęć w wątku głównym;

  • Wyszukiwanie tych problemów w Internecie.

  • Dowiedziałem się, używając narzędzia pamięci Xcode, że jest ono w jakiś sposób powiązane z _ContiguousArrayStorage, ale nie rozumiem, jak i czym jest to naprawdę. enter image description here

Jestem z wszelkich pomysłów, co jest nie tak tutaj. Wszelkie wskazówki będą mile widziane.

Oto cały kod związany: Moje ogólne żądanie API

public func requestWithLocation(_ httpmethod: Alamofire.HTTPMethod, URL: String, parameters: [String: AnyObject]?, completionHandler: @escaping CompletionHandler) ->(){ 
    var header: HTTPHeaders = [:] 
    var location: [String: Double] = [:] 
    let locationManager = CLLocationManager() 

    if (CLLocationManager.authorizationStatus() == .authorizedWhenInUse 
     || CLLocationManager.authorizationStatus() == .authorizedAlways) && locationManager.location != nil { 
     location = [ 
      "lon" : locationManager.location!.coordinate.longitude, 
      "lat" : locationManager.location!.coordinate.latitude 
     ] 
    } 

    if User.sharedInstance.token != "" { 
     header["Authorization"] = User.sharedInstance.token 
    } 

    var parametersWithLocation = parameters ?? [:] 
    parametersWithLocation["location"] = location as AnyObject 

    Alamofire.request("\(serverAddress)/\(URL)", method: httpmethod, parameters: parametersWithLocation, encoding: JSONEncoding.default, headers: header).validate().responseJSON { response in 
     var data: JSON? 

     if response.result.value != nil { 
      data = JSON(response.result.value!) 
     } 
     if User.sharedInstance.token == "" { 
      User.sharedInstance.token = response.response?.allHeaderFields["Authorization"] as! String 
     } else { 
      if let header = response.response?.allHeaderFields["Authorization"] as? String { 
       if User.sharedInstance.token != header { 
        User.sharedInstance.token = header 
       } 
      } 
     } 
     completionHandler(data, response.result.error as NSError?) 
    } 
} 

Moja prośba ekran

class func requestMainScreen(handler: @escaping ([ShortRestaurant], [ShortRestaurant], [ShortRestaurant]) ->()) { 
    var dataForBestChoise: [ShortRestaurant] = [] 
    var dataForTop: [ShortRestaurant] = [] 
    var dataForNearest: [ShortRestaurant] = [] 

    let group = DispatchGroup() 
    group.enter() 

    APIModel.sharedInstance.requestWithLocation(.post, URL: "restaurants/near", parameters: nil, completionHandler: {(data, error) in 

     guard let `data` = data else { 
      group.leave() 
      return 
     } 
     for JSON in data["restaurants"].arrayValue { 
      dataForNearest.append(ShortRestaurant.initFromJSON(JSON)) //here is leak 
     } 
     group.leave() 
    }) 

    group.enter() 
    APIModel.sharedInstance.requestWithLocation(.post, URL: "restaurants/top", parameters: nil, completionHandler: {(data, error) in 
     guard let `data` = data else { 
      group.leave() 
      return 
     } 
     for JSON in data["restaurants"].arrayValue { 
      dataForTop.append(ShortRestaurant.initFromJSON(JSON))//here is leak 
     } 
     group.leave() 
    }) 

    group.enter() 
    APIModel.sharedInstance.requestWithLocation(.post, URL: "restaurants/personal", parameters: nil, completionHandler: {(data, error) in 

     guard let `data` = data else { 
      group.leave() 
      return 
     } 

     for JSON in data["restaurants"].arrayValue { 
      dataForBestChoise.append(ShortRestaurant.initFromJSON(JSON)) //here is leak 
     } 
     group.leave() 
    }) 

    group.notify(queue: DispatchQueue.main) { 
     handler(dataForBestChoise, dataForTop, dataForNearest) 
    } 
} 

moich klas (znam ten rodzaj inicjalizacji jest trochę źle, ale bym zmienił do init(data: JSON) - nie pomogło:

class func initFromJSON(_ data: JSON) -> ShortRestaurant { 
    let restaurant = ShortRestaurant() 
    restaurant.id      = data["id"].stringValue 
    restaurant.name      = data["name"].stringValue 
    restaurant.image     = data["img"].stringValue 
    restaurant.description    = data["shortDesc"].stringValue 
    restaurant.nameOfMetrostatin  = data["address"]["metro"]["name"].stringValue 
    restaurant.mapType     = data["mapType"].stringValue 
    restaurant.address     = data["address"]["street"].stringValue 
    restaurant.longitude    = data["address"]["location"][0].doubleValue 
    restaurant.latitude     = data["address"]["location"][1].doubleValue 
    restaurant.phone     = data["phone"].stringValue 
    restaurant.workTime     = data["currentWork"].stringValue 
    restaurant.avarageBill    = data["price"].stringValue 
    restaurant.peopleInfo    = data["croud"].stringValue 
    restaurant.rating     = data["rating"].stringValue 
    restaurant.ratingTrend    = data["trend"].stringValue 
    restaurant.distance     = data["distance"].doubleValue 
    restaurant.isFavourited    = data["isFavourited"].bool ?? false 
    restaurant.specialOfferDescription = data["discounts"]["name"].string 
    restaurant.specialOfferName   = data["discounts"]["type"].string 
    restaurant.alertText    = data["label"]["name"].string 
    restaurant.alertIcon    = data["label"]["type"].string 
    restaurant.alertBackground   = data["label"]["color"].string 
    restaurant.avaliableDates   = ReservationSchedule.initArrayFrom(data: data["availableDates"]) 
    restaurant.avaliableTimes   = data["scheduleRes"].arrayObject as? [String] ?? [] 
    restaurant.doesHaveDiscount   = data["discounts"]["id"].string != nil 
    restaurant.doesHaveEvent   = data["events"]["id"].string != nil 
    restaurant.weeklyTop    = data["weeklyTop"].bool ?? false 
    restaurant.monthlyTop    = data["monthlyTop"].bool ?? false 
    restaurant.yearTop     = data["yearTop"].bool ?? false 
    restaurant.isActive     = data["isActive"].bool ?? true 
    return restaurant 
} 

Array tych przecieków:

class ReservationSchedule { 
    var description: String 
    var data: String 
    var dayTitle: String 
    var fullTitle: String 

    init(data: JSON) { 
    self.data = data["value"].stringValue 
    self.dayTitle = data["day"].stringValue 
    self.description = data["label"].stringValue 
    self.fullTitle = data["title"].stringValue 
    } 

    class func initArrayFrom(data: JSON) -> [ReservationSchedule] { 
    var schedule: [ReservationSchedule] = [] 
    for day in data.arrayValue { 
     schedule.append(ReservationSchedule.init(data: day)) //here is leak 
    } 
    return schedule 
    } 
} 

Odpowiedz

0

Czy próbowano ustawienie URLCache czasu żądania, będzie to usunięcie cache życzenie i za darmo jest pamięć