NSTimer'i nasıl kullanırım?


Yanıtlar:


616

Öncelikle, dikkatinizi Cocoa / CF belgelerine çekmek istiyorum (her zaman harika bir ilk bağlantı noktasıdır). Apple dokümanlarında, her bir referans makalenin üstünde, "Tamamlayıcı Kılavuzlar" adında bir bölüm bulunur ve bu bölüm belgelenen konunun (varsa) kılavuzlarını listeler. Örneğin, birlikte NSTimer, dokümantasyon listeleri İki tamamlayıcı kılavuzları:

Durumunuz için, Zamanlayıcı Programlama Konuları makalesi muhtemelen en yararlı olanıdır, ancak iş parçacığı konuları ilişkilidir ancak belgelenen sınıfla en doğrudan ilişkili değildir. Zamanlayıcı Programlama Konuları makalesine göz atarsanız, makale iki bölüme ayrılır:

  • Zamanlayıcılar
  • Zamanlayıcıları Kullanma

Bu biçimi almak eşyalar için, ilgili sınıfın ve ne için kullanılır ve daha sonra bazı örnek kod bir bakış var genelde nasıl "kullanma Zamanlayıcılar" bölümünde bu durumda, kullanmak. "Zamanlayıcı Oluşturma ve Zamanlama", "Zamanlayıcıyı Durdurma" ve "Bellek Yönetimi" bölümleri vardır. Makaleden, planlanmış, tekrar etmeyen bir zamanlayıcı oluşturmak şu şekilde yapılabilir:

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

Bu 2,0 saniye sonra ateş ve çağrıları bir zamanlayıcı yaratacak targetMethod:üzerinde selfbir göstericidir tek argümanı ile NSTimerörneğin.

Daha sonra yönteme daha ayrıntılı bir şekilde bakmak isterseniz, daha fazla bilgi için dokümanlara geri dönebilirsiniz, ancak kodun etrafında da bir açıklama var.

Tekrar eden bir zamanlayıcıyı durdurmak (veya tekrar etmeyen bir zamanlayıcıyı tetiklemeden önce durdurmak) istiyorsanız NSTimer, oluşturulan örneğe bir işaretçi tutmanız gerekir ; genellikle başka bir yöntemde başvurabilmeniz için bunun bir örnek değişkeni olması gerekir. Daha sonra arayabilir invalidateüzerinde NSTimerMesela:

[myTimer invalidate];
myTimer = nil;

nilÖrnek değişkenini dışarıda bırakmak da iyi bir uygulamadır (örneğin, zamanlayıcıyı geçersiz kılan yönteminiz birden fazla çağrılırsa ve örnek değişkeni ayarlanmamışsa nilve NSTimerörnek yeniden yerleştirilmişse, bir istisna atar).

Ayrıca makalenin altındaki Bellek Yönetimi konusuna dikkat edin:

Çalışma döngüsü zamanlayıcıyı koruduğundan, bellek yönetimi açısından, zamanlayıcıyı planladıktan sonra genellikle bir zamanlayıcıya başvurmaya gerek yoktur . Zamanlayıcı, yöntemini seçici olarak belirttiğinizde bağımsız değişken olarak iletildiğinden, uygun olduğunda bu yöntemde yinelenen bir zamanlayıcıyı geçersiz kılabilirsiniz . Bununla birlikte, birçok durumda, belki de başlamadan önce zamanlayıcıyı geçersiz kılma seçeneğini de istersiniz. Bu durumda, zamanlayıcıya bir referans tutmanız gerekir, böylece uygun olduğunda ona geçersiz bir mesaj gönderebilirsiniz. Planlanmamış bir zamanlayıcı oluşturursanız (bkz. “Planlanmamış Zamanlayıcılar”), kullanmadan önce zamanlayıcıya yerleştirilmemesi için zamanlayıcıya (referans olarak sayılan bir ortamda tuttuğunuzdan) güçlü bir referans sağlamanız gerekir.


Okk, bir soru, her iki saniyede bir çalıştırılacak kodum olarak ne koyardım?
lab12

Sen geçerdi YESiçin repeats:Aradığınızda scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:. Bunu yaparsanız, NSTimerörneğe başvurduğunuzdan emin olun (yöntem tarafından döndürülür) ve yukarıda ayrıntılı olarak açıkladığım gibi Bellek Yönetimi noktasını izleyin.
Alex Rozanski

Hayır, her 2 saniyede bir başlatılan kodumu nereye koyacağım? Örneğin, her 2 saniyede bir bip sesi çıkarmasını istediğimi varsayalım. bip sesi kodunu nereye koyacağım ..?
lab12

