ios - 是什么导致 UIPageViewController 中的内存泄漏?
问题描述
我正在开发的新应用程序中遇到一些内存泄漏。内存泄漏在启动应用程序后不久就开始了,Xcode 泄漏指向 UIPageviewController 中 viewDidLoad 中的 SetViewControllers 方法。我一直无法弄清楚确切的原因是什么。
这是 UIPageViewController 的代码:
import UIKit
class OnboardingPageViewController: UIPageViewController, UIPageViewControllerDataSource {
// Create viewcontroller array for pageview
lazy var availableViewControllers: [UIViewController] = [vcOne, vcTwo, vcThree]
lazy var vcOne: UIViewController = storyboard!.instantiateViewController(withIdentifier: "onboardingOne")
lazy var vcTwo: UIViewController = storyboard!.instantiateViewController(withIdentifier: "onboardingTwo")
lazy var vcThree: UIViewController = storyboard!.instantiateViewController(withIdentifier: "onboardingThree")
deinit{
print("ONBOARDING PAGEVIEW DEALLOCATED")
}
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
unowned let firstVc = availableViewControllers[0]
setViewControllers([firstVc], direction: .forward, animated: true, completion: nil)
}
// Func to create new viewController
func newVc(_ viewControllerId: String) -> UIViewController{
unowned let vc = storyboard!.instantiateViewController(withIdentifier: viewControllerId)
return vc
}
// UIPageviewControllerDataSource protocol funcs
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let vcIndex = availableViewControllers.firstIndex(of: viewController) else {return nil}
let previousVc = vcIndex - 1
guard previousVc >= 0 else {return nil}
guard availableViewControllers.count > previousVc else {return nil}
return availableViewControllers[previousVc]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let vcIndex = availableViewControllers.firstIndex(of: viewController) else {return nil}
let nextVc = vcIndex + 1
guard nextVc < availableViewControllers.count else {return nil}
guard availableViewControllers.count > nextVc else {return nil}
return availableViewControllers[nextVc]
}
}
viewControllers 被声明为惰性变量,但我最初使用 newVc 函数在 availableViewControllers 数组中创建视图控制器。改后漏水无变化。
滚动页面后,内存泄漏增加了 100 多个新的。
每个 viewController 在情节提要中仅包含一个 ImageView。
我稍后在应用程序中有另一个 UIPageViewController 使用相同的逻辑,并且基于第一个的行为,它很可能也导致一些后来的应用程序泄漏。
编辑:数据源移动到父 vc。Edit2:数据源更改为 [String]
class LoginViewController: UIViewController, FUIAuthDelegate, UIPageViewControllerDataSource {
@IBOutlet weak var loginButton: UIButton!
// lazy var db = Firestore.firestore()
// lazy var uid = Auth.auth().currentUser!.uid
// let notice = Notice()
// unowned let appDelegate = UIApplication.shared.delegate as! AppDelegate
@IBOutlet weak var containerView: UIView!
// lazy var availableViewControllers: [UIViewController] = {[newVc("onboardingOne"), newVc("onboardingTwo"), newVc("onboardingThree")]}()
var availableViewControllers: [String] = ["onboardingOne", "onboardingTwo", "onboardingThree"]
weak var pvc: UIPageViewController!
deinit {
print("LOGINVIEW Deinit RAN")
}
override func viewDidLoad() {
super.viewDidLoad()
let pvc = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
pvc.dataSource = self
self.addChild(pvc)
self.containerView.addSubview(pvc.view)
pvc.view.frame = CGRect(x: 0, y: 0, width: containerView.frame.width, height: containerView.frame.height)
unowned let firstVc = storyboard!.instantiateViewController(withIdentifier: availableViewControllers[0])
pvc.setViewControllers([firstVc], direction: .forward, animated: true, completion: nil)
self.pvc = pvc
// setupLoginButton()
}
// Modify login/register Button
func setupLoginButton() {
loginButton.layer.borderWidth = 0
loginButton.layer.cornerRadius = 25
loginButton.layer.shadowColor = UIColor.lightGray.cgColor
loginButton.layer.shadowOffset = CGSize(width: 0, height: 4)
loginButton.layer.shadowOpacity = 0.9
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor.blue.cgColor, UIColor.init(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)]
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 0)
gradientLayer.frame = loginButton.bounds
gradientLayer.cornerRadius = 25
loginButton.layer.addSublayer(gradientLayer)
}
func newVc(_ viewControllerId: String) -> UIViewController{
unowned let vc = storyboard!.instantiateViewController(withIdentifier: viewControllerId)
return vc
}
// Login/register button pressed
@IBAction func loginButtonTouched(_ sender: Any) {
/* if appDelegate.connected == false {
present(notice.networkAlert, animated: true, completion: nil)
}
else { */
//Setup and get FirebaseUI for login/register (and set delegate)
let authUI = FUIAuth.defaultAuthUI()
let authViewController = authUI?.authViewController()
authUI?.delegate = self
// Present FirebaseUI
present(authViewController!, animated: true, completion: nil)
// }
}
// Handle Firebase Auth result
func authUI(_ authUI: FUIAuth, didSignInWith authDataResult: AuthDataResult?, error: Error?) {
//Show error if one appeared
guard error == nil else {
print(error!.localizedDescription)
return
}
// Make sure Authdataresult exists
guard authDataResult != nil else { return }
// Move to main screen with logged in user
}
// UIPageviewControllerDataSource protocol funcs
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let vcIndex = availableViewControllers.firstIndex(of: viewController.restorationIdentifier!) else {return nil}
let previousVc = vcIndex - 1
guard previousVc >= 0 else {return nil}
guard availableViewControllers.count > previousVc else {return nil}
return storyboard!.instantiateViewController(withIdentifier: availableViewControllers[previousVc])
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let vcIndex = availableViewControllers.firstIndex(of: viewController.restorationIdentifier!) else {return nil}
let nextVc = vcIndex + 1
guard nextVc < availableViewControllers.count else {return nil}
guard availableViewControllers.count > nextVc else {return nil}
return storyboard!.instantiateViewController(withIdentifier: availableViewControllers[nextVc])
}
}
解决方案
推荐阅读
- javascript - 在 Navigation React Native 中传递值
- c++ - Move overload and destructor theory. Can someone please answer if I'm right?
- node.js - 如何从节点访问虚拟文件夹(windows)
- containerd - 如何在没有 K8s 的情况下配置 kata 容器网络?
- django - HTML 更改未反映在使用 Ubuntu 20.0、Nginx 和 Gunicorn 的 Django 应用程序中的网站上
- excel - VBA将工作表保存为特定路径中的工作簿
- python - Selenium Python = 在无限滚动中单击“ShowMore”按钮的问题
- python - Python testfixtures LogCapture 如何在捕获日志时仍然显示日志
- php - RSS 提要模板文件中的 WordPress 特色图片网址
- java - 使用 jpa 将数据插入到 2 个连接表中