2013/12/11 #potatotips
FUJI Goro (gfx) at COOKPAD, Inc.
- C/C++/Perl/JS/Java/Ruby engineer
- JSX committer
- JSX Advent Calendar 2013 is working in progress!
Resource Aquisition Is Initialization
- C++で発明されたリソース管理パターン
- オブジェクトのライフサイクルとリソース管理をリンクさせる手法
- Objective-Cでは、
-init
でリソースを獲得して-dealloc
でリソースを開放するとRAIIになる - ここでリソースとは「開始と終了のある何か」のこと
- サブプロセスのforkとkill
- ネットワークインジケータ(a.k.a. 「くるくる」)のon/off
- ある区間でかかった時間を測定する
NetworkActivityIndicatorをon/offする。
@interface NetworkActivityGuard : NSObject
@end
@implementation NetworkActivityGuard
- (id)init
{
self = [super init];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: YES];
return self;
}
- (void)dealloc
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: NO];
}
@end
任意のコードをスコープ終了時に実行できる。golangのdefer文のObjC版。
@interface ScopeGuard : NSObject
@end
typedef void (^voidBlock)();
@implementation ScopeGuard {
voidBlock _block;
}
- (id)initWithBlock: (voidBlock)block
{
self = [super init];
self->_block = [block copy];
return self;
}
- (void)dealloc
{
_block();
}
+(id)newWitBlock:(voidBlock)block
{
return [[self alloc] initWithBlock:block];
}
@end // ScopeGuard
- (IBAction)startAction:(id)sender {
NSLog(@"started");
self.label.text = @"Working In Progress";
NSMutableArray * const guards = [NSMutableArray new];
[guards addObject: [ScopeGuard newWitBlock:^{
self.label.text = @"Hello, world!";
}]];
[guards addObject:[NetworkActivityGuard new]];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
double const delayInSeconds = 1.5;
dispatch_time_t const popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSLog(@"finished");
if (YES /* complex condition */) {
return; // no need to release guard objects!
}
(void)guards; // to capture guard objects!
});
}
- 「guradsを参照する、しかし使わない」と読む
- ブロックに変数を強制的にキャプチャさせるときのイディオム
- voidにキャストしているのは、これがないとコンパイラが警告するため
(if time permits)