Подтвердить что ты не робот

Утеплители памяти Alamofire Инструменты

Я пытаюсь очистить свое приложение от утечек памяти, и у меня есть несколько проблем, понимающих это.

введите описание изображения здесь

  • Почему функция Alamofire Request.serializeResponseJSON вызывается через 30 секунд после запуска приложения: я ничего не трогал и не перемещался в любом месте, экран был статичным.

  • Почему это происходит?

  • Почему мой код протекает?

Я получаю те же утечки при загрузке экрана.

Что я пробовал до сих пор:

  • Autoreleasepool;

  • Добавление и инициализация массивов всеми возможными способами;

  • Изменение переменной (class, func), которая будет необязательной/нет по желанию/слабая;

  • Инициализация классов в UIViewController;

  • Инициализация классов в основном потоке;

  • Поиск этих проблем в Интернете.

  • Я обнаружил, используя инструмент памяти Xcode, что он каким-то образом связан с _ContiguousArrayStorage, но я не понимаю, как и что это на самом деле. введите описание изображения здесь

Я не понимаю, что здесь не так. Любые советы будут высоко оценены.

Вот все связанный код: Мой общий запрос 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?)
    }
}

Мой экранный запрос

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)
    }
}

Мои классы (я знаю, что такая инициализация неправильна, но я изменился на init(data: JSON) - не помог:

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
}

Массив этих утечек:

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
  }
}
4b9b3361

Ответ 1

Вы пробовали задавать время URLCache для запроса, это приведет к удалению кэша запроса и освобождению памяти