Làm cách nào để sử dụng NSTimer?


344

Làm thế nào để tôi sử dụng một NSTimer? Bất cứ ai có thể cho tôi hướng dẫn từng bước?


1
tôi đã nhận được thông tin theo thông số trên Pravinmagdum.wordpress.com/2010/12/30/how-to-use-nstimer hãy xem nó .. có thể hữu ích cho bạn

Câu trả lời:


616

Đầu tiên tôi muốn thu hút sự chú ý của bạn vào tài liệu Cacao / CF (luôn là một cổng gọi đầu tiên tuyệt vời). Các tài liệu của Apple có một phần ở đầu mỗi bài viết tham khảo có tên là "Hướng dẫn đồng hành", trong đó liệt kê các hướng dẫn cho chủ đề đang được ghi lại (nếu có). Ví dụ, với NSTimer, tài liệu liệt kê hai hướng dẫn đồng hành:

Đối với tình huống của bạn, bài viết Chủ đề lập trình hẹn giờ có thể là hữu ích nhất, trong khi các chủ đề luồng có liên quan nhưng không liên quan trực tiếp nhất đến lớp được ghi lại. Nếu bạn xem bài viết Chủ đề lập trình hẹn giờ, nó được chia thành hai phần:

  • Đồng hồ bấm giờ
  • Sử dụng bộ đếm thời gian

Đối với các bài viết có định dạng này, thường có một cái nhìn tổng quan về lớp và nó được sử dụng để làm gì, và sau đó là một số mã mẫu về cách sử dụng nó, trong trường hợp này là trong phần "Sử dụng bộ đếm thời gian". Có các phần về "Tạo và lên lịch cho bộ định thời", "Dừng bộ hẹn giờ" và "Quản lý bộ nhớ". Từ bài viết, việc tạo một bộ đếm thời gian không lặp lại theo lịch trình có thể được thực hiện như sau:

[NSTimer scheduledTimerWithTimeInterval:2.0
    target:self
    selector:@selector(targetMethod:)
    userInfo:nil
    repeats:NO];

Điều này sẽ tạo ra một bộ đếm thời gian đó bị sa thải sau 2,0 giây và gọi targetMethod:về selfvới một đối số, mà là một con trỏ đến các NSTimerví dụ.

Nếu sau đó bạn muốn xem chi tiết hơn về phương pháp, bạn có thể tham khảo lại các tài liệu để biết thêm thông tin, nhưng cũng có giải thích xung quanh mã.

Nếu bạn muốn dừng bộ hẹn giờ lặp lại, (hoặc dừng bộ hẹn giờ không lặp lại trước khi nó kích hoạt) thì bạn cần giữ một con trỏ tới NSTimerthể hiện đã được tạo; thường thì đây sẽ là một biến đối tượng để bạn có thể tham chiếu đến nó trong một phương thức khác. Sau đó bạn có thể gọi invalidatevào NSTimerVí dụ:

[myTimer invalidate];
myTimer = nil;

Đó cũng là một cách thực hành tốt để nilloại bỏ biến đối tượng (ví dụ: nếu phương thức của bạn làm mất hiệu lực bộ định thời gian được gọi nhiều lần và biến đối tượng không được đặt thành nilvà đối tượng NSTimerđã được xử lý, nó sẽ đưa ra một ngoại lệ).

Cũng lưu ý điểm về Quản lý bộ nhớ ở cuối bài viết:

Vì vòng lặp chạy duy trì bộ hẹn giờ, từ góc độ quản lý bộ nhớ , thông thường không cần phải giữ tham chiếu đến bộ hẹn giờ sau khi bạn lên lịch . Vì bộ định thời được truyền dưới dạng đối số khi bạn chỉ định phương thức của nó làm bộ chọn, nên bạn có thể làm mất hiệu lực bộ định thời lặp lại khi thích hợp trong phương thức đó . Tuy nhiên, trong nhiều tình huống, bạn cũng muốn tùy chọn vô hiệu hóa bộ đếm thời gian có lẽ ngay cả trước khi nó bắt đầu. Trong trường hợp này, bạn cần phải giữ một tham chiếu đến bộ đếm thời gian, để bạn có thể gửi cho nó một tin nhắn không hợp lệ bất cứ khi nào thích hợp. Nếu bạn tạo một bộ đếm thời gian không được lên lịch (xem bộ đếm thời gian không theo lịch sử), thì bạn phải duy trì một tham chiếu mạnh đến bộ định thời gian (trong môi trường được tính tham chiếu, bạn giữ lại nó) để nó không bị hủy trước khi sử dụng.