Yöntemde Birlikte belirttiğiniz targetve selector. Hedef ise Örneğin, selfve seçicidir timerMethod:zamanlayıcı yangınları olduğunda, yöntemi denir timerMethod:üzerinde tanımlı self. Daha sonra bu yöntemde istediğiniz kodu koyabilirsiniz ve zamanlayıcı her tetiklendiğinde yöntem çağrılır. Zamanlayıcı tetiklendiğinde (olarak kabul ettiğiniz) çağrılan yöntemin selector:yalnızca bir argüman alabileceğini unutmayın (çağrıldığında NSTimerörneğe bir işaretçi ).
Alex Rozanski

Üzgünüz, "tanımlanmış self" anlamına geliyordu
Alex Rozanski

331

bir zamanlayıcı kullanmanın birkaç yolu vardır:

1) programlı zamanlayıcı ve seçici kullanarak

NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
                      target: self
                      selector:@selector(onTick:)
                      userInfo: nil repeats:NO];
  • Tekrarları HAYIR olarak ayarlarsanız, zamanlayıcı seçiciyi çalıştırmadan önce 2 saniye bekleyecek ve bundan sonra duracaktır;
  • tekrarlarsa: EVET, zamanlayıcı hemen başlar ve seçici her 2 saniyede bir çağrılır;
  • zamanlayıcıyı durdurmak için zamanlayıcının -invalidate yöntemini çağırırsınız: [t geçersiz kıl];

Yan not olarak, belirtilen aralıktan sonra tekrarlayıcı olmayan ve seçiciyi çağıran bir zamanlayıcı kullanmak yerine, aşağıdaki gibi basit bir ifade kullanabilirsiniz:

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

bu yukarıdaki örnek kodla aynı etkiye sahip olacaktır; ancak seçiciyi her nci seferde çağırmak istiyorsanız, zamanlayıcıyı tekrarlarla kullanırsınız: YES;

2) kendinden programlı zamanlayıcı

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];
  • bu, sizin belirlediğiniz özel bir tarihte (bu durumda, bir dakika sonra) başlayacak ve her saniyede bir kendini tekrarlayacak bir zamanlayıcı oluşturur.

3) programlanmamış zamanlayıcı ve çağrı kullanma

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];

ve bundan sonra, böyle bir şeye ihtiyacınız olduğunda zamanlayıcıyı manuel olarak başlatırsınız:

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



Ve bir not olarak, onTick: yöntemi şöyle görünür:

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

Tamam, ama benim uygulama şeffaflığını azaltmak istiyorum, bu yüzden bunu NSTimer ile nasıl uygulayacağımı bilmiyorum
lab12

24
Tanrım, bu insanlar bugün .. benden oy kullan, çünkü bunu en başından beri belirtmedin ve boşuna yazalım!
Woofy

28
Boşuna yazmadın. Bu iyi bir bilgi!
willc2

Yöntem 2, "kendinden zamanlamalı zamanlayıcı", istediğimde zamanlayıcıyı nasıl durdurabilirim?
Satyam

1
@Satyamsvv, zamanlayıcıyı çağırarak durdurabilirsiniz, başka bir yönteme sahip olun: [zamanlayıcı geçersiz kıl]; zamanlayıcı = sıfır;
Kimpoy

59

Bunun gibi bir şey:

NSTimer *timer;

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

14
Hala güçlü oluyor ... 2014 de!
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

Her nasılsa tutma döngüsünü yaratır, böylece MyViewControllerasla yeniden konumlandırılmaz .
Darrarski

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

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

bunu nereye yazdın
Mohit

1
@JigneshB bu cevap sadece NSTimer nasıl kullanılacağı hakkında değil arka planda kullanmak değil
Mohit

arka plan yönteminde
yazdım

tekrarlanan mod ile EVET
Jignesh B

Apple'ın belgeleri geri arama yönteminin imzası hakkında çok özeldir. Seninki yanlış.
Nikolai Ruhe

2

Cevaplar günün belirli bir zamanlayıcısını kaçırıyor, burada bir sonraki saatte:

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];

Tabii ki, "doRefresh" yerine sınıfınızın istediğiniz yöntemini kullanın

takvim nesnesini bir kez oluşturmaya çalışın ve allUnits'i verimlilik için statik hale getirin.

bir saatlik bileşen eklemek iyi çalışıyor, gece yarısı testine gerek yok ( bağlantı )

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.