ヘッダーファイルにて、プロパティ宣言をすることでそのプロパティについてのゲッターセッターが実装される。
プロパティ宣言をしなくても、自分で実装処理を書いてもよい
プロパティの書式は、
//ヘッダーファイルに書く
//@property (属性 , 属性, ・・・) データ型, 名前
//例
@property ( nonatomic, retain ) NSTimeZone* timeZone;
//ソースファイルに書く
@synthesize timeZone;
上の例を自分で実装した場合は
//ソースファイルに書く
//ゲッター
-(NSTimeZone*) timeZone{
//同時実行不可のための処理:属性nonatomicに相当
@synchronized(self){
return timeZone;
}
}
//セッター:読み書きについて属性が未設定なのでセッターまで生成される
-(void) setTimeZone:(NSTimeZone *)zone{
//同時実行不可のための処理:属性nonatomicに相当
@synchronized(self){
if(timeZone != zone){
[timeZone release];
timeZone = [zone retain];//保持する際は保持カウントをアップさせる:属性retainに相当
}
}
}
※@synchronizedは排他制御するかしないか。
マルチスレッドで同時に実行して欲しくない処理があるとき、これを指定することで片方のスレッドを停止することができる。
上の例では排他制御に対応しており、プロパティの属性でnonatomicを指定すると、排他制御はしなくなる。
Tags: iPhone, Objective-C
クラスファイルの最後の方にやたら登場するdeallocメソッド
NSObjectのメソッドで、それをオーバーライドしている。
dealloc実行のタイミングは保持カウントが0になったときに実行される。
保持カウントはインスタンスの生成、retainさせた参照の追加でカウントアップ。
releaseでカウントダウンされるのでカウント数には注意が必要。
例)
- (void)dealloc {
[window release];
//スーパークラス(NSObject)のdeallocを実行することで実際のメモリの破棄
//C言語のfree関数のようなもの
[super dealloc];
}
Tags: iPhone, Objective-C
Objective-Cにはプロトコルという概念がある。
ActionScriptでいうところのInterfaceみたいなものらしい。
記述はヘッダーファイルでのクラスの定義のところに書く
@interface クラス名 : スーパークラス名 <プロトコル名>
//例
@interface ClockAppDelegate : NSObject <UIApplicati> {
プロトコルはデリゲートとも関わりがある。
たとえば、あるAクラスのデリゲート対象とされたBクラスはAクラスのプロトコルを記述しないとWarningになる。
//例)
//UIWebViewクラスのインスタンス(webView)が現在のクラス(self)にデリゲートされてる
webView.delegate = self;
//このwebViewを持ったクラスはヘッダーファイルにUIWebViewDelegateプロトコルを追加しなくてはならない。
//例
@interface WebAppDelegate : NSObject <UIApplicationDelegate,UIWebViewDelegate> {}
Tags: iPhone, Objective-C
クラスのインスタンスの生成方法
AS3はこんな感じ
//AS3
//newでコンストラクタを実行。
var hoge:MovieClip= new MovieClip();
obj-cはnewでなくて、各クラスによって色んな初期化メソッドが用意されているみたい。
//Objective-C
//NSStringの場合
//直接文字列を入れて初期化
NSString* str = @"HOGEHOGEO";
//NSString専用の初期化用のメソッドを使う
//文字列から生成
NSString* str = [NSString stringWithString: @"HOGEHOGEO"];
//既存の数値を利用して生成
NSString* str = [NSString stringWithFormat: @"ほげ:%d",100];
※またどのクラスでも通用する汎用の初期化メソッドもある。
(これがASのnewに近いのかな)
[[クラス名 alloc] init]
allocでメモリを確保して、initメソッドを実行
(initメソッドはNSObjectのメソッド)
あとallocでメモリ領域を確保した場合は使用後は自分で破棄しないとダメ
(iPhoneはGC無いので)
破棄は
[インスタンス名 release];
//Objective-C
//allocでインスタンス用のメモリを確保し、initを実行
NSString* str = [[NSString alloc] init];
//※ただしNSStringのインスタンスは文字列の上書きができないので上記でインスタンスを作ると中身が空っぽのインスタンスができるだけとなる。
NSLog(@"%@",str);//出力:(ブランク)
//破棄
[str release];
2010/05/21:追記
objective-cでもnewを使ったインスタンスの生成はできる
//newを使った例
NSDate* date = [NSDate new];
//newを使わない(上と同じ意味)
NSDate* date = [[NSDate alloc] init];
Tags: iPhone, Objective-C
アプリケーション自身とか、オブジェクト(クラス)が最初から持っている固有の動作(イベント的なメソッド?)がある。
たとえば、
アプリ起動時に実行されるメソッド、とか
アプリ起動中に着信があった場合に実行されるメソッド、とか
アプリ終了時に実行されるメソッド、など。
これらのメソッドは誰が実行するかを決めた上で、メソッドの中身を実装する必要がある。
誰が(どのクラスが?)、を決める作業をデリゲートを登録するという。
登録はIBのInspectorウィンドウから行う。
(IB使わなくてもObj-Cからも可能)
デリゲートとして登録されたクラスにそれぞれのメソッドを実装することで機能として使えるようになる。
感覚的には各クラスに用意されているメソッドをオーバーライドしているのと同じだろうけど、サブクラスを作る必要がなく、関連の無いクラスからでも、(オーバーライドしたようなメソッドとして)実行することができる。
IBで配置したオブジェクトについていちいちサブクラス作るのメンドイからこの仕組みがあるのかも。
Tags: iPhone, Objective-C
Objecttive-CにおけるASでいうところのtraceにあたるものは、NSLog()
c言語ベースなのでprintf()でもコンソールに出力できるけどWarningがでたりするのでNSLog使った方がいいみたい。
(Object型のデータの出力に特化って感じかな?)
書き方は、printfとかと同様に変換指定子を使う。%+記号
//%@でオブジェクト型のデータ
NSLog(@"結果は:%@",@"あいうえお");//出力:結果は:あいうえお
Tags: iPhone, Objective-C
PRMLLoaderクラスは、xml形式のデータを外部読み込みすることで、progressionのシーン構成を生成するクラスでちょっとはまったのでメモ。
PRMLLoaderクラスの使い方は、ProgressionによるFlashコンテンツ開発ガイドのp268に分かりやすく書いてあるのでその通りにならって実行したつもりが、題記エラーが表示されました。。。
だがしかし、書籍のサンプルファイルをダウンロードしてみるとちゃんとできてる。
書籍サンプルファイルと自分のプロジェクトの差異はなんなんだ?
とひと晩結果が、xmlでのクラスファイル(cls属性)の指定が間違っていました。
まずは、OK
(問題なしの書籍のサンプルは以下の画像のようなプロジェクト構成)
そして、NG
(題記エラーが表示されたプロジェクト構成)
※xmlはいずれも以下の通りとした
<?xml version="1.0" encoding="UTF-8" ?>
<prml version="2.0.0" type="text/prml">
<scene name="index" cls="IndexScene">
</scene>
</prml>
まずOKのNGの違いは、IndexSceneがパッケージでくるまれてるかくるまれていないか、ということ。
OKは、srcの直下にIndexScenen.asがあるのでパッケージにはくるまれていない。
NGは、srcの直下にあるcsr393pv3dというパッケージでくるまれている。
結論としては、パッケージからのパスをxmlのcls属性に設定することが必要。
srcの直下にあるcsr393pv3dにIndexSceneが含まれた場合は、、
<?xml version="1.0" encoding="UTF-8" ?>
<prml version="2.0.0" type="text/prml">
<scene name="index" cls="csr393pv3d.IndexScene">
</scene>
</prml>
これで正常に実行される。
つまり、srcからみたパスの構成を、xmlのcls記述に記述する必要がある。
Progrssionの勉強中にはまったことメモ。
FlashDevelop(以下FD)のProgression用プロジェクトテンプレートを使って試してます。
(FlashIDE無しでも作れちゃうのはホント便利)
Progressionは基本preloader.swf、index.swfの二つを使うので、上記テンプレートの使い方として、FDのprojectファイルを切り替えてパブリッシュしていきます。
いろいろごちゃごちゃやってたときにpreloader.swfをパブリッシュ時に以下のエラーが発生
Error #1065: 変数 ContextMenuClipboardItems は定義されていません。
preloader,indexともにソースコードをデフォルトに戻しても直らないのでなんだこりゃ?としばらく途方にくれました。。。
で、原因はというと、preloaderの対象となるFlashPlayerのヴァージョンを9でパブリッシュして、indexではヴァージョンを10でパブリッシュしていたというオチ。
(そういや、ごちゃごちゃやってるときにプレイヤーは10じゃないとダメだということで、indexだけ変更してたんだったな、と)
ContextMenuClipboardItems はFlashPlayer10から使える機能なので、FlashPlayer9のpreloader.swfからFlashPlayer10のindex.swfを読み込んだ際に使えないよってエラーだったようだ。
エラー内容読めばそのまんまなんだけどね。
というわけで、FlashPlayerのヴァージョンを変更する場合は、preloaderとindexをそろえてやることを忘れずに。。。
(調べてないけどprogressionに限らず親が9で、10の子swfを読み込んだ場合は必ず発生するのかな?)
ちなみにFDでは各プロジェクトのプロパティからプレイヤ-のバージョンを変更可能。