2009-10-17 21 views
7

Tôi có một số NSTimer kích hoạt với khoảng thời gian 3 giây để giảm giá trị. Khi tôi thực hiện một hành động làm tăng giá trị đó, tôi muốn khởi động lại bộ hẹn giờ để đếm 3 giây từ thời điểm đó.Đặt lại thời gian kích hoạt của NSTIMER từ bây giờ thay vì ngọn lửa cuối cùng

Ví dụ: nếu tôi tăng giá trị và hẹn giờ sẽ kích hoạt sau 1 giây, tôi muốn thay đổi điều đó và làm cho hẹn giờ kích hoạt trong 3 giây thay thế. Tôi có thể vô hiệu hóa bộ hẹn giờ và tạo lại không? Hoặc tôi có thể làm điều đó với setFireDate:, sử dụng ngày hiện tại và thêm khoảng thời gian 3 giây?

+0

Cuối cùng tôi sử dụng setFireWithDate, khi tôi tăng giá trị, tôi cũng gửi tin nhắn đến bộ hẹn giờ với ngày hiện tại cộng thêm ba giây. Nó hoạt động ^^ Cảm ơn bạn rất nhiều. – emenegro

Trả lời

7

Có, bạn có thể vô hiệu hóa nó. Và tạo lại nó.

Bạn cũng có thể sử dụng:

- (void) myTimedTask { 
    // other stuff this task needs to do 

    // change the variable varyingDelay to be 1s or 3s or... This can be an instance variable or global that is changed by other parts of your app 
    // weStillWantTimer is also a similar variable that your app uses to stop this recurring task 

if (weStillWantTimer) 
     [self performSelector:@selector(myTimedTask:) withObject:gameColor afterDelay:varyingDelay]; 

} 

Bạn gọi myTimedTask để bắt đầu nhiệm vụ lặp đi lặp lại. Khi nó được bắt đầu, bạn có thể thay đổi độ trễ bằng cách thay đổiThay đổi hoặc dừng nó bằng weStillWantTimer.

+0

+1, nhưng chắc chắn không phải là * toàn cầu *, phải không? :) – zoul

+0

@zoul, tùy thuộc vào mức độ lộn xộn của bạn :-) – mahboudz

1

Vô hiệu hóa bộ hẹn giờ và tạo lại. Tuy nhiên, hãy đảm bảo bạn không làm mất hiệu lực giải phóng bộ hẹn giờ trừ khi bạn chắc chắn rằng mình cần kể từ khi vòng lặp chạy giữ lại bộ hẹn giờ cho đến khi chúng không hợp lệ và sau đó tự giải phóng chúng.

Theo ý kiến ​​của tôi, trộn -performMã mã với mã bộ đếm thời gian dẫn đến nhiều lần thực hiện các phương pháp đích, vì vậy tôi sẽ tránh xa điều đó.

1

Có, làm mất hiệu lực và tạo lại bộ hẹn giờ sẽ hoạt động. Đó là cơ bản những gì bạn đang muốn làm gì nếu bạn không tăng giá trị của bạn: đặt lại và bắt đầu lại.

1

Tài liệu setFireDate: đề cập đến việc thay đổi ngày cháy tương đối đắt, cho thấy tốt hơn là bạn nên hủy và tạo lại bộ hẹn giờ trừ khi bạn đang thực hiện nhiều. Vì lợi ích của lập luận, tuy nhiên, tôi đã đánh lừa loại này một chút trước đây. Tôi thích điều này vì nó gói gọn hành vi điều chỉnh ngày; bộ đếm thời gian tự xử lý nó, chứ không phải chủ sở hữu/bộ điều khiển của nó. Tuy nhiên, tôi không có bất kỳ dữ liệu hiệu suất nào về điều này.

@implementation NSTimer (WSSAdjustingFireDate) 

- (void)WSSFireAdjustingFireDate 
{ 
    [self fire]; 

    [self WSSSkipNextFireAdjustingFireDate]; 
} 

- (void)WSSSkipNextFireAdjustingFireDate 
{ 
    CFRunLoopTimerRef cfSelf = (__bridge CFRunLoopTimerRef)self; 
    CFTimeInterval delay = CFRunLoopTimerGetInterval(cfSelf); 
    CFRunLoopTimerSetNextFireDate(cfSelf, CFAbsoluteTimeGetCurrent() + delay); 
} 

@end 

Tôi đã sử dụng chức năng Nền tảng chính chỉ để tránh tạo một NSDate. Tối ưu hóa sớm? Xin vui lòng vượt qua muối.

3

Tôi đã thực hiện một thử nghiệm nhỏ và hóa ra việc đặt lại fireDate nhanh gấp bốn lần so với việc vô hiệu hóa và tạo lại bộ hẹn giờ. Trước tiên, tôi tạo ra một bộ đếm thời gian mà gọi phương thức DoNothing:

if (!testTimer) { 
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0 
                 target:self 
                selector:@selector(doNothing:) 
                userInfo:nil 
                repeats:NO]; 
    testTimer = timer; 
} 

Đây là mã kiểm tra:

- (void) testInvalidatingTimer { 
    for (int n = 0; n < 10000; n++) { 
     [testTimer invalidate]; 
     testTimer = nil; 

     NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0 
                  target:self 
                 selector:@selector(doNothing:) 
                 userInfo:nil 
                 repeats:NO]; 
     testTimer = timer; 
    } 
} 

- (void) testResettingTimer { 
    for (int n = 0; n < 10000; n++) { 
     if ([testTimer isValid]) { 
      testTimer.fireDate = [NSDate dateWithTimeIntervalSinceNow:3.0]; 
     } 
    } 
} 

Chạy rằng trên một iPad Air mang lại 0,198173 s cho invalidatingTimer và 0,044207 s cho resettingTimer. Nếu hiệu suất là mục tiêu của bạn, tôi khuyên bạn nên đặt lại fireDate. Nó cũng là một nỗ lực mã hóa khá ít.

Các vấn đề liên quan