【问题标题】:Dismissing ViewController doesn't deallocate memory in Swift关闭 ViewController 不会在 Swift 中释放内存
【发布时间】:2018-09-25 22:46:30
【问题描述】:

我有一个视图控制器(我们称之为 TableViewController)。当用户点击自定义 UITableViewCell 中的按钮时,一个新的视图控制器(我们称之为 DetailViewcontroller)正在打开。当用户点击 DetailViewController 内的返回按钮时,我调用了关闭函数,并且 TableViewController 再次打开。

我的问题是,当我执行 50 次这种情况时,内存使用率会更高。所以我猜它不会做任何释放。

我如何打开 DetailViewController;

    @objc func voteBtnTapped(_ sender: UIButton){
    guard let team = FirebaseManager.instance.currentTeam else { return }
    FirebaseManager.instance.delegate = nil
    let voteController = VoteViewController()
    voteController.currentTeam = team
    let transition = CATransition()
    transition.duration = 0.5
    transition.type = kCATransitionPush
    transition.subtype = kCATransitionFromRight
    transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)
    view.window!.layer.add(transition, forKey: kCATransition)
    self.present(voteController, animated: false, completion: nil)
}

我如何关闭 DetailViewController;

    @objc func backBtnTapped(_ sender: UIButton){
    FirebaseManager.instance.delegate = nil
    let transition = CATransition()
    transition.duration = 0.5
    transition.type = kCATransitionPush
    transition.subtype = kCATransitionFromLeft
    transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)
    view.window!.layer.add(transition, forKey: kCATransition)
    self.dismiss(animated: false, completion: nil)
}

它说仪器有泄漏,但我不知道是什么原因导致这些韭菜。

编辑:我发现我正在使用的选择器库(在 DetailViewController 中)阻止了释放。你知道它为什么会阻止它,我该如何处理它?

从回复回答我如何声明pickerView:

 let config = AZAPickerConfiguration<PickerItem>(items: (1...10).map { PickerItem(number: $0) },
                                                    defaultSelectedIndex: 4,
                                                    selectedFont: UIFont(name: "SourceSansPro-SemiBold", size: 50)!, nonSelectedFont:UIFont(name: "SourceSansPro-Light", size: 20)!, selectionRadiusInPercent: 0.5,
                                                    selectionBackgroundColor: UIColor(red:0.00, green:0.42, blue:0.20, alpha:1.0), itemWidth: 80)

    self.pickerView = AZAPicker<PickerItem>(with: config, frame: .zero)

    pickerView!.backgroundColor = .white
    pickerView!.translatesAutoresizingMaskIntoConstraints = false
    //self.pickerView!.onPickItem = self.picker
    self.pickerView!.onPickItem = {( sender : AZAPicker<PickerItem>,item:PickerItem) in
        print("didPickItem: \(item)")
        self.currentPoint = item.number

    }

https://github.com/AvanzaBank/AZAPicker

【问题讨论】:

  • 请使用Instruments 和分配工具,告诉我们是什么分配了这个内存
  • 我添加了。你能检查一下吗? @Lu_
  • 你在tableview中重复使用单元格吗?这都是一个字符串分配,你需要在代码中找到这个分配了这么多次
  • 你能显示 CellForRowAtIndexPath 代码吗?
  • 我添加了@Pandey_Laxman

标签: ios swift memory uiviewcontroller


【解决方案1】:

首先确保detailViewController是导致泄漏的对象。

deinit {
 print("detailViewController deallocated")
}

如果不调用 deinit 则有一个强引用保持 detailsViewController 活动。检查您是否在 detailViewController 中使用 self 而没有弱引用的闭包。或者您在 TableViewController 中保留 detailViewController 引用的地方。

【讨论】:

  • 我在 detailViewController 类中编写了它,但它没有调用。
  • @EmreÖnder 通常这可能是由 3 件事引起的,1- 一个声明为强的委托,一个没有 [weak self] 的闭包和 3 另一个持有这个 viewController 和这个 viewController 的强引用的 viewController强烈引用该 viewController 检查这个答案也许可以帮助你stackoverflow.com/questions/49814852/…
  • 我编辑我的问题。你能检查一下吗? @ReinierMelian
  • @EmreÖnder 你是对的,我会在 github repo 上提出问题并推送解决方案
  • 我打开了一个问题,但实际上没有足够的时间。我宁愿删除该库并自己编写一个新库或找到解决方案。我已经尝试将库中的委托从 var 更改为弱 var 但没有奏效。你能检查一下源代码吗?如果你能找到一些东西:) 谢谢。
【解决方案2】:

那个库好像在使用形式上有错误,在示例代码中声明了这样的方法

func picker(sender: AZAPicker<PickerItem>, item: PickerItem) {
    print("didPickItem: \(item)")
}

但您需要以这种方式分配闭包并问题已解决

已更新(在您的代码中)

self.pickerView!.onPickItem = {[weak self]( sender : AZAPicker<PickerItem>,item:PickerItem) in
    print("didPickItem: \(item)")
    self.currentPoint = item.number

}

完整代码参考

class ViewController: UIViewController {

    @IBAction func dismiss(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
    }
    override func viewDidLoad() {
        super.viewDidLoad()

        let config = AZAPickerConfiguration<PickerItem>(items: (1...100).map { PickerItem(number: $0) },
                                           defaultSelectedIndex: 99,
                                           selectionRadiusInPercent: 0.5,
                                           itemWidth: 80)

        let pickerView = AZAPicker<PickerItem>(with: config, frame: .zero)

        pickerView.backgroundColor = .white
        //in this code [weak self] is not needed because I don't use self inside the closure
        pickerView.onPickItem = {( sender : AZAPicker<PickerItem>,item:PickerItem) in
            print("didPickItem: \(item)")
        }

        pickerView.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(pickerView)

        NSLayoutConstraint(item: pickerView, attribute: .top, relatedBy: .equal, toItem: topLayoutGuide, attribute: .top, multiplier: 1, constant: 20).isActive = true

        NSLayoutConstraint(item: pickerView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0).isActive = true

        NSLayoutConstraint(item: pickerView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0).isActive = true

        NSLayoutConstraint(item: pickerView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 80).isActive = true
    }

}

【讨论】:

  • 我需要在哪里写这个?在 viewdidload 中?
  • 你有pickerView.onPickItem = self.picker@EmreÖnder你也可以删除函数声明
  • 我把它放在 viewdidload 里面并删除旧的声明和函数。完成工作但仍未解除分配。
  • 我添加了我如何声明 PickerView
  • 工作就像一个魅力!谢谢! @ReinierMelian 如果您对问题给予加号投票,我会很高兴:)
猜你喜欢
  • 2018-12-09
  • 2017-02-01
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 2019-12-19
  • 2018-01-31
相关资源
最近更新 更多