2012/05/21

Blockを用いたHookの利用

viewWillAppearで生成したオブジェクトをviewDidDisappearで解放する場合等に、ブロックを使うと関連するコードをまとめて記述できます。この方法であればプロパティが増えてもそれぞれにhookを記述できるので、記述漏れを予防しやすいと思います。

- (void)viewWillAppear:(BOOL)animated
{
   [super viewWillDisappear:animated];
    
    self.viewWillDisapperHooks = [[NSMutableArray alloc]init];
 
    self.myobject = [[MyObject alloc]init];
    [self.viewWillDisapperHooks addObject:^{
            self.myobject =nil;
        }];
}


- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
    for(void (^hook)(void) in self.viewWillDisapperHooks){
        hook();
    }
    self.viewWillDisapperHooks=nil;    
}

2012/05/18

hidden or visible?

CocoaのUI Viewは、オブジェクトを非表示にするためのhiddenという属性を持っています。ただ、他のフレームワークでは同じ目的で意味が反転したvisibleという属性があることが多く、僕はちょっと混乱していました。特にenableと組み合わせる場合に、ユーザ操作可能なのがYESなのかNOなのかがわかりにくくないですか?

この辺は設計思想に関わることなので、フレームワークのお作法に慣れる方が望ましいです。でも、嫌な人は我慢せずにさくさくっとカテゴリで拡張しちゃいましょう。当然プロパティアクセスも可能です。

UIView+Visible.h
#import <UIKit/UIKit.h>

@interface UIView (Visible)

@property(nonatomic,getter=isVisible) BOOL visible;

@end

UIView+Visible.m
#import "UIView+Visible.h"

@implementation UIView (Visible)

- (BOOL)isVisible
{
    return !self.hidden;
}

- (void)setVisible:(BOOL)visible
{
    self.hidden = !visible;
}

@end

外からはreadonlyで、中からはreadwriteな@property

さっき気がついたことのメモ。
readonlyで定義したpropertyを、実装ファイル側でreadwriteに上書きできます。immutableなクラスでpropertyを使う場合にとっても便利。

HOGEHOGE.h
@interface HOGEHOGE : NSObject
@property(readonly,nonatomic,copy) NSString* title;
@end
HOGEHOGE.m
@interface HOGEHOGE ()
@property(readwrite,nonatomic,copy) NSString* title;
@end

@implementation HOGEHOGE
@synthesize title=_title;
@end
ひとりでコードを書いていると、この手の基本的なことをずっと知らなかったりします。

2012/05/17

NSStringの定数定義

これも常識だと思いますが、備忘録としてメモ

定数の命名規則

歴史的にkで始まる定義をよく見かけますが、 Coding Guidelines for Cocoaにはそのようなルールはないようです。他の定数と衝突しないことが重要なので、僕は「クラス名」+「k」+「変数名」を使用しています。

グローバルな定数

他からも参照できるようにヘッダーファイルでextern宣言し、実装ファイル内に定義します。

HogeHoge.h file
extern NSString* const HogeHogekMogeMoge;
HogeHoge.m file
NSString* const HogeHogekMogeMoge = @"HAGAHAGA";

ローカルな定数

Headerファイルでは特に定義をせず、実装ファイル内でstaticに定義しスコープをコンパイル単位に限定します。

HogeHoge.h file
定義なし
HogeHoge.m file
static NSString* const HogeHogekMogeMoge = @"HAGAHAGA";

2012/05/16

ARC環境でweak pointerがnilになるタイミング

検証コードをまとめる余裕がないのでメモとして。

weak pointerにselfを保存している場合、deallocが呼ばれるより前にnilになるようです。つまり下記のような実行順序と考えられます。

  • オブジェクトを指すstrong pointerの数が0になる
  • オブジェクトを指すweak pointerがnullifyされる(nilになる)
  • オブジェクトがdeallocされる
考えてみれば当たり前ですね。

僕の場合、Notification Centerに登録する際に登録解除処理をブロックとして保存し、deallocで呼び出すつもりでした。ここでweak pointerを使うとdealloc呼び出し時にはnullifyされていて動作しません。逆に、strong pointerを使っているとそもそもdeallocされません。このような場合、unsafe_unretained pointerを使うことでオブジェクトを解放しつつ、nullifyを避けることができます。iOS4互換のためだけに存在すると思っていたんですが、こんな利用法があるんですね。

でも多分、今回のケースにおける正解は「そんなコードは書かない」だと思います:-p

2012/05/02

Javaプログラマ的なDynamoDBの捉え方

予測可能なパフォーマンスを、メンテナンスフリーで手に入れられるAmazon DynamoDB。非常に魅力的ではありますが、DynamoDBは徹底的にKey-Valueな考えが必要になります。というか、主キー以外でのルックアップは基本的に実行できないと考えた方が良いです。特にPrimary Keyの扱いが重要なので、ちょっとまとめみました。

DynamoDBのPrimary Keyには「Hash Type Primary Key」と、「Hash and Range Type Primary Key」の二種類があります。詳しい解説は他のサイトにまかせるとして、これらをJavaプログラマ的に捉えると下記のようになります。

Hash Type Primary Key

Map<HashKey,Object>
Hash Type Primary Keyを使用する場合には、本当に純粋なMapとして捉えられます。HashKeyが適切に分散さえしていれば、DynamoDBのすばらしい性能の恩恵を受けることができます。

Hash and Range Type Primary Key

Map<HashKey, SortedMap<RangeKey,Object>>
Hash and Range Type Primary Keyを使用する場合にも、Hash Keyの役割は変わりません。ただ、これに加えて、ソートされたRange Keyを用いることができます。Range Keyはソートされているだけでなく、Queryという機能を用いて柔軟にアクセスできます。ただし、Range Keyだけでは十分な分散は実現できません。

Primary Keyを用いないアクセス

Primary Keyを用いない場合には、Scanという機能で総当たり処理が可能です。ただ、Scanは主キーを無視した完全な総当たり処理であり、原則として実運用に用いるべきものではないと考えます。Primary Key以外で検索を行う必要がある場合には、別のTableをインデックスとして作成するか、DynamoDB以外と組み合わせることを検討した方が良いと思います。

Use it well

DynamoDBは強い癖がありますが、うまく使えば非常に強力な道具になります。エンジニアの腕の見せ所ですね。