избегая сохранения циклов для UITableView, сделанного программно из ViewController, который является потомком другого ViewController - PullRequest
0 голосов
/ 04 июня 2018

У меня есть ViewController с именем MainViewController, который выступает в качестве центральной страницы приложения.Этот MainViewController имеет 6 свойств, которые являются экземплярами других viewController

lazy var shelvesView: ShelvesViewController = {
    return ShelvesViewController()
}()
lazy var goalsView: GoalsViewController = {
    return GoalsViewController()
}()
lazy var shoppingView: ShoppingListViewController = {
    return ShoppingListViewController()
}()
lazy var tipsView: TipsViewController = {
    return TipsViewController()
}()
lazy var myDenView: MyDenViewController = {
    return MyDenViewController()
}()
lazy var settingsview: SettingsViewController = {
    return SettingsViewController()
}()

, когда mainViewController загружается, он запускается с полкамиViewView Controller, наложенными на него прямо под пользовательским NavBar mainViewControllers, как, например,

func setupShelvesView() {
    shelvesView.willMove(toParentViewController: self)
    addChildViewController(shelvesView)
    self.view.addSubview(shelvesView.view)
    shelvesView.view.frame = CGRect(x: 0, y: view.frame.height * 0.08, width: view.frame.width, height: view.frame.height - (view.frame.height * 0.08))
    shelvesView.didMove(toParentViewController: self)
    globalCurrentView = 1
}

У меня также есть меню, которое скользит по этому mainViewController со списком различных страниц, на которые пользователь может перейти.когда пользователь переключается на новую страницу, например, goalViewController, shelvesViewController будет анимирован за пределами экрана, удаляется из parentViewController (MainViewController), а goalViewController будет инициализироваться, перемещаться в MainViewController и анимироваться на экране в том же фрейме, что и shelvesView.Каждый раз, когда я переключаю VC из меню, я использую этот метод.

func changeVCfrom(OldVC oldVC: UIViewController, newVC: UIViewController) {

    let newStartFrame = CGRect(x: 0 + self.view.frame.width, y: 0, width: view.frame.width, height: view.frame.height - (view.frame.height * 0.08))

    let newEndframe = CGRect(x: 0, y: view.frame.height * 0.08, width: view.frame.width, height: view.frame.height - (view.frame.height * 0.08))

    let oldfinishFrame = CGRect(x: 0 - self.view.frame.width, y: 0, width: self.view.frame.width, height: self.view.frame.height)

    oldVC.willMove(toParentViewController: nil)
    self.addChildViewController(newVC)
    newVC.view.frame = newStartFrame


    transition(from: oldVC, to: newVC, duration: 0.2, options: [.curveEaseOut], animations: {
        oldVC.view.frame = oldfinishFrame
        newVC.view.frame = newEndframe
    }, completion: { (success) in
        oldVC.willMove(toParentViewController: nil)
        oldVC.view.removeFromSuperview()
        oldVC.removeFromParentViewController()
        newVC.willMove(toParentViewController: self)
        self.view.addSubview(newVC.view)
    })
}

проблема здесь в том, что я сделал все свои представления программно и любой из вышеупомянутых viewControllers (ленивых свойств), у которых есть свойство tableView нау них утечка памяти.каждый раз, когда виртуальный контроллер отключается от MainViewController, память, используемая для tableView, не освобождается, и каждый раз, когда он возвращается к MainViewController, он снова выделяется для дополнительной памяти.

на данный момент, как это было раньшенастройка моих tableViews

let tableView = UITableView()

override func viewDidLoad() {
    super.viewDidLoad()
    setupObjects()
    tableView.register(ShelfTableViewCell.self, forCellReuseIdentifier: "shelfCell")
}
func setupTableView() {
    view.addSubview(tableView)
    tableView.delegate = self
    tableView.dataSource = self
    setupTableViewConstraints()
}
func setupTableViewConstraints() {
    tableView.translatesAutoresizingMaskIntoConstraints = false
    tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
    tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
}

Я понимаю, что мне нужно, чтобы мои view таблицы были слабыми, неизвестными или каким-то образом заставляли view table полностью освобождаться, когда находились вне экрана.но что бы я ни пытался, я получаю ошибки повсюду, которые я не могу разрешить, или мой ViewController не может загрузить просмотр таблицы.Я прошу прощения за длинный вопрос, но любая помощь по этому вопросу будет очень признателен.

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

при прокрутке таблицы вверх и вниз. Вид моей памяти резко увеличится.Оказывается, я неправильно настроил dequeReusableCell.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = ShelfTableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: "shelfCell")
    tableView.dequeueReusableCell(withIdentifier: "shelfCell", for: indexPath)
    if let shelf = UserController.shared.user?.shelves?[indexPath.row] as? Shelf {
        cell.shelf = shelf
        return cell
    } else {
        return UITableViewCell()
    }
}

По сути, каждый раз, когда происходило обращение к viewWillAppear, я перезагружал tableViewData, который выполнял этот код

    let cell = ShelfTableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: "shelfCell")
    tableView.dequeueReusableCell(withIdentifier: "shelfCell", for: indexPath)

, что приводило к замене утечки памяти

вышеуказанный код с последующим разрешил проблему

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "shelfCell", for: indexPath) as! ShelfTableViewCell
    if let shelf = UserController.shared.user?.shelves?[indexPath.row] as? Shelf {
        cell.shelf = shelf
        return cell
    } else {
        return UITableViewCell()
    }
}
0 голосов
/ 04 июня 2018

Табличные представления не освобождаются, когда ваши дочерние контроллеры представления уходят с экрана.

Ваш MainViewController владеет этими другими контроллерами представления.Да, они ленивы, но как только их вызывают в первый раз, они инициализируются вместе с собственными представлениями таблиц.

Контроллеры дочерних представлений не освобождаются, просто перемещая их за пределы экрана.Все, что вы делаете, это изменяете фрейм и удаляете их как дочерний контроллер представления MainViewController.Так как они все еще находятся в памяти, табличное представление также все еще находится в памяти.

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

self.tableView = nil

Здесь не должно быть цикла сохранения, поскольку свойства источника данных и делегата tableView равны weak, что означает, что они не увеличивают счетчик ссылок контроллера представления.

...