ios - 修复 Swift 中的内存问题
问题描述
我在推送/搜索到某些UIViewControllers [ChallengePrivacySettingViewC]
.
的所有组件ChallengePrivacySettingViewC
都是以编程方式创建的。我已经广泛检查了所有工具,但似乎无法弄清楚发生了什么。它似乎不是任何类型的非循环引用或奇怪的指针。
这是ViewController
已实例化的,并在通过Allocations
工具检查时分配了大约 2 X 60+ MB。
class ChallengePrivacySettingViewC:UIViewController{
deinit {
print("Got deinit") // this is called
}
typealias ChangeHandler = (([Bool]) -> Void)
var changeHandler: ChangeHandler?
let menuView = UIView()
private var tableView:UITableView = {
let tb = UITableView()
tb.translatesAutoresizingMaskIntoConstraints = false
return tb
}()
lazy var backdropView: UIView = {
let bdView = UIView(frame: self.view.bounds)
bdView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
return bdView
}()
var privacyGroup:[Bool] = [true,false] //get dependency injection
let menuHeight = UIScreen.main.bounds.height / 3
var isPresenting = false
var dataSource:[ChallengePrivacyModel] = [ChallengePrivacyModel]()
init() {
super.init(nibName: nil, bundle: nil)
modalPresentationStyle = .custom
transitioningDelegate = self
}
fileprivate func setupConstraints() {
view.backgroundColor = .clear
view.addSubview(backdropView)
view.addSubview(menuView)
menuView.addSubview(tableView)
menuView.layer.cornerRadius = 20
tableView.layer.cornerRadius = 20
menuView.backgroundColor = .white
menuView.translatesAutoresizingMaskIntoConstraints = false
menuView.heightAnchor.constraint(equalToConstant: menuHeight).isActive = true
menuView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
menuView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
menuView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: menuView.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: menuView.trailingAnchor),
tableView.topAnchor.constraint(equalTo: menuView.topAnchor),
tableView.bottomAnchor.constraint(equalTo: menuView.bottomAnchor),
])
}
fileprivate func setup() {
setupConstraints()
tableView.delegate = self
tableView.dataSource = self
tableView.register(ChallengePrivacyCell.self, forCellReuseIdentifier: "cellId")
tableView.isScrollEnabled = false
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ChallengePrivacySettingViewC.handleTap(_:)))
backdropView.addGestureRecognizer(tapGesture)
}
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
dataSource = ChallengePrivacyModel.loadData()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
}
@objc func handleTap(_ sender: UITapGestureRecognizer) {
changeHandler?(privacyGroup)
dismiss(animated: true, completion: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我显示viewController的方式:
@objc func tapOnPrivacyBtn(_ sender: UIButton) {
let vc = ChallengePrivacySettingViewC()
vc.privacyGroup = self.privacyGroup
vc.changeHandler = { [weak self] privacyGroup in
self?.privacyGroup = privacyGroup
}
present(vc, animated: true, completion: nil)
}
deinit()
每次弹出时都会调用ChallengePrivacySettingViewC
. 没有悬空参考。
分配工具上的内存增长:
VM: CoreUI image data 122.05 MiB 3
0x14a75b000 00:51.346.892 60.06 MiB
0x13c3ed000 00:51.314.556 60.06 MiB
0x138ca5000 00:51.378.480 1.94 MiB
我在 [0x14a75b000 和 0x13c3ed000] 的堆栈跟踪中看到了这个:
0 libsystem_kernel.dylib mmap
1 CoreUI -[_CSIRenditionBlockData _allocateImageBytes]
2 CoreUI -[_CSIRenditionBlockData initWithPixelWidth:pixelHeight:sourceRowbytes:pixelFormat:]
3 CoreUI __csiCompressImageProviderCopyImageBlockSetWithOptions
4 CoreGraphics CGImageProviderCopyImageBlockSetWithOptions
5 QuartzCore CA::Render::(anonymous namespace)::create_image_from_image_provider(CGImage*, CGImageProvider*, CGColorSpace*, unsigned int)
6 QuartzCore CA::Render::create_image(CGImage*, CGColorSpace*, unsigned int, double)
7 QuartzCore CA::Render::copy_image(CGImage*, CGColorSpace*, unsigned int, double, double)
8 QuartzCore CA::Render::prepare_image(CGImage*, CGColorSpace*, unsigned int, double)
9 QuartzCore CA::Layer::prepare_commit(CA::Transaction*)
10 QuartzCore CA::Context::commit_transaction(CA::Transaction*)
11 QuartzCore CA::Transaction::commit()
12 UIKitCore _afterCACommitHandler
13 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
14 CoreFoundation __CFRunLoopDoObservers
15 CoreFoundation __CFRunLoopRun
16 CoreFoundation CFRunLoopRunSpecific
17 GraphicsServices GSEventRunModal
18 UIKitCore UIApplicationMain
19 Company main /Users/Company/Desktop/Original/frontend-current/company/Module/LoginSignup/SignupVC/BankingSetupC.swift:26
20 libdyld.dylib start
奇怪的是。除非我退出应用程序,否则我会将这 2 块 60MB 的内存浮动。按下主页按钮会将内存重置为正常内存使用。应用程序从未在任何时候被杀死。
知道这里发生了什么吗?非常感激
解决方案
推荐阅读
- uart - MSP430FR5994 Launchpad UART 参考设计不工作
- visual-studio-2019 - 使用 Visual Studio 2019 构建的 EXE 出现“DLL 入口点”错误,但将 EXE 列为 DLL?
- spring-boot - Spring Boot 在应用程序启动时抛出空指针异常
- node.js - Node.js:使用 YouTube 数据 API 设置视频标题和描述
- javascript - 为什么浏览器会自动更改日期格式?
- c++ - 多维向量的意外重新分配
- c++ - 从模板类导出友元运算符
- laravel - 当后端和前端分为两个 git repos 和域时如何在 laravel 中处理用户身份验证
- javascript - Chrome 扩展静音背景页面
- docker - 手动遵循 Dockerfile 说明