11

バックグラウンド タスクとして使用するために、GCD ブロック (2 秒ごとに 1 回起動し、メソッドを呼び出す) でタイマーを作成したいと考えています。しかし、私が見るように、タイマーは決して起動しません。これが私のコードです:

- (void)startMessaging
{
    BOOL queue = YES;
    dispatch_queue_t _queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0, _queue);
    dispatch_source_set_timer(timerSource, dispatch_walltime(NULL, 0), 2ull * NSEC_PER_SEC,1ull * NSEC_PER_SEC );
    dispatch_source_set_event_handler(timerSource, ^{
        if (queue) {
            [self observeNewMsgs];
        }
    });
    dispatch_resume(timerSource);
}

- (void)observeNewMsgs
{
    NSLog(@"JUST TO TEST");
    // Staff code...
}

では、これの何が問題なのですか?どうすればこれを修正できますか?

4

1 に答える 1

32

クラスプロパティまたはインスタンス変数を作成する必要がdispatch_source_tあるため、スコープから外れないようにする必要があります(ARCでは、スコープから外れると解放されるため)。これを行うと、コードは正常に機能します。たとえば、次のようになります。

@interface ViewController ()
@property (nonatomic, strong) dispatch_source_t timerSource;
@property (getter = isObservingMessages) BOOL observingMessages;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self startMessaging];
}

- (void)startMessaging
{
    self.observingMessages = YES;
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    self.timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(self.timerSource, dispatch_walltime(NULL, 0), 2ull * NSEC_PER_SEC, 1ull * NSEC_PER_SEC);
    dispatch_source_set_event_handler(self.timerSource, ^{
        if (self.isObservingMessages) {
            [self observeNewMsgs];
        }
    });
    dispatch_resume(self.timerSource);
}

- (void)observeNewMsgs
{
    NSLog(@"JUST TO TEST");
    // Staff code...
}

@end

また、バックグラウンド プロセスが開始された後に your の値を変更する機能が必要な場合は、BOOL上記のように、それをクラス プロパティにすることもできます。observingMessagesまた、その目的をより明確にするために、名前を に変更しました。

(文体的なものですが、クラス インスタンス変数にはアンダースコア文字のみを使用するため、_queue変数の名前を に変更しましqueueた。)

于 2013-01-29T19:34:07.113 に答える