2011-11-17 54 views
2

我正在研究一個應用程序,我想每隔幾秒鐘調用一個方法,同時用戶將他們的手指放在按鈕上,並在發佈時停止。在iOS中的Touch Down上觸發重複事件

目前,我正在觸發事件中啓動一個NSOperation,然後應該調用NSTimer在2秒後觸發另一個NSOperation。

但是隻有第一個「runOperation」正在發生;來自計時器的人不是。

- (IBAction)buttonPressed:(id)sender 
{ 
    [self doStuff]; 
} 

- (void)runOperation { 
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self 
                      selector:@selector(doStuff) 
                      object:nil]; 

    [queue addOperation:operation]; 
    [operation release]; 
} 

- (void)doStuff { 
    /* stuff goes here */ 

    [self performSelectorOnMainThread:@selector(setTimer) withObject:nil waitUntilDone:YES]; 
} 

- (void)setTimer 
{ 
    timer = [[NSTimer timerWithTimeInterval:2.f target:self selector:@selector(runOperation) userInfo:nil repeats:NO] retain]; 
} 

- (IBAction)finishTakingPictures:(id)sender { 
    [timer invalidate]; 
    timer = nil; 
} 

回答

1

人,希望這有助於你出去,不知道爲什麼我花了這這麼多時間... :)

如果使用NSTimer:timerWithTimeInterval:...你需要計時器添加到運行循環使用NSRunLoop:addTimer:forMode。這就是爲什麼你的計時器沒有開火。如果您使用NSTimer:scheduledTimerWithTimeInerval:...它將被添加到當前運行循環中。

關於您的實施的一些想法。

  1. 你有很多間接性。您可以直接在doStuff中設置它並刪除setTimer方法。

  2. 沒有理由在主線程上設置計時器,您可以在任何線程上設置計時器。

  3. 你根本不需要計時器,我會在下面建議一個替代實現。

替代實現:

  1. 添加BOOL屬性例如@property (nonatomic) BOOL isFinished;

  2. 當用戶按下按鈕時,設置isFinished = NO;並開始您的第一個操作。

  3. 當操作完成時,如果isFinished == NO開始另一個操作。您可以通過使用performSelector:afterDelay:或當用戶停止按壓按鈕使用dispatch_after()

  4. 增加延時,設置isFinished = YES

此備用實現假定您希望第一個完成後,開始下一步操作。如果您希望操作在固定的時間間隔後發生,而不管操作是否已經處理,請更改您的計時器重複執行,並在計時器啓動時檢查isFinished == YES以使計時器無效。

+0

doh doh and doh again;我怎麼錯過了將定時器添加到runloop的問題!是的,很多不必要的間接方法(導致大量關於未能看到真正問題的麻煩,並且在主線程上設置計時器正在抓着吸管)。 – akbsteam

+0

感謝您的詳細回覆,如果可以的話我會接受這兩個答覆,但是NJones可能更接近我將使用的實現。這就是說,總是很高興看到另一種方法。 – akbsteam

+0

很高興你在學習。 WRT SO,一些想法。一般來說,你應該接受第一個正確的答案,除非後面的答案要優越得多。我不在乎幾點,原則上這樣說。我的回答是正確的,我告訴過你如何解決這個問題。所有額外的東西都是肉汁。 @NJones的回答很好,這只是我的一個小小的調整。在這種情況下,沒關係,但有時候你不想使用視圖屬性來跟蹤狀態(例如,當視圖可能會在操作仍在進行時消失)。最後,你可以儘可能多的答覆,只要你喜歡。快樂的編碼。 – XJones

2

XJones(無關係)對於計劃的計時器是正確的,並且關於可笑的間接量。但我個人非常喜歡這個用戶交互模型的NSTimer。以下是我將如何實施它。

_buttonTimer is an instance variable, 
button is an IBOutlet to the button in question, 
touchDown: is connected to the button's TouchDown event. 

將該按鈕添加爲插座,因爲按鈕知道它是狀態,所以不需要讓BOOL跟蹤按鈕狀態。

然後將這些方法添加到您的UIViewController子類。

-(void)helloMe{ 
    if (self.button.state == UIControlStateNormal){ 
     [_buttonTimer invalidate]; 
     _buttonTimer = nil 
    } 
    else { 
     NSLog(@"Hello me"); 
     // Do stuff here 
    } 
} 

- (IBAction)touchDown:(id)sender { 
    _buttonTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(helloMe) userInfo:nil repeats:YES]; 
    [_buttonTimer fire]; // If desired 
} 

現在運行,您將按下按鈕並每隔兩秒鐘在控制檯中看到「Hello me」,直到您鬆開按鈕。

+0

偉大的東西,歡呼聲 – akbsteam