SlideShare ist ein Scribd-Unternehmen logo
1 von 15
Downloaden Sie, um offline zu lesen
ヘッダ参照の『鶏と卵』問題
Masayuki Nii
2010/10/25
iOS Developer勉強会.Urawa #2

1
Agenda

コンパイルにはヘッダのインクルードが必要
他のクラスを使う場合は通常はヘッダのインクルードが
必要になる
プレフィックスヘッダを使えばよりシンプルに書ける
[おまけ]メンバ変数やメソッドの隠匿化
[おまけ]バージョンによる分岐

2
ヘッダとソース
MyAppDelegate.h
@interface MyAppDelegate : NSObject {
}
@end

MyAppDelegate.m
#import “MyAppDelegate”
@implementation MyAppDelegate
@end

MyAppListViewController.h
@interface MyAppListViewController
: NSViewController {
}
@end

MyAppListViewController.m
#import “MyAppListViewController”
@implementation MyAppListViewController
@end

MyAppDetailViewController.h
@interface MyAppDetailViewController
: NSViewController {
}
@end

MyAppDetailViewController.m
#import “MyAppDetailViewController”
@implementation MyAppDetailViewController
@end

3
他のクラスを参照する場合
MyAppDelegate.h
@interface MyAppDelegate : NSObject {
UIWindow *window;
MyAppListViewController *listView;
MyAppDetailViewController
*detailView;
}
@end

MyAppDelegate.m

MyAppListViewController.h

MyAppListViewController.m

@interface MyAppListViewController
: NSViewController {
}
@end

#import “MyAppListViewController”
@implementation MyAppListViewController
@end

MyAppDetailViewController.h
@interface MyAppDetailViewController
: NSViewController {
}
@end

MyAppDetailViewController.m
#import “MyAppDetailViewController”
@implementation MyAppDetailViewController
@end

#import “MyAppDelegate”
@implementation MyAppDelegate
@end

エラーになるはず!

4
他のヘッダやクラスの定義を追加する
MyAppDelegate.h
@class MyAppListViewController;
@class MyAppDetailViewController;
@interface MyAppDelegate : NSObject {
UIWindow *window;
MyAppListViewController *listView;
MyAppDetailViewController
*detailView;
}
@end
MyAppListViewController.h
@interface MyAppListViewController
: NSViewController {
}
@end
MyAppDetailViewController.h
@interface MyAppDetailViewController
: NSViewController {
}
@end

MyAppDelegate.m
#import “MyAppDelegate”
#import “MyAppListViewController”
#import “MyAppDetailViewController”
@implementation MyAppDelegate
@end
MyAppListViewController.m
#import “MyAppListViewController”
#import “MyAppDelegate”
#import “MyAppDetailViewController”
@implementation MyAppListViewController
UIApplication ap = [UIApplication sharedApplication];
MyAppDelegate *aDel = ap.delegate;
MyAppDetailViewController *dvc = aDel.detailView;
@end
MyAppDetailViewController.m
#import “MyAppDetailViewController”
@implementation MyAppDetailViewController
@end
5
ヘッダファイルの存在

結果的にすべての.mファイルで他のヘッダを読み込むこ
とになる

•
•

通常は「全部」は不要だが、後から追加するときに必ずヘッダを指
定することになる
ヘッダには@classでクラス名を追加する

1クラスを1ヘッダで作る限りはその必要がある

6
プレフィックスヘッダの利用
コンパイル時に必ず読み込
むヘッダ

•
•
•

通常はフレームワークのヘッダ
のみが指定されている
すべてのソースのコンパイル時
に読み込まれる
拡張子は.pch

Xcodeではプリコンパイル
や共有が可能

•

開発中に変更がほとんどない
ようなヘッダ群をコンパイルし
た状態にしておく
7
プリコンパイルヘッダに定義を集める
MyAppDelegate.h
@interface MyAppDelegate : NSObject {
UIWindow *window;
MyAppListViewController *listView;
MyAppDetailViewController
*detailView;
}
@end
MyAppDelegate.m
@implementation MyAppDelegate
@end
MyAppListViewController.h
@interface MyAppListViewController
: NSViewController {
}
@end
MyAppDetailViewController.h
@interface MyAppDetailViewController
: NSViewController {
}
@end

MyApp.pch
@class MyAppDelegate;
@class MyAppListViewController;
@class MyAppDetailViewController;
#import <UIKit/UIKit.h>
#import “MyAppDelegate”
#import “MyAppListViewController”
#import “MyAppDetailViewController”
MyAppListViewController.m
@implementation MyAppListViewController
UIApplication ap = [UIApplication sharedApplication];
MyAppDelegate *aDel = ap.delegate;
MyAppDetailViewController *dvc = aDel.detailView;
@end
MyAppDetailViewController.m
@implementation MyAppDetailViewController
@end
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-todefine-private-methods-for-a-class-in-objective-c

•
•
•

11
プライベートなメソッドの定義
MyAppDetailViewController.h
@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
MyAppDetailViewController.m
@interface MyAppDetailViewController()
-(NSArray *)analyzeParameter:(NSString *)p;
@end

←カテゴリの定義
←プライベートメソッド

@implementation MyAppDetailViewController
-(void) setupContents: (NSString *)param
{}
-(NSArray *)analyzeParameter:(NSString *)p
{}
@end
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
SDK Ver.3.2を
....
#endif

