2016-01-29 47 views
2

在我的一個應用程序中,我提供了一個登錄視圖控制器,如代碼所示。這很好,除了當我註銷應用程序並重新登錄時,同樣的方法被調用,並且它最終創建了一個新的MyLandingController,以保持舊的仍在附近。因爲,我將它分配給一個屬性,不應該讓汽車解除舊的分配?我檢查並確保沒有其他對象保留對MyLandingController的強烈參考;儘管如此,還是有一些弱點。重新登錄iOS應用程序時發生內存泄漏

- (void)presentMyLandingView { 
    self.navigationController = nil; 
    [[self.window viewWithTag:100] removeFromSuperview]; 
    self.window.backgroundColor = [UIColor whiteColor]; 
    self.primaryViewController = [[MyLandingController alloc] init]; 
    self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.primaryViewController]; 
    [self.navigationController.navigationBar setBarStyle:UIBarStyleBlack]; 
    [self.window insertSubview:[self.navigationController view] atIndex:1]; 
    self.window.rootViewController = self.navigationController; 
    [NSTimer scheduledTimerWithTimeInterval:.50 target:self selector:@selector(clearSubviews) userInfo:nil repeats:NO]; 
} 

作爲一個臨時的解決辦法,我認爲把一個條件,如果我的大MyLandingController存在,那麼使用而不是創建一個新的。這修復了泄漏,但整個視圖向上移動(看起來像通過導航欄大小向上移動)。

所以,我要尋找答案,在這裏2個問題 -

Q1)爲什麼重新初始化一個新的視圖控制器對象不解除分配舊的對象的屬性。 Q2)爲什麼重新使用現有對象(從弱引用拉出)不能很好地呈現UI - 屏幕向上移動?

+0

爲什麼你還沒有對導航控制器&self.primaryViewController進行修改。導航控制器正在這裏發生。 –

+0

已經嘗試過 - 沒有運氣! – Abhinav

回答

1

由於着陸控制器仍在演示文稿堆棧中,所以它不會泄露 - 導航控制器仍然保存引用。

這 - 巧合 - 回答你的問題,因爲視圖控制器不應該在演示文稿堆棧中兩次。

,你可以檢查它是否存在,在短短

[self.navigationController popToRootViewControllerAnimated:NO]; 

,而不是創建另一個實例的這種情況。

+0

謝謝Jan!正如我所提到的,我試過了,它修復了泄漏,但是我的着陸視圖加載不好。整個視圖向上移動約64點。 – Abhinav

+0

你可以顯示你正在使用的代碼嗎?好像你在濫用一種或另一種技術,很難猜測。你是否有機會操縱控制器的'viewDidLoad'中的任何幀,該幀應該在'viewDidAppear'中? – SmokeDispenser

+0

我有一個弱引用MyLandingController到一個單例會話類,然後使用它而不是創建一個新的設置爲rootViewController窗口對象。 – Abhinav

0

存在內存泄漏,因爲最後一行:

[NSTimer scheduledTimerWithTimeInterval:.50 target:self selector:@selector(clearSubviews) userInfo:nil repeats:NO];

NSTimer保持強引用其目標是無效之前。從Apple's documentation

定時器觸發時發送由aSelector指定的消息的對象。定時器保持對該對象的強引用,直到它(定時器)失效。

爲了擺脫內存泄漏,您必須在創建新計時器之前使您的舊計時器無效。

- (void)presentMyLandingView { 
     [self.timer invalidate]; //invalidates the old timer 
     //rest of your code goes here 
     self.timer = [NSTimer scheduledTimerWithTimeInterval:.50 target:self selector:@selector(clearSubviews) userInfo:nil repeats:NO]; //keeps reference to the new timer so that it is possible to invalidate that timer later . Note that this should be a `weak` reference as the timer is retained by the run loop anyway. 
} 
+0

這不是事實。這裏有兩件事 - 第一,這個定時器是非重複定時器,所以它一旦完成就消失,所以強引用,第二個定時器在AppDelegate上,這不會導致泄漏。 MyLandingController在這裏泄漏。而且,正如我所提到的,如果我重新使用早先創建的對象,但是在重新登錄之後,泄漏得到修復,那麼UI並沒有完全顯示;事實上,視圖從狀態欄開始的地方開始。 – Abhinav