2012-12-27 32 views
0

嗨,並提前致謝。我有一個問題,當我在一個視圖中啓動NSTimer,然後切換到UIPickerView的另一個視圖時,UIPickerView的行爲會受到影響。我在任何視圖和包含NSTimer的視圖之間來回切換的次數越多,UIPickerView的行爲就會受到越深刻的影響 - 它們會滯後並緩慢移動 - 最終會導致UIPickerView不會調用DidSelectRow方法。這不僅僅是一個UIPickerView受到影響,而是我的應用中的所有UIPickerView影響NIPimer行爲的UIPickerView

如果我決定首先不激活NSTimer,我的UIPickerViews工作沒有問題。但是,當我撥打NSTimer方法時,在包含NSTimer的視圖和其他任何視圖的視圖之間切換回來和第四次之後,我的應用程序UIPickerView全部停止工作。爲了恢復他們的正確行爲,我需要關閉應用程序並重新啓動它。

我使用的是ARC所以我沒有手動發佈NSTimer - 但我認爲這與我的問題有關。我猜想NSTimer或其方法每次切換回包含NSTimer的視圖時都會重複(沒有發佈或解除分配)。無論如何,這是我第二次編碼任何東西,所以我不知道如何解決這個問題,雖然我讀過NSTimerUIPickerView可以通過相同的NSRunLoop或線程分配,但我不確定那是什麼手段。

無論如何,這裏是我的代碼 - 它非常通用的樣板代碼。

-(void)showActivity:(NSTimer *)tim { 

    NSDate *currentDate = [NSDate date]; 
    NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate]; 
    NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval]; 

    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; 
    [dateFormatter setDateFormat:@"HH:mm:ss.S"]; 
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]]; 
    NSString* timeString = [dateFormatter stringFromDate:timerDate]; 
    stopWatchLabel.text = timeString; 

} 


- (IBAction)onStartPressed:(UIButton *)sender; { 

    stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1/10 
                target:self 
               selector:@selector(showActivity:) 
               userInfo:nil 
               repeats:YES]; 
    // Save the new start date every time 
    startDate = [[NSDate alloc] init]; // equivalent to [[NSDate date] retain]; 
    NSDate *savedMentionDate = [[NSUserDefaults standardUserDefaults] objectForKey:@"mostRecentMentionDate"]; 

    if (savedMentionDate == nil) { 
     //There is no existing mention, so save the most recent one 
     [[NSUserDefaults standardUserDefaults]setObject:startDate forKey:@"mostRecentMentionDate"]; 
     [[NSUserDefaults standardUserDefaults] synchronize]; 
    } else { 
     startDate = savedMentionDate; 
    } 

    [stopWatchTimer fire]; 

    timerSetting = 0; 

    NSNumber* timerSettingNS = [[NSNumber alloc] initWithInt:timerSetting]; 
    [[NSUserDefaults standardUserDefaults] setObject:timerSettingNS forKey:@"timerSetting"]; 
    [[NSUserDefaults standardUserDefaults] synchronize]; 

} 


- (IBAction)onStopPressed:(UIButton *)sender { 

    [stopWatchTimer invalidate]; 

} 


- (IBAction)resetTimer:(UIButton *)sender; { 

    stopWatchLabel.text = @"00:00:00.0"; 

    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; 
    [defaults removeObjectForKey:@"mostRecentMentionDate"]; 

    timerSetting = 1; 

    NSNumber* timerSettingNS = [[NSNumber alloc] initWithInt:timerSetting]; 
    [[NSUserDefaults standardUserDefaults] setObject:timerSettingNS forKey:@"timerSetting"]; 
    [[NSUserDefaults standardUserDefaults] synchronize]; 

} 

-(void)ViewDidLoad { 
    ... 
    ... 
    NSNumber* timerSettings = [defaults objectForKey:@"timerSetting"]; 

    if (timerSettings == nil || timerSettings.intValue == 1) { 

     [self resetTimer:resetTime]; 

    } else if (timerSettings.intValue == 0) { 

     [self onStartPressed:start]; 

    } 

} 
+0

請不要濫用'xcode'標籤,它不是適用於一般的iOS編程相關問題。 – 2012-12-27 07:21:09

+0

好的我一定不要在將來... –

回答

0

我想出了一個解決方案。我已經在允許應用切換視圖的所有方法中插入了代碼[stopWatchTimer invalidate]。

這或多或少是什麼人會告訴你,因爲:

我很驚訝這個工作,因爲當我在viewDidLoad中和viewDidUnload方法包括[stopWatchTimer無效]它沒有任何影響......

這些方法只要求非常特殊的場合:

viewDidLoad時調用視圖控制器的觀點已被加載。 (應該不是太大的驚喜...)

的重要組成部分,是瞭解什麼load意味着:

當一個視圖控制器被實例化 - 從NIB吧,或者在代碼 - 它不有一個觀點。相反,它所具有的信息是如何在被要求時提供服務的信息。

所以當你發送view消息到一個UIViewController時,它會判斷它是否已經有了它的_view實例變量。如果沒有,它會調用它自己的loadView方法,它將做任何必要的事情來填充該實例變量的一些有意義的東西。然後它會發送消息viewDidLoad,以完成它所管理的視圖層次結構的設置,然後纔會返回_view的值。

這意味着viewDidLoad在視圖控制器視圖的整個生命週期中只調用一次。但是,這是什麼意思?

在iOS 5及更早版本中,視圖的生命週期與它作爲可見視圖層次結構的一部分相關聯:當它不包含在其中並且其擁有的視圖控制器收到內存警告時,基本實現基本上查看視圖是否有超級視圖,並且(如果不是)它將調用viewWillUnload,釋放並且零出_view,並最終調用viewDidUnload來完成此過程。 (這就是爲什麼在一些糟糕的遺留代碼庫中,您可能會發現覆蓋didReceiveMemoryWarning,不會調用到super ...)

從iOS 6開始,UIViewController不再執行此操作!

這就是爲什麼viewWillUnload和viewDidUnload已被棄用的原因:視圖一直存在,直到它擁有的視圖控制器被丟棄,因此這些方法不再被調用。

因爲這樣,有什麼相關的情況來清除你的計時器? 1. viewWillDisappear:你的觀點即將「離開舞臺」,所以拆掉任何只有在前方和中心時纔有意義的東西。 2.每當你要模糊受定時器影響的部分時。這可能是因爲您正在呈現另一個視圖控制器,或者顯示其他事物(如UIPickerView),以隱藏屏幕下方的大部分內容。 3.每當需要重新配置/重置定時器時。 (如果不這樣做,這就是爲什麼你的應用程序來擺在首位戛然而止的原因。)

有可從右在Xcode一噸在這些問題上出色的文檔,以及在線:

  • View Contoller Programming Guide是絕對必讀的iOS版本。
  • NSTimer Class Reference和鏈接的伴隨指南非常好。請務必閱讀概念部分 - 在「任務」部分之前。在NSTimer標籤下(並且實際上與NSTimer相關)詢問的任何問題的90%以上都不會被詢問是否人們實際閱讀這個...
0

我想出了一個解決方案。我已經在允許應用切換視圖的所有方法中插入了代碼[stopWatchTimer invalidate]。我很驚訝這個作品,因爲當我在viewDidLoad和viewDidUnload方法中包含[stopWatchTimer invalidate]時,它沒有任何效果...