15

Click here to load reader

iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

Embed Size (px)

DESCRIPTION

iOS.Dev.Urawa#2 2010/10/25 ヘッダ参照の『鶏と卵』問題 新居雅行

Citation preview

Page 1: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

ヘッダ参照の『鶏と卵』問題

Masayuki Nii2010/10/25

iOS Developer勉強会.Urawa #2

1

Page 2: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

Agenda

コンパイルにはヘッダのインクルードが必要

他のクラスを使う場合は通常はヘッダのインクルードが必要になる

プレフィックスヘッダを使えばよりシンプルに書ける

[おまけ]メンバ変数やメソッドの隠匿化

[おまけ]バージョンによる分岐

2

Page 3: iOS.Dev.Urawa#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

Page 4: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

他のクラスを参照する場合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

Page 5: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

他のヘッダやクラスの定義を追加する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

Page 6: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

ヘッダファイルの存在

結果的にすべての.mファイルで他のヘッダを読み込むことになる• 通常は「全部」は不要だが、後から追加するときに必ずヘッダを指定することになる• ヘッダには@classでクラス名を追加する1クラスを1ヘッダで作る限りはその必要がある

6

Page 7: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

プレフィックスヘッダの利用

コンパイル時に必ず読み込むヘッダ• 通常はフレームワークのヘッダのみが指定されている• すべてのソースのコンパイル時に読み込まれる• 拡張子は.pchXcodeではプリコンパイルや共有が可能• 開発中に変更がほとんどないようなヘッダ群をコンパイルした状態にしておく

7

Page 8: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

プリコンパイルヘッダに定義を集める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

Page 9: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

プリコンパイルヘッダ

あらかじめコンパイルしたヘッダ• たくさんのヘッダがあった時代の産物• ほんとうに何分、何十分とかかる時代があったiOS時代、ヘッダは減った• プリコンパイルがすぐ(1秒くらい?)で終わる• ヘッダを全部入れておけば、.h/.mファイルでの参照は不要注意点• 継承したクラスがある場合、プリコンパイルヘッダでの順序に依存する• Google DOMクラスのようにプリコンパイルヘッダに入れておくとエラーになるような場合もある。これについては通常通りの使用方法にする

9

Page 10: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

余談:importとinclude

include• ファイルを読み込むプリプロセッサ• C言語で定義• 2重の読み込みがなされる可能性があり、#ifndef等で排除• ヘッダパスをコンパイル時に指定するのが一般的なので、ソース上では相対的なパスを記述する

import• Objective-Cで追加されたプリプロセッサ• 同じファイルを2度読みしないようになっている

10

Page 11: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

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

Page 12: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

プライベートなメソッドの定義

@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

Page 13: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

メリット

クラス内で使うメソッドの定義が楽• .mファイルの修正だけでOKスコープをコントロール• .hファイルには外部から利用したいメソッドだけの定義でかまわないので、メソッドが入り乱れない

13

Page 14: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

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

Page 15: iOS.Dev.Urawa#2-ヘッダ参照の『鶏と卵』問題

まとめ

プレフィックスヘッダを積極的に使おう

プライベートメソッドを意識しよう

15