Category Archive: iPhone

[iPhone]InterFaceBuilderに設定してあるオブジェクトの初期化にはinitWithCoderもしくは、awakeFromNib

(IBを使って)nibファイルにオブジェクトを引き充てた場合、nibからオブジェクトインスタンスが読み込まれる時、initもinitWithFrameも呼び出されない。
初期化処理的なコードを記載したいときは、initWithCoderを使う。
とのこと。

もうひとつnibから読み込まれたときに実行されるメソッドでawakeFromNibというメソッドがある。
nibファイルを読み込んでメモリ上にインスタンスが復元された後に呼びだされる、とのこと。
(initWithCoderはそうじゃないないのか??)
こちらはIBのGUIで設定したパラメータを取得したときに使う。
らしい。

イマイチ使い分けがわからんのだけど、定義は

-(void) awakeFromNib;
-(id)initWithCoder:(NSCoder*)coder;

なので、initWithCoderは引数があって、戻り値を返すような仕様。
(selfを戻すらしい)
根本的にどういうものなのかはまだよくわからん。。

ちなみに実行される順番としては、
initWithCoder→awakeFromNib
って感じでこれは予想通り。

[iPhone]Objective- Cの勉強メモ:xibファイルとはどういうものなのか

・xibファイルとは、
XML Interface Builderの略。
その名の通り、xml形式のファイル。
これをxcodeから開くとInterfaceBuilder(アプリケーション:以下IB)が立ち上がってビジュアル的にxmlの中身を編集できる。
(ということだと思う)

・Flashでいったらxibファイルって何にあたるの?
とTwitterでつぶやいたら、
エライ人から「FLEXでいうところのMXMLみたいなもの」と教えてもらった。
なるほど、FLEXでもMXMLも表示オブジェクトの配置情報を持っているし、MXMLを使わなくてもASで表示オブジェクトの配置することもできる。
(でもMXMLも使い方をよくわかってない)

ちょっと調べてみようと思ったらかなり分かりやすい素敵記事発見。

iPhone:Xib/Nib ファイル(その1):「支出管理」サポート
iPhone:Xib/Nib ファイル(その2) :「支出管理」サポート

xibファイルは、UIApplicationかUIViewControllerのサブクラスによってロードされるものなのね。
どのクラスにも設定できちゃうから、この辺りの仕組みがよくわからなかった。
ありがたやありがたや。

[iPhone] Objective- Cの勉強メモ:Xcodeショートカット:ヘッダーファイルとソースファイルの切り替え

.h/.mファイルの切り替え
cmd + option + 上キー(交互に切り替わる)

[iPhone] Objective- Cの勉強メモ:NSNotificationCenterでイベント通知の管理

Objective-CはASと違ってデリゲートとという機能がある。
デリゲートとは別に色んなクラスが通知するイベントを一括で管理してくれるクラスがあるみたい。
それが、NSNotificationCenterクラス。

手順としては、
1.NSNotificationCenterのインスタンスを生成
2.通知の登録(インスタンスに通知先、リスナー関数、通知の種類、通知の送信元)
3.通知の開始
4.(通知の終了)
5:(通知の登録解除)

例)

//playerはMPMusicPlayerControllerのインスタンス

//通知センタのインスタンを取得	
NSNotificationCenter* noteCenter = [NSNotificationCenter defaultCenter];
//addObserver:通知先
//selector:リスナー関数
//name:通知してほしい通知の種類?
//object:通知の送信元	
[noteCenter 
addObserver:self 
selector:@selector(hoge:)
name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification 
object:player];
//通知開始を指示
[player beginGeneratingPlaybackNotifications];

nameはnilにすると全ての種類のイベントが取得対象になる。
(そもそも通知の送信元がどのようなイベントを発信してるかを把握してる必要あり?)
(ドキュメントみれば書いてあるのかな?)
objectはnilにすると、全ての送信元からイベントを受け取る。

あとNSNotificationCenterはシングルトンになるので、インスタンス変数の保持はしなくてもいいみたい。

[iPhone] Objective- Cの勉強メモ:カテゴリという概念を使って元クラスの拡張(メソッドの追加)できる

Objective-CにはASにはない機能でカテゴリという概念がある。
これはクラスファイルにメソッドを追加することができる機能。

