iphone, ipad アプリ開発勉強会#2
DESCRIPTION
iPhone, iPad アプリ開発勉強会#2 の為に作成した資料です。TRANSCRIPT
iPhone, iPadアプリ開発勉強会#2
12年12月7日金曜日
一般的なアプリの構成
実行
@interface MyViewController {@private NSString *str}
@prototyp(non...
@end
@imprementation MyViewController {@synthesize *mView
- (id) init { self = [super init]; return self:}
@end
ヘッダファイル(MyViewController.h)
実装ファイル(MyViewController.m)
ビュー(MyViewController.xib)
画面ひとつ分の構成
通常は画面1つにつき、
•ビュー•ヘッダファイル•実装ファイル
で構成されます
12年12月7日金曜日
一般的なアプリの構成ビューが1つのとき
実行
@interface MyViewController {@private NSString *str}
@prototyp(non...
@end
@imprementation MyViewController {@synthesize *mView
- (id) init { self = [super init]; return self:}
@end
ヘッダファイル(MyViewController.h)
実装ファイル(MyViewController.m)
ビュー(MyViewController.xib)
@interface MyViewController {@private NSString *str}
@prototyp(non...
@end
@imprementation MyViewController {@synthesize *mView
- (id) init { self = [super init]; return self:}
@end
ヘッダファイル(MyAppViewDelegate.h)
実装ファイル(MyAppDelegate.m)
アプリケーションデリゲート
それ以外では、アプリひとつにつき、アプリケーションデリゲートが1つあります。
12年12月7日金曜日
一般的なアプリの構成ビューが2つのとき
実
@interface MyView
@imprementation MyView
ヘッダファイル 実装ファイル
ビュー
@interface MyViewController {@private NSString *str}
@prototyp(non...
@end
@imprementation MyViewController {@synthesize *mView
- (id) init { self = [super init]; return self:}
@end
ヘッダファイル(MyAppViewDelegate.h)
実装ファイル(MyAppDelegate.m)
アプリケーションデリゲート
実
@interface MyView
@imprementation MyView
ヘッダファイル 実装ファイル
ビュー
アプリケーションデリゲートはアプリ全体で共有します
12年12月7日金曜日
一般的なアプリの構成
実
@interface MyView
@imprementation MyView
ヘッダファイル 実装ファイル
ビュー
@interface MyViewController {@private NSString *str}
@prototyp(non...
@end
@imprementation MyViewController {@synthesize *mView
- (id) init { self = [super init]; return self:}
@end
ヘッダファイル(MyAppViewDelegate.h)
実装ファイル(MyAppDelegate.m)
アプリケーションデリゲート
実
@interface MyView
@imprementation MyView
ヘッダファイル 実装ファイル
ビュー
ヘッダファイル 実装ファイル
@interface MyView
@imprementation MyView
なんらかの機能を提供するクラス
12年12月7日金曜日
一般的なアプリ開発の流れ
1. XCodeでプロジェクト作成
2. ビューに部品(ボタン、テキストフィールド等...)を追加
3. ビューコントローラのヘッダファイルに@property(IBoutlet)宣言を追加
4. 実装ファイルに@synthesize宣言を追加
5. ビューのデザイン画面で、さきほど宣言したビューコントローラのプロパティと実際の部品を繋ぐ。
6. コード中でビューの部品にアクセスする際には@property宣言した変数を通して。
7. ボタンなどを配置してタップした時のアクションを定義する(次ページ)
12年12月7日金曜日
一般的なアプリ開発の流れ(アクションの定義)
1. デザイン画面にアクションを起こすボタンなどを配置する。
2. ビューコントローラのヘッダファイルにアクションのメソッド定義をする。
3. ビューコントローラの実装ファイルにアクションを実装する。
4. デザイン画面で、アクションと実際の部品を繋ぐ。
5. ボタンなどを配置して、そのボタンをタップした時のアクションのコードを書く。
6. コンパイル、動作を確認。
12年12月7日金曜日
メモリ管理
Rubyと同様に、Objective-Cにおいてもクラスからインスタンスを作って使用します。
obj = Hoge.new
obj.sayhello #メソッド呼び出し
Hoge *obj = [[Hoge alloc] init];
[obj sayhello] /* メソッド呼び出し */
[obj release]; /* メモリを解放 */
/* または */
[obj autorelease]; /* これもメモリ解放 */
Rubyの場合 Objective-Cの場合
12年12月7日金曜日
もしメモリを解放しないと...
90%
10%アプリが使用中空きメモリ
70%
30%
40%60%
40%60%
5%
95%
iPhoneの持ってるメモリを使い果たしてしまう!実際にはそうなる前にiOS
によりアプリが強制終了されます。
だんだんメモリ使用量が増えていって...
12年12月7日金曜日
メモリ解放するには、プログラム中で生成したオブジェクトを解放します。
オブジェクトは、誰にも使用されなくなったら解放します。
Hogeクラスのオブジェクト[[Hoge alloc] init]
オブジェクトA
オブジェクトB
オブジェクトC
オブジェクトが使われている(参照されている)状態
12年12月7日金曜日
メモリ解放するには、プログラム中で生成したオブジェクトを解放します。
オブジェクトは、誰にも使用されなくなったら解放します。
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
オブジェクトが使われていない(参照されていない)状態こうなったら解放しちゃってもいい
12年12月7日金曜日
でも、他のオブジェクトから使われているかどうかなんて、どうやったらわかるのでしょう...
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
オブジェクトが使われている(参照されている)状態
3
Objective-Cでのメモリ管理にはリファレンスカウンタを使用します
リファレンスカウンタ
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
オブジェクトが使われている(参照されている)状態
2
Objective-Cでのメモリ管理にはリファレンスカウンタを使用します
リファレンスカウンタ
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
オブジェクトが使われている(参照されている)状態
1
Objective-Cでのメモリ管理にはリファレンスカウンタを使用します
リファレンスカウンタ
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
誰からも使われなくなったオブジェクトはリファレンスカウンタが0に!
0
Objective-Cでのメモリ管理にはリファレンスカウンタを使用します
リファレンスカウンタ
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
オブジェクトは解放されてなくなりました!リファレンスカウンタが0になったときの
オブジェクトの解放はiOSにより自動的に行われます。
0
Objective-Cでのメモリ管理にはリファレンスカウンタを使用します
リファレンスカウンタ
12年12月7日金曜日
実際のコードでみてみると...
Hoge *obj = [[Hoge alloc] init];
[obj sayhello] /* メソッド呼び出し */
[obj release]; /* メモリを解放 */
/* または */
[obj autorelease]; /* これもメモリ解放 */
Hogeクラスのオブジェクト
1
リファレンスカウンタオブジェクトが生成された時点で、生成もとのオブジェクトの参照分、1がリファレンスカウンタにセットされます。
12年12月7日金曜日
実際のコードでみてみると...
Hoge *obj = [[Hoge alloc] init];
[obj sayhello] /* メソッド呼び出し */
[obj release]; /* メモリを解放 */
/* または */
[obj autorelease]; /* これもメモリ解放 */
Hogeクラスのオブジェクト
0
リファレンスカウンタオブジェクトが生成された時点で、生成もとのオブジェクトの参照分、1がリファレンスカウンタにセットされます。
オブジェクトに対してreleaseメソッドを呼ぶ事でリファレンスカウンタの値が1引かれます。
12年12月7日金曜日
実際のコードでみてみると...
Hoge *obj = [[Hoge alloc] init];
[obj sayhello] /* メソッド呼び出し */
[obj release]; /* メモリを解放 */
/* または */
[obj autorelease]; /* これもメモリ解放 */
Hogeクラスのオブジェクト
0
リファレンスカウンタ
オブジェクトに対してreleaseメソッドを呼ぶ事でリファレンスカウンタの値が1引かれます。
12年12月7日金曜日
複数のオブジェクトから参照されてると...
Hoge *obj = [[Hoge alloc] init]; /* この時点でリファレンスカウンタは1 */
a.obj = obj; /* この時点でリファレンスカウンタは2 */
b.obj = obj; /* この時点でリファレンスカウンタは3 */
c.obj = obj; /* この時点でリファレンスカウンタは4 */
[obj release]; /* ここで-1されて3 */
....
/* aが解放される時にaがobjに対してreleaseを実行してカウンタは2に */
/* bが解放される時にbがobjに対してreleaseを実行してカウンタは1に */
/* cが解放される時にcがobjに対してreleaseを実行してカウンタは0に */
/* ここでオブジェクトは解放される */
12年12月7日金曜日
自動解放プールを使う方法
Hoge *obj = [[Hoge alloc] init];
[obj sayhello] /* メソッド呼び出し */
// [obj release]; /* メモリを解放 */
/* または */
[obj autorelease]; /* これもメモリ解放 */
Hogeクラスのオブジェクト
0
12年12月7日金曜日
自動解放プールを使う方法
Hoge *obj = [[Hoge alloc] init];
[obj sayhello] /* メソッド呼び出し */
// [obj release]; /* メモリを解放 */
/* または */
[obj autorelease]; /* これもメモリ解放 */
Hogeクラスのオブジェクト
0
12年12月7日金曜日
releaseとautorelease(自動解放プール)の違いは...?
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
3
releaseを使うと、カウンタはすぐに-1され、0になった時点でオブジェクト(の使用するメモリは)即時解放されます。
リファレンスカウンタ
release
release
release
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
オブジェクトは解放されてなくなりました!リファレンスカウンタが0になったときの
オブジェクトの解放はiOSにより自動的に行われます。
0
リファレンスカウンタ
releaseを使うと、カウンタはすぐに-1され、0になった時点でオブジェクト(の使用するメモリは)即時解放されます。
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
3
autoreleaseを使うと、カウンタはすぐには-1されず、従ってオブジェクト(が使用するメモリ)はすぐには解放されません。
リファレンスカウンタ
autorelease
autorelease
autorelease
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
3
そのかわり、メモ用紙(自動解放プール)にその旨を記録しておきます。
autorelease
autorelease
autoreleaseオブジェクトAが解放した。オブジェクトBが解放した。オブジェクトCが解放した。
自動解放プール
メモ用紙(自動解放プール)に記録しておく
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
3
autoreleaseを使うと、カウンタはすぐには-1されず、従ってオブジェクト(が使用するメモリ)はすぐには解放されません。
オブジェクトAが解放した。オブジェクトBが解放した。オブジェクトCが解放した。
自動解放プール
自動解放プールが解放される時にメモされている「解放」が一斉に行われます。
0
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
0
autoreleaseを使うと、カウンタはすぐには-1されず、従ってオブジェクト(が使用するメモリ)はすぐには解放されません。
オブジェクトAが解放した。オブジェクトBが解放した。オブジェクトCが解放した。
自動解放プール
自動解放プールが解放される時にメモされている「解放」が一斉に行われます。
12年12月7日金曜日
Hogeクラスのオブジェクト
オブジェクトA
オブジェクトB
オブジェクトC
0
autoreleaseを使うと、カウンタはすぐには-1されず、従ってオブジェクト(が使用するメモリ)はすぐには解放されません。
オブジェクトAが解放した。オブジェクトAが解放した。オブジェクトAが解放した。
自動解放プール
自動解放プールも開放されます...
12年12月7日金曜日
どう使い分ければ...
12年12月7日金曜日
どう使い分ければ...
メソッドの中でだけ使う、一時的なオブジェクトはメソッドから抜ける前にreleaseで解放します。
- (void) hoge { NSArray * array = [[NSArray alloc] init];
/* 何か処理*/
[array release];}
12年12月7日金曜日
どう使い分ければ...
メソッドの返り値として呼び出し元に返す値は、相手が受け取る前に解放してしまってはまずいので、autoreleaseを使います。
- (NSArray *) hoge { NSArray * array = [[NSArray alloc] init]; [array autorelease];
/* 何か処理*/
return array;}
12年12月7日金曜日
どう使い分ければ...
なお、次に説明するコンビニエンスコンストラクタを使えばなにもしなくてもautoreleaseを呼び出し済みのオブジェクトが得られます。
- (NSArray *) hoge { NSArray * array = [NSArray array];
/* 何か処理*/
return array;}
12年12月7日金曜日
ちなみに、最も基本的なオブジェクト生成は
[[クラス名 alloc] init];
で、この場合はreleaseまたはautoreleaseを明示的に呼んで解放してやる必要があります。
ただし、これとは別に
[クラス名 小文字ではじまるクラス名~];
というオブジェクト生成方法もあり、この場合は既にautoreleaseが呼ばれた状態でオブジェクトが渡されます。
つまり...
NSArray *array = [NSArray array];
は
NSArray * array = [[NSArray alloc] init][array autorelease];
と同じです。
12年12月7日金曜日
ARC (オート・レファレンス・カウンタ)とは
12年12月7日金曜日
iOS5から、ARCが使えるようになりました
12年12月7日金曜日
ARCを使ってもオブジェクトの解放に関する考え方は変わりませんが...
12年12月7日金曜日
- (void) hoge { NSArray * array = [[NSArray alloc] init];
/* 何か処理*/
[array release];}
ARC無しの場合
使い終わったらreleaseしてやらないとメモリリーク!
12年12月7日金曜日
- (void) hoge { NSArray * array = [[NSArray alloc] init];
/* 何か処理*/
}
ARCが有効の場合
と書いておけば...
- (void) hoge { NSArray * array = [[NSArray alloc] init];
/* 何か処理*/
[array release];}
コンパイル時にコンパイラが勝手に追加してくれます!
メモリにも開発者にも優しい(*´∀`*)
コンパイル
12年12月7日金曜日
今後はARCを有効にしておいて、[[クラス alloc] init] でオブジェクトを生成しても解放忘れがなく、
かつARCによって自動挿入されたreleaseにより、すぐにオブジェクトを解放してくれるのでこっちがいいかも。
12年12月7日金曜日
RubyやJavaのGCとの違いは?
GC(ガベージコレクション)はアプリ実行時に一定期間おきにメモリの掃除をします。
ARCは、コンパイル時にメモリの解放コードを自動挿入し、実行時には自動的に何かをする事はありません。
↓
GCが走らない分、処理が止まったりせず、より滑らかでスムーズな使用感が得られます!
12年12月7日金曜日
おわり
12年12月7日金曜日