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

Я выполняю вызов API в Firebase для получения информации о профиле пользователя и сохранения ее в переменной-члене ViewController. API объявлен как статическая функция внутри класса MyApi:

// Get User Profile
    static func getUserProfile(byID userId:String,response:@escaping (_ result:[User]?,_ error:Error?)->()) {

        // check ID is valid
        guard userId.length > 0 else {
            print("Error retrieving Creator data: invalid user id provided")
            response(nil,ApiErrors.invalidParameters)
            return
        }

        // retrieve profile
        let profilesNode = Database.database().reference().child(MyAPI.profilesNodeKey)
        profilesNode.child(userId).observe(.value, with: { (snapshot) in
            // check if a valid data structure is returned
            guard var dictionary = snapshot.value as? [String:AnyObject] else {
                print("Get User Profile API: cannot find request")
                response([],nil)
                return
            }

            // data mapping
            dictionary["key"] = userId as AnyObject
            guard let user = User(data:dictionary) else {
                print("Get User Profile API: error mapping User profile data")
                response(nil,ApiErrors.mappingError)
                return
            }
            response([user], nil)
        }) { (error) in
            response(nil,ApiErrors.FirebaseError(description: error.localizedDescription))
        }
    }

и я так называю:

MyAPI.getUserProfile(byID: creatorId) { (profiles, error) in
            guard let profiles = profiles, profiles.count > 0 else {
                Utility.showErrorBanner(message: "Error retrieving Creator profile")
                print("Error retrieving creator profile ID:[\(creatorId)] \(String(describing: error?.localizedDescription))")
                return
            }
            self.currentProfile = profiles.first!
        }

ViewController вызывается в модальном режиме, поэтому его следует освобождать при каждом выходе из экрана.

Проблема : огромный кусок памяти выделяется при входе на экран, но он не освобождается при выходе из него. Я уверен в этом, потому что проблема не появляется, если я уберу строку self.currentProfile = profiles.first! (очевидно)

Как я могу избежать этого?

ПРИМЕЧАНИЕ : currentProfile относится к типу User, который раньше был struct. Я сделал это классом, чтобы использовать слабую ссылку для хранения информации:

weak var currentCreator: User? {
        didSet {
            updateView()
        }
    }

но проблема все еще сохраняется.

1 Ответ

3 голосов
/ 11 марта 2019

Вы добавляете наблюдателя:

profilesNode.child(userId).observe(...)

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

Если вы хотите читать данные только один раз , для этого есть другой API, использующий наблюдающий единый .

...