意味する

14
まとめ

プレフィックスヘッダを積極的に使おう
プライベートメソッドを意識しよう

15

Weitere ähnliche Inhalte

Mehr von Masayuki Nii

Mehr von Masayuki Nii (17)

Cocoa勉強会#57-Baseによるローカライズまとめ
Cocoa勉強会#57-BaseによるローカライズまとめCocoa勉強会#57-Baseによるローカライズまとめ
Cocoa勉強会#57-Baseによるローカライズまとめ
 
Cocoa勉強会#56-小ネタ集あなたの常識はすでに通用しない
Cocoa勉強会#56-小ネタ集あなたの常識はすでに通用しないCocoa勉強会#56-小ネタ集あなたの常識はすでに通用しない
Cocoa勉強会#56-小ネタ集あなたの常識はすでに通用しない
 
Cocoa勉強会#45-AWS SimpleDBを使ってみる
Cocoa勉強会#45-AWS SimpleDBを使ってみるCocoa勉強会#45-AWS SimpleDBを使ってみる
Cocoa勉強会#45-AWS SimpleDBを使ってみる
 
Cocoa勉強会#36-iPhone OS 3.0で変更されたテーブルビュー
Cocoa勉強会#36-iPhone OS 3.0で変更されたテーブルビューCocoa勉強会#36-iPhone OS 3.0で変更されたテーブルビュー
Cocoa勉強会#36-iPhone OS 3.0で変更されたテーブルビュー
 
Cocoa勉強会#33-意外に楽に使えるlibcurl
Cocoa勉強会#33-意外に楽に使えるlibcurlCocoa勉強会#33-意外に楽に使えるlibcurl
Cocoa勉強会#33-意外に楽に使えるlibcurl
 
Cocoa勉強会#28-OpenSSLで暗号化したファイルを復号する
Cocoa勉強会#28-OpenSSLで暗号化したファイルを復号するCocoa勉強会#28-OpenSSLで暗号化したファイルを復号する
Cocoa勉強会#28-OpenSSLで暗号化したファイルを復号する
 
Cocoa勉強会#27-QuickLookプラグインの作り方
Cocoa勉強会#27-QuickLookプラグインの作り方Cocoa勉強会#27-QuickLookプラグインの作り方
Cocoa勉強会#27-QuickLookプラグインの作り方
 
Cocoa勉強会23-識別情報の変換〜文字エンコードとデータタイプ
Cocoa勉強会23-識別情報の変換〜文字エンコードとデータタイプCocoa勉強会23-識別情報の変換〜文字エンコードとデータタイプ
Cocoa勉強会23-識別情報の変換〜文字エンコードとデータタイプ
 
Cocoa勉強会#37-シェイクイベントの実装
Cocoa勉強会#37-シェイクイベントの実装Cocoa勉強会#37-シェイクイベントの実装
Cocoa勉強会#37-シェイクイベントの実装
 
Cocoa勉強会#32-表形式のデータに順序を記録する方法
Cocoa勉強会#32-表形式のデータに順序を記録する方法Cocoa勉強会#32-表形式のデータに順序を記録する方法
Cocoa勉強会#32-表形式のデータに順序を記録する方法
 
Cocoa勉強会#35-iPhoneでのコピペとカスタムUI
Cocoa勉強会#35-iPhoneでのコピペとカスタムUICocoa勉強会#35-iPhoneでのコピペとカスタムUI
Cocoa勉強会#35-iPhoneでのコピペとカスタムUI
 
Cocoa勉強会#47-NSURLConnectionのデリゲートメソッドと認証
Cocoa勉強会#47-NSURLConnectionのデリゲートメソッドと認証Cocoa勉強会#47-NSURLConnectionのデリゲートメソッドと認証
Cocoa勉強会#47-NSURLConnectionのデリゲートメソッドと認証
 
Cocoa勉強会#38-UITableViewテーブル内のナビゲーション
Cocoa勉強会#38-UITableViewテーブル内のナビゲーションCocoa勉強会#38-UITableViewテーブル内のナビゲーション
Cocoa勉強会#38-UITableViewテーブル内のナビゲーション
 
Cocoa勉強会#43-Blocksを使う
Cocoa勉強会#43-Blocksを使うCocoa勉強会#43-Blocksを使う
Cocoa勉強会#43-Blocksを使う
 
Cocoa勉強会#42-UIWebKitをコンポーネントとして使う
Cocoa勉強会#42-UIWebKitをコンポーネントとして使うCocoa勉強会#42-UIWebKitをコンポーネントとして使う
Cocoa勉強会#42-UIWebKitをコンポーネントとして使う
 
Cocoa勉強会#50-ストーリーボードとセグウェイ
Cocoa勉強会#50-ストーリーボードとセグウェイCocoa勉強会#50-ストーリーボードとセグウェイ
Cocoa勉強会#50-ストーリーボードとセグウェイ
 
Cocoa勉強会#63-Xcode Server〜みんなで使ってみる
Cocoa勉強会#63-Xcode Server〜みんなで使ってみるCocoa勉強会#63-Xcode Server〜みんなで使ってみる
Cocoa勉強会#63-Xcode Server〜みんなで使ってみる
 

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