Click here to load reader
Upload
masayuki-nii
View
306
Download
0
Embed Size (px)
DESCRIPTION
iOS.Dev.Urawa#2 2010/10/25 ヘッダ参照の『鶏と卵』問題 新居雅行
Citation preview
ヘッダ参照の『鶏と卵』問題
Masayuki Nii2010/10/25
iOS Developer勉強会.Urawa #2
1
Agenda
コンパイルにはヘッダのインクルードが必要
他のクラスを使う場合は通常はヘッダのインクルードが必要になる
プレフィックスヘッダを使えばよりシンプルに書ける
[おまけ]メンバ変数やメソッドの隠匿化
[おまけ]バージョンによる分岐
2
ヘッダとソース
MyAppDelegate.h
MyAppListViewController.h
MyAppDetailViewController.h
@interface MyAppDelegate : NSObject {}@end
@interface MyAppListViewController : NSViewController {
}@end
@interface MyAppDetailViewController: NSViewController {
}@end
MyAppDelegate.m
MyAppListViewController.m
MyAppDetailViewController.m
#import “MyAppDelegate”@implementation MyAppDelegate@end
#import “MyAppListViewController”@implementation MyAppListViewController@end
#import “MyAppDetailViewController”@implementation MyAppDetailViewController@end
3
他のクラスを参照する場合MyAppDelegate.h
MyAppListViewController.h
MyAppDetailViewController.h
@interface MyAppDelegate : NSObject {UIWindow *window;MyAppListViewController *listView;MyAppDetailViewController *detailView;
}@end
@interface MyAppListViewController : NSViewController {
}@end
@interface MyAppDetailViewController: NSViewController {
}@end
MyAppDelegate.m
MyAppListViewController.m
MyAppDetailViewController.m
#import “MyAppDelegate”@implementation MyAppDelegate@end
#import “MyAppListViewController”@implementation MyAppListViewController@end
#import “MyAppDetailViewController”@implementation MyAppDetailViewController@end
エラーになるはず!
4
他のヘッダやクラスの定義を追加するMyAppDelegate.h
MyAppListViewController.h
MyAppDetailViewController.h
@class MyAppListViewController;@class MyAppDetailViewController;@interface MyAppDelegate : NSObject {
UIWindow *window;MyAppListViewController *listView;MyAppDetailViewController *detailView;
}@end
@interface MyAppListViewController : NSViewController {
}@end
@interface MyAppDetailViewController: NSViewController {
}@end
MyAppDelegate.m
MyAppListViewController.m
MyAppDetailViewController.m
#import “MyAppDelegate”#import “MyAppListViewController”#import “MyAppDetailViewController”@implementation MyAppDelegate@end
#import “MyAppListViewController”#import “MyAppDelegate”#import “MyAppDetailViewController”@implementation MyAppListViewControllerUIApplication ap = [UIApplication sharedApplication];MyAppDelegate *aDel = ap.delegate;MyAppDetailViewController *dvc = aDel.detailView;@end
#import “MyAppDetailViewController”@implementation MyAppDetailViewController@end
5
ヘッダファイルの存在
結果的にすべての.mファイルで他のヘッダを読み込むことになる• 通常は「全部」は不要だが、後から追加するときに必ずヘッダを指定することになる• ヘッダには@classでクラス名を追加する1クラスを1ヘッダで作る限りはその必要がある
6
プレフィックスヘッダの利用
コンパイル時に必ず読み込むヘッダ• 通常はフレームワークのヘッダのみが指定されている• すべてのソースのコンパイル時に読み込まれる• 拡張子は.pchXcodeではプリコンパイルや共有が可能• 開発中に変更がほとんどないようなヘッダ群をコンパイルした状態にしておく
7
プリコンパイルヘッダに定義を集めるMyAppDelegate.h
MyAppListViewController.h
MyAppDetailViewController.h
@interface MyAppDelegate : NSObject {UIWindow *window;MyAppListViewController *listView;MyAppDetailViewController *detailView;
}@end
@interface MyAppListViewController : NSViewController {
}@end
@interface MyAppDetailViewController: NSViewController {
}@end
MyAppDelegate.m
MyAppListViewController.m
MyAppDetailViewController.m
@implementation MyAppDelegate@end
@implementation MyAppListViewControllerUIApplication ap = [UIApplication sharedApplication];MyAppDelegate *aDel = ap.delegate;MyAppDetailViewController *dvc = aDel.detailView;@end
@implementation MyAppDetailViewController@end
@class MyAppDelegate;@class MyAppListViewController;@class MyAppDetailViewController;
#import <UIKit/UIKit.h>#import “MyAppDelegate”#import “MyAppListViewController”#import “MyAppDetailViewController”
MyApp.pch
8
プリコンパイルヘッダ
あらかじめコンパイルしたヘッダ• たくさんのヘッダがあった時代の産物• ほんとうに何分、何十分とかかる時代があったiOS時代、ヘッダは減った• プリコンパイルがすぐ(1秒くらい?)で終わる• ヘッダを全部入れておけば、.h/.mファイルでの参照は不要注意点• 継承したクラスがある場合、プリコンパイルヘッダでの順序に依存する• Google DOMクラスのようにプリコンパイルヘッダに入れておくとエラーになるような場合もある。これについては通常通りの使用方法にする
9
余談:importとinclude
include• ファイルを読み込むプリプロセッサ• C言語で定義• 2重の読み込みがなされる可能性があり、#ifndef等で排除• ヘッダパスをコンパイル時に指定するのが一般的なので、ソース上では相対的なパスを記述する
import• Objective-Cで追加されたプリプロセッサ• 同じファイルを2度読みしないようになっている
10
Objective-Cのスコープ
メンバ変数• @public、@privateでスコープを定義できる• プロパティを使う方がスマートかつ安全• つまり、全部@privateにし、外部からアクセス可能なメンバ変数にしたい場合は、プロパティを使うのがいい
メソッド• Objective-Cにはスコープの概念がない• しかしやりようはある• 萩原先生の書籍 Objective-C 2.0(p229)• 最近の生成ソースやサンプル• Technique to make some methods to "private"http://stackoverflow.com/questions/172598/best-way-to-define-private-methods-for-a-class-in-objective-c
11
プライベートなメソッドの定義
@interface MyAppDetailViewController : NSViewController {@private
UIScrollView *myScroll;UIView *myContents;
}@property (retain, nonatmic) IBOutlet UIScrollView *myScroll;@property (retain, nonatmic) IBOutlet UIView *myContents;-(void) setupContents: (NSString *)param;@end
@interface MyAppDetailViewController()-(NSArray *)analyzeParameter:(NSString *)p;@end
@implementation MyAppDetailViewController-(void) setupContents: (NSString *)param{ }-(NSArray *)analyzeParameter:(NSString *)p{ }@end
MyAppDetailViewController.h
MyAppDetailViewController.m
←プライベートメソッド←カテゴリの定義
12
メリット
クラス内で使うメソッドの定義が楽• .mファイルの修正だけでOKスコープをコントロール• .hファイルには外部から利用したいメソッドだけの定義でかまわないので、メソッドが入り乱れない
13
one more Omake...
SDKのバージョンによるコンパイルの分岐• Ver.3とVer.4で異なる場合の処理が面倒になってきた• ex. NSConnectionDelegate、Blocksなど• Availability.h等に関連キーワードが定義されている
#if __IPHONE_OS_VERSION_MIN_REQUIRED > 30200....
#else....
#endif
↑SDK Ver.3.2を意味する
14
まとめ
プレフィックスヘッダを積極的に使おう
プライベートメソッドを意識しよう
15