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