6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

インスタンスが生成されてから一度しか実行されない機構

Last updated at Posted at 2014-09-03

概要

dispatch_onceを使えばインスタンスのライフサイクルで1度しか実行されないことを保証する機構ができます。
できませんでした。

詳細についてはコメント欄をどうぞ

背景

インスタンスが生成されてから一度だけ実行したい処理というのは出てくると思います。そんなの init でやればいいのですが、
状況によっては init の時には準備が整っておらず、任意のタイミングで処理を実行したいことがあると思います。

その時にフラグのプロパティを持つのはダサい、マルチスレッド面倒!という場合の解決策です。

概要

  • インスタンスにdispatch_once_t型のプロパティを持つ
  • このプロパティをdispatch_onceに渡して実行する

コード

@interface MyObject : NSObject
@property (nonatomic, assign) dispatch_once_t onceToken;
- (void)runOnce;
@end


@implementation MyObject
- (void)runOnce {
    dispatch_once(&(_onceToken), ^{
		// 一度しか実行しない処理をここに書く
    });
}
@end

実験とその結果

以下のクラスに対して、処理を100回リクエストする処理を行いました。

@interface MyObject : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) dispatch_once_t onceToken;
@property (nonatomic, assign) NSInteger count;
- (void)runOnce;
@end

@implementation MyObject

+ (instancetype)objectForName:(NSString *)name {
    MyObject *obj = [MyObject new];
    obj.name = name;
    return obj;
}

- (void)runOnce {
    dispatch_once(&(_onceToken), ^{
        _count++;
        NSLog(@"%@ : here!!!", _name);
    });
}
@end

MyObject *obj1 = [MyObject objectForName:@"obj1"];
MyObject *obj2 = [MyObject objectForName:@"obj2"];

dispatch_group_t group = dispatch_group_create();

for (NSInteger i = 0; i < 100; ++i) {
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [obj1 runOnce];
        [obj2 runOnce];
    });
}

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

NSLog(@"%@ -> %ld", obj1.name, obj1.count);
NSLog(@"%@ -> %ld", obj2.name, obj2.count);

2014-09-03 19:27:08.895 project[28275:7400318] obj1 : here!!!
2014-09-03 19:27:08.896 project[28275:7400318] obj2 : here!!!
2014-09-03 19:27:08.896 project[28275:7400187] obj1 -> 1
2014-09-03 19:27:08.896 project[28275:7400187] obj2 -> 1

様々なスレッドからobj1, obj2に対してrunOnceを呼んでいますがobj1, obj2のどちらも処理は一度しか行われていないのが分かります。

注意点

onceTokenは書き換え可能なのでインスタンス内などで上書きしないようにしましょう。
tokenの値が元に戻ると再び処理が実行されます。

6
7
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?