通常クラスを拡張するにはそのクラスを継承したサブクラスを定義すればいいと思う。
でも根本的に弄りたくなった場合、元のクラスを書き換えちゃうということもできる。
(ASだと、Flash8でAS2のときは直接編集できたけど、AS3ではSWCになってるから無理ぽ)
でも書き換えちゃうと何か不具合がおきたときとかバックアップとってないと元に戻すのが大変。

というわけでカテゴリという概念は、元クラスを簡易的に拡張できるという概念。
ただし追加できるのはメソッドだけ。
変数は追加できない。
手順は拡張用のクラス(?)ファイルを作ってそこで定義する。

例)UIViewを拡張する、UIViewExファイルを生成する場合
//ヘッダーファイル

#import <UIKit/UIKit.h>
//ここでの()の中の名前は任意(ファイル名と同じでなくてよい)
@interface UIView (AnimationExtension) 
//メソッドの定義
//ここに追加したいメソッドを書く
-(void) hoge;
@end

//実行ファイル

#import "UIViewExtention.h"
@implementation UIView(AnimationExtension)
//メソッドの実装
    //ここで定義したメソッドを実装する
 -(void) hoge{
    //処理
}
@end

書き方で注意するのは、ヘッダーファイルでのinterfaceのくだり。
変数は定義できないので、{}は書く必要なし。

これを反映されるには、反映させたいクラスファイルにて

#import "UIViewExtention.h"

を記述すればよい。
これが記述されたクラス内では、UIViewインスタンスにUIViewExで追加したメソッドが普通に使えるようになる。

//例

-(void) init{
//imageViewはUIImageVIewクラスのインスタンス
//(UIImageViewのスーパークラスはUIImageなのでhogeメソッドが使える)
[imageView hoge];
}

[iPhone]Objective- Cの勉強メモ:乱数の取り扱い

まずはObjective-CというかC言語での乱数の発生させる方法。
使える関数は2種類
まず
int rand(void);
という関数でint型の乱数を返すことができる。
このときに返る値は、0~馬鹿でかい数という感じ。
馬鹿でかい数はコンパイラによって変わるらしい。
(ASのMath.random()のように、0~1未満というわけでない)

int i;
i = rand();
printf(%d,i);//0から馬鹿でかい数の間の間

ただ、このままだと乱数は実行するたびに常に同じ値を返すことになるので、初期化処理という行為が必要になる。
そこで使うのがsrand();
void srand(unsigned int 初期値);

使い方としては、rand()関数を実行する前にsrand()関数を実行することで初期化すればよし。
初期値には、絶対にかぶらない値を日付データから取ればよし。

//time(NULL)で現在の時刻が1970年1月1日午前0時0分0秒からの通算秒数で得られる。
srand(time(NULL));
rand();

以上が、C言語での設定方法

Objective-Cではsrandは以下のようにするらしい。

//NSDateインスタンスを作って、本日の日付けを秒数に換算してる
srand([[NSDate date] timeIntervalSinceReferenceDate]);
rand()

※C言語のやり方でも問題なさげ。

[iPhone]Objective- Cの勉強メモ:プロパティ宣言:@propertyの意味

ヘッダーファイルにて、プロパティ宣言をすることでそのプロパティについてのゲッターセッターが実装される。
プロパティ宣言をしなくても、自分で実装処理を書いてもよい

プロパティの書式は、

//ヘッダーファイルに書く
//@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を指定すると、排他制御はしなくなる。

[iPhone]Objective-Cの勉強メモ:dealloc

クラスファイルの最後の方にやたら登場するdeallocメソッド
NSObjectのメソッドで、それをオーバーライドしている。
dealloc実行のタイミングは保持カウントが0になったときに実行される。

保持カウントはインスタンスの生成、retainさせた参照の追加でカウントアップ。
releaseでカウントダウンされるのでカウント数には注意が必要。

例)

- (void)dealloc {
    [window release];
//スーパークラス(NSObject)のdeallocを実行することで実際のメモリの破棄
//C言語のfree関数のようなもの
    [super dealloc];
}

[iPhone]Objective-Cの勉強メモ(ActionScriptとの比較的な):プロトコル

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> {}

[iP]Objective-Cの文法メモ(ActionScript3.0との比較的な):インスタンスの作り方

クラスのインスタンスの生成方法
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];