Утечка памяти при инициализации JSON с использованием SwiftyJSON - PullRequest
0 голосов
/ 20 марта 2019

Прежде всего, я новичок в графике инструментов и памяти.Попытка проверить, имеет ли утечка памяти мое приложение, тогда я сталкиваюсь с этой проблемой.Это коллекция класса с архитектурой MVVM, которая выполняет следующие функции:

  1. View Controller вызывает функцию в View Model
  2. View Model запрашивает сетевой класс для получения JSON из сетиapi
  3. Сетевой класс успешно извлекает данные из веб-API, он использует SwiftyJson для преобразования словаря в объект JSON, и происходит утечка памяти
  4. Утечка происходит в функции init SwiftyJSON, также известной как JSON ()/JSON.init()
  5. База кода представляет собой смесь target-c и swift, но классы с утечкой памяти написаны на swift

Я сделалНебольшое исследование, ниже приведены мои выводы:

  1. Создайте новый проект, скопируйте классы и попытайтесь воссоздать проблему, но утечки памяти не происходит
  2. Эта проблема возникает, только когдаВызывается замыкание и возвращает результат обратно вызывающей стороне
  3. Эта утечка также происходит в других местах, имеющих подобную структуру кода;Вызов закрытие -> закрытие сделать вызов API -> получить результат -> преобразовать в JSON -> утечка памяти.Другой случай - получение удаленной конфигурации с использованием Firebase SDK.Более подробно, функция FIRRemoteConfig.fetch

Достаточно введения, кода и снимка экрана графика и инструмента памяти, как показано ниже (класс кода довольно большой, поэтому я прикрепляю только большинствоважная часть):

Memory graph image

Instrument image

Просмотр класса контроллера

@objc final class HomeVC: UIViewController {
    internal lazy var viewModel = { return HomeVM() }()

    override func viewDidLoad() {
        initVM()
    }

    private func initVM() {
        viewModel.reloadPersonalization.addObserver(onChange: {[weak self] (reload) in
            if reload {
                self?.collectionView.reloadSections(IndexSet(integer: HomeSection.personalization.rawValue))
            }
        })
    }
}

Просмотреть модель класса

import SwiftyJSON

class HomeVM {
    //MARK:- Observable

    let reloadPersonalization = Observable<Bool>(value: false)
    let isLoading = Observable<Bool>(value: false)

    //MARK:- Properties
    var personalizations = Personalization()

    //MARK:- Initialization
    init() {

    }

    //MARK:- Functions

    public func fetchPersonalization() {
        BaseApi.requestAPIService(apiService: MainMallService.showPersonalization, resultReceive: {

        }, success: {[weak self] (json) in
            self?.personalizations.updateProductList(json: json)
            self?.reloadPersonalization.value = true
            }, successWithError: {[weak self] (errorMsg) in
                self?.reloadPersonalization.value = false
        }, fail: {[weak self] (errorMsg) in
            self?.reloadPersonalization.value = false
        })

    }
}

Сетевой класс

import Moya
import SwiftyJSON
import Alamofire

    class BaseApi {
        //MARK: Properties

        //MARK: Functions
        open class func requestAPIService(apiService: TargetType, resultReceive: @escaping () -> Void ,success: @escaping (_ jsonResponse: JSON) -> (), successWithError: @escaping (_ error: String) -> (), fail: @escaping (_ errorMsg: String) -> ()) {
            let provider = MoyaProvider<MultiTarget>(manager:NetworkManager.shared ,plugins: [NetworkLoggerPlugin(verbose: true)])
            let target = MultiTarget(apiService)

            provider.request(target) { result in
                resultReceive()

                switch result {
                case let .success(moyaResponse):
                    let data = moyaResponse.data
                    let json = JSON(data)
                    let apiStatus = ApiStatus.initWithJson(json: json["status"])

                    switch apiStatus.status {
                    case .Success:
                        if json["response"].exists() {
                            let jsonResponse = json["response"]
                            success(jsonResponse)
                        }

                    case .Failed:
                        successWithError(StringConst.Error.internalError)

                    case .Unkown:
                        fail(StringConst.Error.unknownError)
                    }

                case let .failure(error):
                    var errorMsg = ""

                    if error._code == NSURLErrorTimedOut {
                        errorMsg = StringConst.Connection.timeout
                    } else if error._code == NSURLErrorNotConnectedToInternet {
                        errorMsg = StringConst.Connection.noConnection
                    } else {
                        errorMsg = StringConst.Error.unknownError
                    }

                    fail(errorMsg)
                }
            }
        }
    }

В этой строке кода произошла утечка памяти, и график памяти, и прибор снова указывают на эту линию;Утечка происходит только при вызове блока успеха, другие блоки, такие как error и successWithError, не вызывают утечку памяти.

let json = JSON(data)

Благодарим вас за помощь!

...