2013-06-30 33 views
0

DemoViewController負責向用戶顯示教程。包含動畫和計時器以重複手勢演示,同時被用戶忽略。從DataViewController實例化。未被編輯,但後來重新啓動其內部計時器。我需要它完全消失,所以當用戶返回第一頁時不會再次創建它。IOS設置其ID爲零後定時重啓iOS對象

dataViewController.h

#import "DemoViewController.h" 
@property (strong,nonatomic) DemoViewController *demoController; 

dataViewController.h

-(void) viewWillAppear:(BOOL)animated { 
    // demoPageNumber is 0 
    if ((self.demoController== nil) && ([_pageNumber isEqualToNumber:demoPageNumber])){ 
     self.demoController = [[DemoViewController alloc] initWithView:self.view]; 
    } 
} 

-(void) viewWillDisappear:(BOOL)animated{ 
    [self.demoController free]; // invalidate timer, nil all internal objects 
    self.demoController=nil; // should free object 
} 

DemoViewController.m

-(void) free{ 
    [animationRespawnTimer invalidate]; 
    animationRespawnTimer=nil; 
} 

-(void) respawnDemoWithSelector:(SEL)selector{ 
    NSLog(@"Timer fired %@", self); 
    [self resetTimer]; 
    animationRespawnTimer = [NSTimer scheduledTimerWithTimeInterval:10 
                 target:self 
                 selector:selector 
                 userInfo:nil 
                 repeats:NO]; 
} 

-(void) showScrollDemo{ 


    NSLog(@"showScrollDemo fired"); 
    [self stopPreviousAnimations]; 
    scrollHandView.frame = CGRectMake(315.0, 700.0, 100, 100); 
    scrollHandView.hidden=NO; 
    scrollHandView.alpha=1; 

    [UIView animateWithDuration:3.0 
          delay: 0.0 
         options: (UIViewAnimationOptionCurveEaseOut | 
            UIViewAnimationOptionRepeat) 
        animations:^{ 

         [UIView setAnimationRepeatCount:3]; 
         scrollHandView.frame = CGRectMake(315.0, 300.0, 100, 100); 

        } 
        completion:^(BOOL finished){ 

         [UIView animateWithDuration:1.0 delay:0 
         options:UIViewAnimationOptionCurveEaseOut 
             animations:^{ 
              scrollHandView.alpha=0; 

          } 
          completion:^(BOOL finished){ 
          scrollHandView.hidden=YES; 

        [self respawnDemoWithSelector: @selector(showScrollDemo)]; 

          } 
         ]; 

       } 
]; 

}

當加載頁面時,如果是這樣的第一頁,demoController被實例化,並在清理完成後自定義免費方法,從頁面退出。根據我的理解,這應該刪除demoController對象及其所有內容,包括定時器。和調試區域恰恰相同!直到在新頁面上時,demoController計時器神祕地從以前的對象ID重新生成。

17:59:14.041 viewWillAppear begin (self.demoController null) 
18:00:05.346 viewWillAppear, <DemoViewController: 0x7580310> //demoController created 
18:00:15.786 in the demoController method the "showScrollDemo" is fired 
18:00:19.834 viewWillAppear end <DemoViewController: 0x7580310> 

頁面被加載,演示執行正常。現在我正在翻頁。 viewWillDisappear事件被觸發。

18:01:17.966 viewWillDisappear begin, send "free" message to demoController 
18:01:17.966 "free" was performed from <DemoViewController: 0x7580310> 
18:01:34.059 viewWillDisappear end (self.demoController null) 

因此,「self.demoController」爲空。然後demoController重新生成自己以前的ID

18:02:36.514 Timer fired <DemoViewController: 0x7580310> 

爲什麼?定時器不能重生,它被設置爲重複:NO。

回答

1

我假設它是動畫的完成塊,它調用respawnDemoWithSelector並創建一個新的計時器。

根據這樣的回答:https://stackoverflow.com/a/9676508/1187415,你可以停止所有正在運行的 動畫與

[self.view.layer removeAllAnimations]; 

或者,你可以在布爾屬性done添加到這是在free方法設置 到YES的DemoViewController,和檢查動畫的完成塊:

if (!self.done) 
    [self respawnDemoWithSelector: @selector(showScrollDemo)]; 

UPDATE:動畫塊捕獲對self的強烈參考,從而防止 對象被解除分配。 「保留 - 循環」問題的標準解決方案 (假設您使用ARC)是對自我使用弱引用。這將是這樣的:

__weak typeof(self) weakSelf = self; 
[UIView animateWithDuration:3.0 
         delay: 0.0 
        options: (UIViewAnimationOptionCurveEaseOut | 
           UIViewAnimationOptionRepeat) 
       animations:^{ 

        [UIView setAnimationRepeatCount:3]; 
        weakSelf.scrollHandView.frame = CGRectMake(315.0, 300.0, 100, 100); 

       } 
       completion:^(BOOL finished){ 

        [UIView animateWithDuration:1.0 delay:0 
             options:UIViewAnimationOptionCurveEaseOut 
             animations:^{ 
              weakSelf.scrollHandView.alpha=0; 

             } 
             completion:^(BOOL finished){ 
              weakSelf.scrollHandView.hidden=YES; 
              [weakSelf respawnDemoWithSelector: @selector(showScrollDemo)]; 

             } 
         ]; 

       } 
]; 

weakSelf抱持着強烈的參考DemoViewController並設置爲nil 自動,如果它指向的對象,以被釋放。在這種情況下,塊內部發送到weakSelf的所有消息都不做任何事情。

+0

是的,動畫是在被調用的方法中,但是如果對象是空的,我該如何訪問它的方法呢?我實例化DemoViewController,調用它的方法「showScrollDemo」。然後我刪除這個對象,然後調用這個方法。它應該返回零,什麼都不做,對吧? –

+1

@JanisJakaitis:但是動畫塊會捕獲對'self'的引用,因此即使調用self.demoController = nil,它也不會被釋放。至少這就是我所假設的。你有沒有嘗試我的建議? –

+0

[self.view.layer removeAllAnimations];沒有改變任何東西。 「完成」是一種解決方法,我想找到一種方法來殺死「免費」方法中的動畫和計時器。當demoController尚未實例化時,將系統恢復到之前的狀態。 –

相關問題