Проблема с утечкой памяти при использовании формы Eureka - PullRequest
0 голосов
/ 16 декабря 2018

Я работаю над приложением "Менеджер паролей".В RootVC (VC - View Controller) у меня есть таблица с сохраненными паролями.Нажав на пароль в строке, я открываю второй VC с именем EditPasswordVC, который содержит детали пароля.Пароли хранятся в Core Data (PasswordModel).И это работает, но моя память продолжает увеличиваться, когда я открываю пароль, после просмотра пароля возвращаюсь, затем снова открываю тот же или другой пароль, и моя память продолжает увеличиваться.Зачем?

Здесь вы можете увидеть мою проблему: enter image description here

RootVC:

import UIKit
import CoreData
import SVProgressHUD

class ResponsiveView: UIView {
    override var canBecomeFirstResponder: Bool {
        return true
    }
}

class RootVC: UITableViewController {

    var passwordsArray = [PasswordModel]()

    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    @IBOutlet weak var addBarButton: UIBarButtonItem!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated: Bool) {
        loadPasswords()
        SVProgressHUD.dismiss()
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return passwordsArray.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "RootCell", for: indexPath)
        cell.textLabel?.text = passwordsArray[indexPath.row].title
        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let editPasswordVC = EditPasswordVC()
        editPasswordVC.passwordData = passwordsArray[indexPath.row]
        self.navigationController?.pushViewController(editPasswordVC, animated: true)

    }

    override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let delete = UIContextualAction(style: .normal, title: "Delete") { (action, sourceView, completionHandler) in
            self.createConfirmDeletingAlertMessage(indexPath: indexPath)

        }
        delete.backgroundColor = .red
        delete.image = UIImage(named: "delete-icon")

        let swipeAction = UISwipeActionsConfiguration(actions: [delete])
        swipeAction.performsFirstActionWithFullSwipe = false // This line disables full swipe

        return swipeAction
    }

    private func loadPasswords() {
        let request: NSFetchRequest<PasswordModel> = PasswordModel.fetchRequest()
        do {
            passwordsArray = try context.fetch(request)
        } catch {
            print("error load \(error)")
        }
        self.tableView.reloadData()
    }

    private func createConfirmDeletingAlertMessage(indexPath: IndexPath) {
        let alertVC = UIAlertController(title: "Confirm deleting password!", message: "", preferredStyle: .alert)

        let deleteAction = UIAlertAction(title: "DELETE", style: .default, handler: { (saveAction) in
            self.deletePassword(indexPath: indexPath.row)
            self.tableView.deleteRows(at: [indexPath], with: UITableView.RowAnimation.automatic)
        })
        let cancelAction = UIAlertAction(title: "CANCEL", style: .default, handler: nil)

        alertVC.addAction(deleteAction)
        alertVC.addAction(cancelAction)
        self.present(alertVC, animated: true, completion: nil)
    }

    private func deletePassword(indexPath: Int) {
        self.context.delete(self.passwordsArray[indexPath])
        self.passwordsArray.remove(at: indexPath)
        do {
            try self.context.save()
        } catch {
            print("error save in root vc \(error)")
        }
    }

}

Это EditPasswordVC:

import Foundation
import Eureka
import GenericPasswordRow
import SVProgressHUD

protocol EditPasswordVCDelegate {
    func editDidEnd()
}

class EditPasswordVC: FormViewController {

    var passwordData: PasswordModel!

    override func willMove(toParent parent: UIViewController?) {
        super.willMove(toParent: parent)
        if parent == nil{
            self.navigationController?.isToolbarHidden = false
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        setupView()
        initElements()
    }

    override func viewWillDisappear(_ animated: Bool) {
        self.navigationController?.popViewController(animated: true)
        dismiss(animated: true, completion: nil)
    }

    private func setupView() {
        self.title = "Password detail"
        self.navigationController?.isToolbarHidden = true
        self.hideKeyboardWhenTappedAround()

        navigationOptions = RowNavigationOptions.Disabled

        createBarButtonItems()
    }

    private func createBarButtonItems() {
        let editButton = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(editButtonPressed))
        self.navigationItem.rightBarButtonItem = editButton
    }

    private func initElements() {

        form +++ Section("Password information") {
            $0.header?.height = { 40 }
        }

        <<< CustomTextCellRow() {
            $0.tag = RowTags.rowTitleTag.rawValue
        }.cellSetup({ (titleCell, titleRow) in
            titleCell.setupTitleCell()
            titleCell.setupNonEditCell()
            titleCell.textFieldCustomTextCell.text = self.passwordData.title
        })

        <<< WebPageCellRow() {
            $0.tag = RowTags.rowWebPageTag.rawValue
        }.cellSetup({ (webPageCell, webPageRow) in
            webPageCell.setupNonEditCell()
            webPageCell.textFieldWebPage.text = self.passwordData.webPage
        })

        <<< CustomTextCellRow() {
            $0.tag = RowTags.rowEmailTag.rawValue
        }.cellSetup({ (emailCell, emailRow) in
            emailCell.setupEmailCell()
            emailCell.setupNonEditCell()
            emailCell.textFieldCustomTextCell.text = self.passwordData.email
        })

        <<< CustomTextCellRow() {
            $0.tag = RowTags.rowUsernameTag.rawValue
        }.cellSetup({ (usernameCell, usernameRow) in
            usernameCell.setupUsernameCell()
            usernameCell.setupNonEditCell()
            usernameCell.textFieldCustomTextCell.text = self.passwordData.username
        })

        +++ Section("Enter password") {
            $0.header?.height = { 20 }
        }

        <<< GenericPasswordRow() {
            $0.tag = RowTags.rowPasswordTag.rawValue
        }.cellSetup({ (passwordCell, passwordRow) in
            passwordCell.setupPasswordCell()
            passwordCell.setupNonEditRow()
            passwordCell.textField.text = self.passwordData.password
            passwordCell.updatePasswordStrenghtAndTextFieldDidChange()
        })

    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        if let customTextCell = tableView.cellForRow(at: indexPath) as? CustomTextCell {
            UIPasteboard.general.string = customTextCell.textFieldCustomTextCell.text
            SVProgressHUD.showInfo(withStatus: "Copied To Clipboard")
            SVProgressHUD.dismiss(withDelay: 1)
        } else if let genericPasswordCell = tableView.cellForRow(at: indexPath) as? GenericPasswordCell {
            UIPasteboard.general.string = genericPasswordCell.textField.text
            SVProgressHUD.showInfo(withStatus: "Copied To Clipboard")
            SVProgressHUD.dismiss(withDelay: 1)
        } else {
            let webPageCell = tableView.cellForRow(at: indexPath) as? WebPageCell
            guard let url = URL(string: webPageCell!.textFieldWebPage.text ?? "https://") else { return }
            UIApplication.shared.open(url)
        }

        tableView.deselectRow(at: indexPath, animated: false)
    }

}

Это ссылка на след моего инструмента.Что я делаю не так?

Спасибо

1 Ответ

0 голосов
/ 12 июня 2019

Изменение объявления UIContextualAction с помощью обработчика аргумента решит проблему с памятью.Ниже приведены необходимые модификации.

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let delete = UIContextualAction(style: .normal, title: "Delete", handler: { (action, sourceView, completionHandler) in
        self.createConfirmDeletingAlertMessage(indexPath: indexPath)

    }) 
    delete.backgroundColor = .red
    delete.image = UIImage(named: "delete-icon")

    let swipeAction = UISwipeActionsConfiguration(actions: [delete])
    swipeAction.performsFirstActionWithFullSwipe = false // This line disables full swipe

    return swipeAction
}
...