Cocoaアプリケーションを作ってみる
Objective-Cについて簡単に勉強したので、とりあえずコードを書いてみる。書けば分かるさ精神。
今回はここのチュートリアルに沿って、通貨換算アプリケーションを作る。
プロパティー
早速知らない機能が出て来た。@property。Objective-C 2.0の機能らしい。
アクセッサを簡単に作る機能!って理解でよろしい?
@interface Converter : NSObject { float sourceCurrencyAmount,rate; } @property(readwrite) float sourceCurrencyAmount,rate; @end
で、
- (float)sourceCurrencyAmount; - (void)setSourceCurrencyAmount:(float)newSourceCurrencyAmount; - (float)rate; - (void)setRate:(float)newRate;
が宣言されたことになるらしいよ!こりゃ慣れるのに時間がかかりそうだ、、、
実装部では次のように各必要がある。
@implementation Converter @synthesize sourceCurrencyAmount,rate; @end
こーすると使えるようになるご様子。@propertyと@synthesizeはペア。readwrite以外にcopyとかある様子。後で勉強する。
ガベージコレクション
言われた通り書いていたんだが、
「allocしといてfreeしてないけどいいのか?」
と思っていたら、ちゃんと次のページで解説されていた!!
親切すぎて涙。ADC最高。
そして、なんと、
Objective-C 2.0ではガベージコレクションをサポートしているらしい!!
ビックリしたよ!
ガベージコレクションを有効にするには設定が必要。
- 「プロジェクト」>「プロジェクト設定を編集」を選択
- 「ビルド」タブに移動
- 「GCC 4.0 - Code Generation」の下の「Objective-C Garbage Collection」の値を「Supported」に設定
OK
XcodeとInterface Builderの使い方を学んだ。
Objective-Cを勉強してみる - その2
メモメモ
- ラベルが意味不
- (戻り値型)メソッド名 : (引数型) 変数名 ラベル : ....
ラベルとコロンが名前の一部として認識されているため、Objective-C では同じ戻り値、引数、メソッド名を持つメソッドを区別して呼び出すことができるのです。例えば (void)setPoint:(int):(int) というメソッドと(void)setPoint:(int) label:(int) メソッドは異なるメソッドとして宣言、定義することができます。
ほー、これは面白い。
- 自分自身はself。C++のthisに近い。メソッド内でのみ有効なid型の変数。
- 親クラスはsuper。変数ではない。スーパークラスを保有するクラスのインスタンスメソッド内のメッセージ式でのみ利用可。
- ちょっ、、、
void CallMethod( id obj ){ [obj method]; } int main(){ CallMethod([SuperClass alloc]); CallMethod([SubClass alloc]); return 0; }
これって、コンパイル通るわけ?
objがmethodっていうメソッド持ってなかったらどうすんの?
関数が呼び出すメソッドは、実行時にならなければ最終的な判定はできません。
なにー。なるほど確かに動的。
通常、オブジェクトをインスタンス化した場合は直後に init メッセージを送信しなければなりません。この作業は自動的なものではなく、明示的にメッセージから呼び出さなければなりません。
自動にしてくれればいいのに!><
しかし、new メソッドを使えば上記の文を内部で実行してくれるため、イニシャライザが自動的に呼び出される仕組みを再現できます。
あるんじゃん、、、、
[[クラス名 alloc] init] + (id)new;
なるほど、newはクラスメソッド!分かってきた!たぶん。
- 引数付きイニシャライザはinitWith**とするのが習慣らしい
- allocしたらfreeで解放!
- サブクラスでは[super free]を忘れずに。
- コンパイル時に型の判定を行うには、id型ではなくそのクラス型のポインタを使う。
- C++と同じ感じになる。
- インスタンス変数には@public,@private,@protectedの三種の可視性がある。
- デフォルトは@protected。
- @publicとか無いものだと思ってたーー。あるんかい。ちょっと幻滅。
- クラスメソッドはあってもクラス変数はない
- クラス型が意味不
クラスがインスタンスを生成するように、正しくコンパイルされたクラスは、自らの情報を表すクラスオブジェクトを保有しています。 このクラスオブジェクトは Class 型として、変数に保存することも可能です。
?????。だめだ。寝る。
OpenCVのcvGetTickFrequencyが変
OpenCVのcvGetTickFrequencyが変!な気がする。笑。
MacOSだけかもしれんけど。
cvGetTickCount,cvGetTickFrequency
opencv.jpで調べものをしていたら、
cvGetTickCountとcvGetTickFrequencyなる関数があるのを発見。
時間計測をしてくれるらしい。いつからあったのこんな関数?
GetTickCount
tics数を返すint64 cvGetTickCount( void );
関数 cvGetTickCount は,プラットフォーム依存の開始時点からのtics数(スタートアップからのCPU ticks数,1970年からのミリ秒等)を返す. この関数は,ある関数やユーザコードの実行時間を正確に計測するのに便利である. tics数から時間単位に変換するためには,cvGetTickFrequencyを用いる.
etTickFrequency
1ミリ秒あたりのtics数を返すdouble cvGetTickFrequency( void );
関数 cvGetTickFrequency は,1ミリ秒あたりのtics数を返す. つまり,cvGetTickCount() を cvGetTickFrequency() で割った商が,プラットフォーム依存の開始時刻からのミリ秒単位の時刻になる.
とりあえず、使ってみる。
long long int time1 = cvGetTickCount(); process(); // とある処理。0.1秒以下の予定 long long int time2 = cvGetTickCount(); double msec = (double)(time1-time2)/cvGetTickFrequency(); cout << time1 << endl; // 1214131457632194 cout << time2 << endl; // 1214131457650528 cout << cvGetTickFrequency() << endl; // 1 cout << msec << endl; // 18334
いやいやいや、、cvGetTickFrequency() == 1 !!?
体感的にはcvGetTickFrequency() == 1000 くらいなんだけど、、、
変なのは俺?
Google先生に聞くと、みんなcvGetTickFrequency()で割ったあとに、さらに1000で割ってミリ秒にしてる。
変なのはopencv.jp!!
英語のリファレンス見てきた!!
GetTickFrequency
Returns number of tics per microseconddouble cvGetTickFrequency( void );
The function cvGetTickFrequency returns number of tics per microsecond. Thus, the quotient of cvGetTickCount() and cvGetTickFrequency() will give a number of microseconds starting from the platform-dependent event.
microsecondをopencv.jpではミリ秒と訳している様子。一応報告しておくか。
修正された。
対応はぇぇ!!
Objective-Cを勉強してみる - その3
メモメモメモ
- クラスオブジェクトというものがある。
- 良く理解していないが、Class型として変数に保存可能らしい。
- 存在しない場合はNil。NULLと同様に0を表す。
- なら、NULLにしてくれれば良いのに、、、
- クラスオブジェクトの取得
- インスタンスから取得
- クラス名を直接指定して取得
#import <stdio.h> #import <objc/Object.h> @interface Test : Object + (void)Write; - (id)init; @end @implementation Test + (void)Write { printf("I love you... so please do not love me.\n"); } - (id)init { printf("You can be whatever.\n"); return [super init]; } @end int main() { Class testClass = [Test class]; [testClass Write]; [[testClass new] free]; [testClass free]; return 0; }
うーん。メリットがイマイチ分からんなー。
書いていけば理解できるかな?
それと、最後のfreeは必要?
よく分かってないなー。
- セレクタ!?
- ますますObjective-Cがキモイ。なんじゃこりゃ。笑
- メソッドがコンパイル時に変換される内部表現を直接扱えるらしい。
- SEL型の変数として@selectorというコンパイラディレクティブで取得。
- ObjectクラスはSEL型変数を受け取るperformメソッドが存在。
- 受け取ったセレクタが表現するメソッドを実行するらしい。
この性質を上手く利用すれば、実行時に呼び出すべきメソッドを状況に応じて切り替えるようなプログラムを実現することができます。
うーん。実際どう使う?実感が湧かない。これもそいういう場面に出会わないと理解できそうにないなぁ。
- メソッドのポインタ
普段は隠蔽されていますが、メソッドとは最初の引数に自分のクラスを参照するオブジェクトを受け取る関数なのです。
な、なんだって!?
-
- メソッドはIMP型。このポインタを取得可能。
- ポインタから呼んだ方がメッセージより速そう。これは良い。
- カテゴリ
- クラスのメソッドをカテゴリ分けして記述可能。
#import <stdio.h> #import <objc/Object.h> @interface Test : Object - (void)WriteA; @end @interface Test (Fate) - (void)WriteB; @end @implementation Test - (void)WriteA { printf("I am the bone of my sword.\n"); } @end @implementation Test (Fate) - (void)WriteB { printf("体は剣で出来ている\n"); } @end
面白い!!これは良いかも!
-
- メソッドが衝突すると継承によるオーバーライドと違い、完全に隠蔽されてしまうので注意。
- プロトコル
@interface クラス名 : スーパークラス名 <プロトコル1, ...>
実践では、クラスの実装に依存しない完全に抽象化された型としてプロトコルが利用されるほかに、ポインタを使わずにメソッドをコールバックさせる方法としても利用されます。
なるほど、面白い。こうやってコールバックになるのか!
とりあえず
とりあえずここは一通り呼んだ。
なんか内容が古い気もするのでObjective-C 2.0の本でも読みたいなぁ。
あと、何かコードを書いてみよ。
こことか面白そう。
Objective-Cを勉強してみる
Xcodeを使ってみようと思って、Xcodeを起動してiPhoneSDKのサンプルを覗いてみた。
.mな拡張子のファイルがあって、Matlab!!?とか思いながら調べてみると、
どやらObjective-Cのファイルの拡張子は.mらしい。
wikipediaを眺めていると
メソッド呼び出しはメッセージ送信で行うらしい!
すげー!オブジェクト指向!!
ということで、勢いで勉強を始める。
本当はC言語
Objective-CはC言語の拡張。
どうやらコンパイラがObjective-CのコードをCのコードに変換するらしい。
追加された型や予約語も#defineやtypedefされているだけ。
マジか。それはビックリだ。
とりあえず、ここで一通り修行する。
メモ
@interface クラス名 : 親クラス名 { インスタンス変数宣言 } メソッド宣言 @end
なんだこれ?キモイ!><
- インスタンス変数はC++でいうところのprotected扱い!?
- ルートクラスを継承するのが基本。GCCはObject、CocoaではNSObjectというクラス
- ルートクラスを作ることもできるけどね。
- メソッド宣言がキモイ。
- (戻り値の型) メソッド名 : 引数のリスト ;
- -で始まるのがインスタンスメソッド、+から始まるのがクラスメソッド
- デフォルトの戻り値はid型(オブジェクトを表す汎用型)
- 宣言と実装は完全分離
@implementation クラス名 メソッド定義 @end
- Objective-Cにはnewとかない。インスタンス作成もクラスが行う。
- 通常はルートクラスのallocというクラスメソッドでインスタンスを生成する。
- allocの戻り値はid型。
- allocがクラスの宣言情報からメモリを割り当てるらしい。すごい。alloc神。
- メソッドの呼び出しはメッセージ式で行う。キモイ。
- 動的らしい。よくわからんが。要勉強。
- 動的ゆえ、実行時にメソッドを検索するためCに比べてオーバーヘッドが倍以上らしい。
id obj = [Test alloc]; // Testというクラスのインスタンスobjを生成 [obj method]; // objのメソッドmethodを実行 // objを使い捨てにするなら次のようにも書ける [[Test alloc] method];
にゃるほどね。
風邪悪化
寝る
vectorの最大値と最小値
max_elementとmin_elementというものがあった。
vector<double> data; // data は適当にいれておく。 double max,min; max = *max_element( data.begin(), data.end() ); min = *min_element( data.begin(), data.end() );
次と同じ
vector<double> data; double max,min; sort( data.begin(), data.end() ); max = data.back(); min = data.front();
アルゴリズムっていろいろあるんだね。
移行アシスタントによるデータ復元
めでたくBootCampでWindowsを入れることができたので、
いよいよ昔のデータをMacBookに復元する。
クリーンインストールした意味が薄れるけれども。
iTimeMachineのインストール
TimeMachineでバックアップした時と同様、iTimeMachineをインストール。
TimeMachineで以前バックアップしたバックアップディスクを選択。
移行アシスタントによる復元
- アプリケーション/ユーティリティ/移行アシスタント.appを起動。
- "TimeMachineバックアップまたは他のディスクから"を選択
- TimeMachineのバックアップディスクを選択
- 復元項目を選択
- 復元!!
「残り1分以内」となってから待つこと約3時間半。何故!?
見事復元に成功!!
またMacBook(Kro)が可愛くなりました!