我正在使用的新应用程序遇到内存泄漏。 启动应用程序后不久便开始发生内存泄漏,并且Xcode泄漏指向viewDidLoad内部的UIPageviewController中的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的故事板中的viewControllers仅包含一个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])
}
}