2012/04/02

インターフェースビルダーを使わずに画面を生成:Objective-C

画面が表示されるまでの内部的な動きを理解するために、インターフェースビルダーを使わずにベタ書きで画面を生成してみる。

画面を描画するためには大きく分けて次の処理が必要になる。
1.ウィンドウの生成と初期化 2.ビューの生成と初期化 3.ウィンドウにビューを追加して表示
全体像としては、ウィンドウは基本1つだけ存在し、その上に複数のビューとコンポーネントが乗る、というイメージ。 ウィンドウの生成やビューの呼び出しはAppDelegateファイル内に記述する。実際のビューの中身についてはビューを描画するクラスを作って別途定義する。 AppDelegateファイルの全体像は下記。
#import "StudyAppDelegate.h"
#import "HelloWorld.h"

@implementation StudyAppDelegate

@synthesize window = _window;

- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  //ウィンドウの生成、初期化
    _window.backgroundColor = [UIColor whiteColor];  //背景色の指定
    [_window makeKeyAndVisible];  //ウィンドウの表示

    CGRect bounds = [[UIScreen mainScreen] bounds];  //スクリーンサイズの取得
    bounds.origin.y += 20;  //ビューの配置場所を指定
    bounds.size.height -= 20;  //ビューのサイズを指定
    UIView* view = [[[HelloWorld alloc] initWithFrame:bounds] autorelease];  //ビューを生成
    [_window addSubview:view];  //ビューの表示
    
    return YES;
}

- (void)dealloc {
    [_window release];
    [super dealloc];
}

@end
1行ずつの処理の内容を羅列すると、
・起動直後に呼ばれるメソッドで下記を処理 - ウィンドウの生成、初期化 - 背景色の指定 - ウィンドウの表示 - スクリーンサイズの取得 - ビューの配置場所を指定 - ビューのサイズを指定 - ビューを生成 - ビューの表示 - メソッドの返り値としてYESを返す。 ・メモリ開放のメソッドを書く。
1行ずつ見ていく。 まずは土台となるウィンドウを作るところから。

ウィンドウの生成と初期化

_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
まずはUIWindowクラスのallocメソッドでメモリを確保して、initWithFrameメソッドで初期化。初期化時に画面サイズを指定したいので、UIScreenクラスのmainScreenメソッドでメインスクリーンのオブジェクトを取得し、boundsプロパティで画面サイズを取得する。今回はウィンドウサイズ=スクリーンサイズとする。ここまででウィンドウの生成と初期化が完了。

ウィンドウ背景色を指定する

_window.backgroundColor = [UIColor whiteColor];
インスタンス変数_windowのbackgroundColorプロパティに[UIColor whiteColor]を代入すると背景色が指定できる。 この時点でウィンドウの準備が完了したので、

ウィンドウを表示する

[_window makeKeyAndVisible];
つぎはウィンドウの上に乗せるビューの生成と初期化。 ビューの配置する場所や大きさを事前に指定するところから。

改めてウィンドウのサイズを取得しておく

CGRect bounds = [[UIScreen mainScreen] bounds];
CGRect型の変数boundsを用意しつつ、再度[[UIScreen mainScreen] bounds]でメインスクリーンのサイズを改めて取得。(ウィンドウ生成する前の時点で変数を用意して格納しておけば2回記述する必要ないな、、) ※サイズ指定(CGRect CGPoint CGSize) - iPhoneアプリ開発の虎の巻 : http://goo.gl/rJR6H

ビューの配置場所を指定する

bounds.oringin.y += 20;
左上の頂点を始点としてピクセル単位で指定する。メニューバーの下から表示するように値に20を足す。

ビューの縦の大きさを指定する

bounds.size.height -= 20;
ビューを配置する位置を20ピクセル下に移動したので、ビューの全体の縦の大きさは20ピクセル小さくする。(そうしないと画面からはみ出してしまうので。)

ビューの生成と初期化

UIView* view = [[[HelloWorld alloc] initWithFrame:bounds] autorelease];
HelloWorldクラスのインスタンスを生成して、配置場所と大きさを格納したbounds変数を引数として初期化する。 HelloWorldクラスはビューの詳細について書かれているのかな?という感じがする。実際に見てみると、、
#import "HelloWorld.h"

@implementation HelloWorld

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor purpleColor];
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    UIFont* font = [UIFont systemFontOfSize:24];
    [@"Hello, World!" drawAtPoint:CGPointMake(0,0) withFont:font];
}
@end
こんな感じ。詳しく見ていく。

initWithFrame:メソッドをオーバーライド

- (id)initWithFrame:(CGRect)frame {
}
HelloWorldクラスはUIViewクラスを継承しているので、initWithFrame:メソッドをオーバーライドすることによって初期化処理ができるようになる。 次に、初期化処理の具体的な内容。

親クラスの同名メソッドを読んでオブジェクトを生成してプロパティを指定

self = [super initWithFrame:frame];
if (self) {
    self.backgroundColor = [UIColor purpleColor];
}
return self;
ビューを作ったら何か表示しましょう、ということで描画メソッドを定義する。 HelloWorldクラスはUIViewクラスを継承しているので、drawRect:メソッドをオーバーライドして描画処理を実行できる。

drawRect:メソッドをオーバーライド

- (void)drawRect:(CGRect)rect {
}
このdrawRect:メソッドはビューの再描画が必要なタイミングで自動的に呼び出される。

文字列を描画してみる

UIFont* font = [UIFont systemFontOfSize:24];
[@"Hello, World!" drawAtPoint:CGPointMake(0,0) withFont:font];
1行目でフォントサイズの指定用にUIFont型のfont変数にフォントサイズを格納し、2行目でNSStringクラスのdrawAtPoint:withFontメソッドで文字列を描画する。 ちなみにsystemFontOfSizeメソッドはUIFontのクラスメソッド。また、drawAtPointの引数はCGpoint型で引き渡す必要があるため、CGpointMake関数を使ってCGPointを生成している。 HElloWorld.mが確認できたのでAppDelegate.mファイルの続きに戻る。

ビューを表示する

[_window addSubview:view];
addSubviewメソッドでウィンドウにビューを追加する。 ここまでが画面描画までの一連のプロセス。

0 件のコメント:

コメントを投稿