Okk, một câu hỏi, tôi sẽ nhập mã nào để được thực thi cứ sau hai giây?
lab12

Bạn muốn vượt qua YEScho repeats:khi bạn gọi scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:. Nếu bạn làm như vậy thì hãy đảm bảo giữ một tham chiếu đến NSTimerthể hiện (nó được trả về bởi phương thức) và làm theo điểm trên Quản lý bộ nhớ như tôi đã trình bày chi tiết ở trên.
Alex Rozanski

Không, tôi sẽ đặt mã của mình ở đâu sau 2 giây? Ví dụ: giả sử tôi muốn nó phát ra tiếng bíp mỗi 2 giây. Tôi sẽ đặt mã tiếng ồn ở đâu ..?
lab12

Trong phương thức mà bạn chỉ định với targetselector. Ví dụ: nếu mục tiêu của bạn là selfvà bộ chọn là timerMethod:, phương thức được gọi khi bộ định thời kích hoạt được timerMethod:xác định trên self. Sau đó, bạn có thể đặt bất kỳ mã nào bạn muốn trong phương thức đó và phương thức sẽ được gọi bất cứ khi nào bộ định thời kích hoạt. Lưu ý rằng phương thức được gọi khi bộ định thời kích hoạt (mà bạn truyền vào là selector:) chỉ có thể nhận một đối số (mà khi được gọi là một con trỏ tới NSTimerthể hiện).
Alex Rozanski

Xin lỗi, có nghĩa là "được xác định self"
Alex Rozanski

331

có một vài cách sử dụng bộ đếm thời gian:

1) hẹn giờ theo lịch trình & sử dụng bộ chọn

NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
                      target: self
                      selector:@selector(onTick:)
                      userInfo: nil repeats:NO];
  • nếu bạn đặt lặp lại thành NO, bộ hẹn giờ sẽ đợi 2 giây trước khi chạy bộ chọn và sau đó nó sẽ dừng;
  • nếu lặp lại: CÓ, bộ hẹn giờ sẽ bắt đầu ngay lập tức và sẽ lặp lại gọi bộ chọn sau mỗi 2 giây;
  • để dừng bộ hẹn giờ, bạn gọi phương thức -invalidate của bộ đếm thời gian: [t không hợp lệ];

Là một lưu ý phụ, thay vì sử dụng bộ hẹn giờ không lặp lại và gọi bộ chọn sau một khoảng thời gian xác định, bạn có thể sử dụng một câu lệnh đơn giản như sau:

[self performSelector:@selector(onTick:) withObject:nil afterDelay:2.0];

điều này sẽ có tác dụng tương tự như mã mẫu ở trên; nhưng nếu bạn muốn gọi bộ chọn mỗi lần thứ n, bạn sử dụng bộ hẹn giờ với số lần lặp lại: CÓ;

2) hẹn giờ tự lên lịch

NSDate *d = [NSDate dateWithTimeIntervalSinceNow: 60.0];
NSTimer *t = [[NSTimer alloc] initWithFireDate: d
                              interval: 1
                              target: self
                              selector:@selector(onTick:)
                              userInfo:nil repeats:YES];

NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer:t forMode: NSDefaultRunLoopMode];
[t release];
  • việc này sẽ tạo một bộ đếm thời gian sẽ tự khởi động vào một ngày tùy chỉnh do bạn chỉ định (trong trường hợp này, sau một phút) và lặp lại sau mỗi một giây

3) hẹn giờ đột xuất và sử dụng lời mời

NSMethodSignature *sgn = [self methodSignatureForSelector:@selector(onTick:)];
NSInvocation *inv = [NSInvocation invocationWithMethodSignature: sgn];
[inv setTarget: self];
[inv setSelector:@selector(onTick:)];

NSTimer *t = [NSTimer timerWithTimeInterval: 1.0
                      invocation:inv 
                      repeats:YES];

và sau đó, bạn bắt đầu hẹn giờ bằng tay bất cứ khi nào bạn cần như thế này:

