ページ

ラベル objective-c の投稿を表示しています。 すべての投稿を表示
ラベル objective-c の投稿を表示しています。 すべての投稿を表示

2010年5月31日月曜日

Objective-C カテゴリでプロパティ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

例えばこんなクラスがあるとする。

Customer.h

@interface Customer :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * address1;
@property (nonatomic, retain) NSString * postcode;
@property (nonatomic, retain) NSString * lastname;
@property (nonatomic, retain) NSString * address2;
@property (nonatomic, retain) NSString * firstname;
@property (nonatomic, retain) NSDate * birthdate;
@property (nonatomic, retain) NSString * firstnameKana;
@property (nonatomic, retain) NSString * lastnameKana;

@end



birthdate(誕生日)から現時点での年齢を計算したいのだが、これをプロパティとして取得できるようにしたい。これをカテゴリで実装する。

こんな感じ。

Customer+Extension.h

#import "Customer.h"

@interface Customer (Extension)

@property (assign, nonatomic, readonly) NSInteger age;

@end


追加メソッドをプロパティとして実装できる。

@implementation Customer (Extension)

- (NSInteger)ageForBirthday_:(NSDate *)dateOfBirth {
  :
}

- (NSInteger)age
{
return [self ageForBirthday_:self.birthdate];
}



これを使う場合はこんな感じ。

#import "Customer+Extension.h"



cell.detailTextLabel.text =
[NSString stringWithFormat:@"%d歳", customer.age];


参考)
Calculate age in objective-c | I ticked the wrong box

Cocoaの日々: CoreData - Xcodeでモデルクラスを自動生成する

2010年1月14日木曜日

+initialize は2度呼ばれる(場合あり)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

+initialize はクラスのイニシャライザ(初期化メソッド)。クラスがロードされた時に呼び出される。これが2度呼ばれることがある(状況によってはさらに複数回呼び出される)。

Mac Dev Center にそんな情報があった。

Mac Dev Center: Coding Guidelines for Cocoa: Tips and Techniques for Framework Developers

試してみよう。

ParentClass とそれを継承した ChildClass を作る。

ParentClass.h

@interface ParentClass : NSObject {

}

@end


ParentClass.m

#import "ParentClass.h"

@implementation ParentClass

+ (void)initialize
{
NSLog(@"initialize: %@", self);
}

@end


ChildClass.h

#import "ParentClass.h"

@interface ChildClass : ParentClass {

}

@end


ChildClass.m

#import "ChildClass.h"

@implementation ChildClass

@end




+initialize は ParentClass のみ実装し、ChildClass では実装しない。

これを実行時に、例えば AppDelegate などでインスタンス化する。


- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application

// [ChildClass self];
[[ChildClass alloc] init];
}


結果はこう。

Test[1116:80f] initialize: ParentClass
Test[1116:80f] initialize: ChildClass


ParentClass の +initialize が2回呼び出されいている。これはランタイムが使用するクラスへ +initialize を投げるのだが、派生クラスに実装がない場合は親クラスのメソッドが呼び出されるため(そういう意味ではクラスメソッドも、インスタンスメソッド同様にメッセージのルーティングが行われている)。


試しに ChildClass.m に +initialize を実装してみる。

#import "ChildClass.h"

@implementation ChildClass

+ (void)initialize
{
NSLog(@"initialize in ChildClass: %@", self);
}

@end


結果はこう。

Test[1199:80f] initialize: ParentClass
Test[1199:80f] initialize in ChildClass: ChildClass



先のりファンレスでは初期化処理が複数回呼び出されるのを避ける為に self をチェックするのが良いと書かれていた。

こんな感じ。


#import "ParentClass.h"

@implementation ParentClass

+ (void)initialize
{
if (self == [ParentClass class]) {
NSLog(@"initialize: %@", self);
}
}

@end


ChildClass の initialize を消して再び実行すると:


Test[1250:80f] initialize: ParentClass




派生クラスが想定される場合、親となるクラスでの +initialize を実装する場合は気を付ける必要がある。

2009年9月20日日曜日

Objective-Cでクロージャ? 〜 Blocks

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

Blocksをちょっと試してみた。

詳しくは ADC に記事がある。
Blocks Programming Topics


NSArray の enumerateObjectsUsingBlock: を使ってみる。

配列内のオブジェクトに対する処理をこんな感じでかける。

NSMutableArray* array = [NSArray arrayWithObjects:
@"cat", @"dog", @"monkey", @"dolphin", @"elephant", nil];

[array enumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"%@, %d", obj, idx);
}
];


結果。
 cat, 0
dog, 1
monkey, 2
dolphin, 3
elephant, 4


おおこれは面白い。


Blocks関係の参考情報:
マルチコア時代の新機軸! Snow LeopardのGCD
Objective-C Blocks

2009年7月12日日曜日

プロトコルの @optional

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

iPhone開発本を読んでいて知ったのだが Objective-C 2.0 ではプロトコルに @optional が追加され、実装が任意のメソッドを定義できるようになっている。

Objective-C 2.0プログラミング言語 > 任意のプロトコル(日本語)

こんな感じ(上記 ADCリファレンス より引用)

@protocol MyProtocol

- (void)requiredMethod;

@optional
- (void)anOptionalMethod;
- (void)anotherOptionalMethod;

@required
- (void)anotherRequiredMethod;

@end


知らなかった。WEBの情報だけでなくたまには本も読むものだ(と思ったりした)。


(参考)
Wikipedia - Objective-C: Protocols
以下、上記サイトから引用。
Objective-C 2.0 added support for marking certain methods in a protocol optional; the compiler will not enforce that such methods are implemented.


iPhoneアプリ開発まっしぐら - iPhoneアプリ開発における 非形式プロトコル (informal protocol) の利用について

# なるほど。非形式なプロトコルを使わないで任意実装メソッドが定義できるようになったのか。

2009年7月10日金曜日

Objective-C 2.0 プロパティのsetter/getterを自前で実装

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

前回のコードでは setter/getterを自前で実装したいが為にプロパティ宣言は行わなかったが、調べてみるとできることがわかった。

http://journal.mycom.co.jp/column/objc/102/index.html



ダイナミックObjective-C - 102 プロパティ(2) - プロパティの宣言


前回のコード:
HotkeyTextView.h
@interface HotkeyTextView : NSTextView {

BOOL _is_editing;
Hotkey* _hotkey;
}

@property (retain) Hotkey* hotkey;

- (Hotkey*)hotkey;
- (void)setHotkey:(Hotkey*)hotkey;


HotkeyTextView.m
@implementation HotkeyTextView

@synthesize hotkey = _hotkey



AppController.m
- (void)awakeFromNib
{
:
[_text1 setHotkey:hotkey];
:



これをこうする。

HotkeyTextView.h
@property (retain) Hotkey* hotkey;   // プロパティ宣言追加

//- (Hotkey*)hotkey; // コメントアウト
//- (void)setHotkey:(Hotkey*)hotkey; // コメントアウト



HotkeyTextView.m
@implementation HotkeyTextView

// @synthesize hotkey = _hotkey <-- コメントアウト



AppController.m
// [_text1 setHotkey:hotkey];
_text1.hotkey = hotkey; // プロパティでアクセス



つまり @synthesize が setter/getter メソッドを自動生成するので、その宣言をなくすだけで良い。