Reputation: 2537
I have a FakeSplashController which does;
Something blocks this ViewController to be deallocated and deinit function doesn't get called.
In addition, AppInitService has a static func and It is called inside this SplashController. I also try to add [weak self]
to network request. However, It also doesn't solve the problem.
class SplashViewController: UIViewController {
let logoImage: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "logo")
imageView.contentMode = .scaleAspectFit
return imageView
}()
let textLogo: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "text-logo")
imageView.contentMode = .scaleAspectFit
return imageView
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setupUI()
networkRequests()
}
func networkRequests(){
AppInitService().initAppRequest { [](result) in
switch result{
case .success(_):
self.startAnimation()
return
case .error(let error):
UIControlUtil.showErrorMessage(title: error.title, message: error.message, closeButton: true)
return
}
}
}
func openApp(){
let loginController = WelcomeViewController()
guard let window = UIApplication.shared.keyWindow else {
return
}
window.rootViewController = loginController
}
func startAnimation(){
UIView.animate(withDuration: 0.8, animations: {
self.logoImage.frame.origin.x -= 100
}, completion: nil)
UIView.animate(withDuration: 1,delay: 0.3,animations: {
self.textLogo.alpha = 1
self.textLogo.frame.origin.x += 50
}, completion: { _ in
self.openApp()
})
}
deinit {
print("Splash Deinited")
}
func setupUI(){
self.view.backgroundColor = Color.NavigationBar.tintColor
logoImage.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
logoImage.center = self.view.center
self.view.addSubview(logoImage)
textLogo.frame = CGRect(x: 0,y: 0, width: 195, height: 80)
textLogo.center = self.view.center
textLogo.frame.origin.x -= 20
self.view.addSubview(textLogo)
textLogo.alpha = 0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Upvotes: 0
Views: 269
Reputation: 1562
Without using weak reference function cannot release self object so this function generate retain cycle instants of you can use weak reference.
// You can use weak reference certain to not capture self by updating it to...
func networkRequests(){
AppInitService().initAppRequest { [weak self] result in
guard let strongSelf = self else {
return
}
switch result{
case .success(_):
strongSelf.startAnimation() // HERE BE DRAGONS!
return
case .error(let error):
UIControlUtil.showErrorMessage(title: error.title, message: error.message, closeButton: true)
return
}
}
}
Upvotes: 0
Reputation: 77661
You are capturing self
in this block...
func networkRequests(){
AppInitService().initAppRequest { result in
switch result{
case .success(_):
self.startAnimation() // HERE BE DRAGONS!
return
case .error(let error):
UIControlUtil.showErrorMessage(title: error.title, message: error.message, closeButton: true)
return
}
}
}
This is a potential cause of your memory leak.
You can be certain to not capture self by updating it to...
func networkRequests(){
AppInitService().initAppRequest { [weak self] (result) in
switch result{
case .success(_):
self?.startAnimation()
return
case .error(let error):
UIControlUtil.showErrorMessage(title: error.title, message: error.message, closeButton: true)
return
}
}
}
Upvotes: 1
Reputation: 2537
The problem was I was creating this SplashController as a global and optional variable inside AppDelegate as;
var splashController: SplashController?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
splashController = SplashController()
self.window?.rootViewController = splashController
return true
}
I make it as:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let splashController = SplasController()
self.window?.rootViewController = splashController
return true
}
Upvotes: 0
Reputation: 3152
You can first get all the view controllers in the array and then after checking with the corresponding view controller class, you can delete the one you want.
Here is small piece of code:
var navArray:Array = (self.navigationController?.viewControllers)!
navArray.removeAtIndex(0)
self.navigationController?.viewControllers = navArray
I think this will make your work easier.
Upvotes: 0