NSRunLoop *runner = [NSRunLoop currentRunLoop];
[runner addTimer: t forMode: NSDefaultRunLoopMode];



Và như một lưu ý, phương thức onTick: như thế này:

-(void)onTick:(NSTimer *)timer {
   //do smth
}

Ok, nhưng bạn thấy tôi muốn giảm độ trong suốt của ứng dụng của mình, vì vậy tôi không biết cách áp dụng điều đó với NSTimer
lab12

24
trời ạ, những người này hôm nay .. bỏ phiếu từ tôi vì bạn đã không chỉ định điều đó ngay từ đầu và hãy để chúng tôi viết vô ích!
Waggery

28
Bạn đã không viết vô ích. Đây là thông tin TỐT!
willc2

Trong phương pháp 2, "bộ hẹn giờ tự lên lịch", làm cách nào tôi có thể dừng bộ hẹn giờ khi tôi muốn?
Satyam

1
@Satyamsvv, bạn có thể dừng bộ hẹn giờ bằng cách gọi, giả sử một phương thức khác có: [bộ đếm thời gian không hợp lệ]; hẹn giờ = nil;
Kimpoy

59

Một cái gì đó như thế này:

NSTimer *timer;

    timer = [NSTimer scheduledTimerWithTimeInterval: 0.5
                     target: self
                     selector: @selector(handleTimer:)
                     userInfo: nil
                     repeats: YES];

14
Vẫn còn mạnh ... 2014 nữa!
Muruganandham K

5
#import "MyViewController.h"

@interface MyViewController ()

@property (strong, nonatomic) NSTimer *timer;

@end

@implementation MyViewController

double timerInterval = 1.0f;

- (NSTimer *) timer {
    if (!_timer) {
        _timer = [NSTimer timerWithTimeInterval:timerInterval target:self selector:@selector(onTick:) userInfo:nil repeats:YES];
    }
    return _timer;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

-(void)onTick:(NSTimer*)timer
{
    NSLog(@"Tick...");
}

@end

Bằng cách nào đó, nó tạo ra chu kỳ giữ lại, vì vậy MyViewControllerkhông bao giờ được giải quyết.
Darrarski

5
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timerCalled) userInfo:nil repeats:NO];

-(void)timerCalled
{
     NSLog(@"Timer Called");
     // Your Code
}

bạn đã viết cái này ở đâu
Mohit

1
@JigneshB câu trả lời này chỉ là về cách sử dụng NSTimer chứ không phải về việc sử dụng nó trong nền
Mohit

tôi đã viết trong phương thức nền tức là - (void) applicationDid EntryBackground: (UIApplication *) application {}
Jignesh B

với chế độ lặp lại CÓ
Jignesh B

Tài liệu của Apple rất cụ thể về chữ ký của phương thức gọi lại. Bạn sai rồi.
Nikolai Ruhe

2

Các câu trả lời bị thiếu một thời gian cụ thể của bộ đếm thời gian trong ngày ở đây là vào giờ tiếp theo:

NSCalendarUnit allUnits = NSCalendarUnitYear   | NSCalendarUnitMonth |
                          NSCalendarUnitDay    | NSCalendarUnitHour  |
                          NSCalendarUnitMinute | NSCalendarUnitSecond;

NSCalendar *calendar = [[ NSCalendar alloc]  
                          initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *weekdayComponents = [calendar components: allUnits 
                                                  fromDate: [ NSDate date ] ];

[ weekdayComponents setHour: weekdayComponents.hour + 1 ];
[ weekdayComponents setMinute: 0 ];
[ weekdayComponents setSecond: 0 ];

NSDate *nextTime = [ calendar dateFromComponents: weekdayComponents ];

refreshTimer = [[ NSTimer alloc ] initWithFireDate: nextTime
                                          interval: 0.0
                                            target: self
                                          selector: @selector( doRefresh )
                                          userInfo: nil repeats: NO ];

[[NSRunLoop currentRunLoop] addTimer: refreshTimer forMode: NSDefaultRunLoopMode];

Tất nhiên, thay thế "doRefresh" bằng phương thức mong muốn của lớp bạn

cố gắng tạo đối tượng lịch một lần và làm cho allUnits trở thành tĩnh cho hiệu quả.

thêm một thành phần giờ hoạt động tốt, không cần kiểm tra nửa đêm ( liên kết )

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.