[영화] 아저씨

취미 2011. 2. 28. 14:26


재미는 있었지만 2번은 보기힘든 액션영화..
너무 현실과 떨어진 소재다 보니 몰입에 여러가지 방해가..
걍 환타지나 남미 액션 본듯한 느낌
하지만 원빈의 몸은 두번볼만 하다..ㅡ.ㅡ











'취미' 카테고리의 다른 글

[영화] 황해  (0) 2011.03.29
주말 우에노 나들이..  (0) 2011.03.09
[영화] 시라노 연애조작단  (0) 2011.02.04
[게임] 스타크레프트2 이정훈  (0) 2010.12.07
[게임] 몬스터헌터3rd 포터블  (0) 2010.12.06
Posted by 김반장78
,

#import <UIKit/UIKit.h>


 


//HttpEx의선언


@interface HttpEx : UIViewController <UITextFieldDelegate> {


    UITextField*             _textField;


    UIActivityIndicatorView* _indicator;


    NSMutableData*           _data;


}


@end


#import "HttpEx.h"




#define URL_TEST @"http://npaka.net/iphone/test.txt"
#define BTN_READ 0


//HttpEx의구현
@implementation HttpEx


//텍스트필드 생성


- (UITextField*)makeTextField:(CGRect)rect text:(NSString*)text {
    UITextField* textField=[[[UITextField alloc] init] autorelease];
    [textField setText:text];
    [textField setFrame:rect];
    [textField setReturnKeyType:UIReturnKeyDone];
    [textField setBackgroundColor:[UIColor whiteColor]];
    [textField setBorderStyle:UITextBorderStyleRoundedRect];
    [_textField setDelegate:self];
    return textField;
}


//텍스트버튼 생성
- (UIButton*)makeButton:(CGRect)rect text:(NSString*)text tag:(int)tag {
    UIButton* button=[UIButton buttonWithType:UIButtonTypeRoundedRect];
    [button setFrame:rect];
    [button setTitle:text forState:UIControlStateNormal];
    [button setTag:tag];
    [button addTarget:self action:@selector(clickButton:)
        forControlEvents:UIControlEventTouchUpInside];
    return button;
}


//데이터→스트링
- (NSString*)data2str:(NSData*)data {
    return [[[NSString alloc] initWithData:data
        encoding:NSUTF8StringEncoding] autorelease];
}


//GET방식으로HTTP통신
- (void)http2data:(NSString*)url delegate:(id)delegate {
    NSURLRequest* request=[NSURLRequest
        requestWithURL:[NSURL URLWithString:url]
        cachePolicy:NSURLRequestUseProtocolCachePolicy
        timeoutInterval:30.0];       
    [NSURLConnection connectionWithRequest:request
        delegate:delegate];
       
    //인디케이터 에니메이션의 개시
    [_indicator startAnimating];
}


//데이터수신시작할때 호출NSURLConnection 델리게이트
- (void)connection:(NSURLConnection*)connection
    didReceiveResponse:(NSURLResponse*)response {
    if (_data!=nil) [_data release];
    _data=[[NSMutableData data] retain];
}


//데이터수신시 호출NSURLConnection 델리게이트
- (void)connection:(NSURLConnection*)connection
    didReceiveData:(NSData*)data {
    [_data appendData:data];
}


//데이터수신완료시 호출NSURLConnection 델리게이트
- (void)connectionDidFinishLoading:(NSURLConnection*)connection {
    _textField.text=[self data2str:_data];
   
    [_data release];
    _data=nil;


    //인디케이터 에니메이션의 정지
    [_indicator stopAnimating];
}


//데이터수신실패시 호출NSURLConnection 델리게이트
- (void)connection:(NSURLConnection*)connection
    didFailWithError:(NSError*)error {
    _textField.text=@"통신에러";


    //인디케이터 에니메이션의 정지
    [_indicator stopAnimating];
}


//초기화
- (void)viewDidLoad {
    [super viewDidLoad];
       
    //텍스트필드의 생성
    _textField=[[self makeTextField:CGRectMake(0,0,300,32)
        text:@""] retain];
    [self.view addSubview:_textField];
       
    //접속 버튼 생성
    UIButton* btnRead=[self makeButton:CGRectMake(0,50,90,40)
        text:@"접속" tag:BTN_READ];
    [self.view addSubview:btnRead];


    //인디케이터의 생성
    _indicator=[[UIActivityIndicatorView alloc] init];
    [_indicator setFrame:CGRectMake(140,140,40,40)];
    [_indicator setActivityIndicatorViewStyle:
        UIActivityIndicatorViewStyleWhiteLarge];
    [_indicator setHidesWhenStopped:YES];
    [self.view addSubview:_indicator];


    //변수의 초기화
    _data=nil;
}


- (void)dealloc {
    [_textField release];
    [_indicator release];
    [_data release];
    [super dealloc];
}


//텍스트필드에서 리턴키 눌렸을때 호출
- (BOOL)textFieldShouldReturn:(UITextField*)sender {
    [sender resignFirstResponder];
    return YES;
}


//버튼클릭시 호출
- (IBAction)clickButton:(UIButton*)sender {
    if (sender.tag==BTN_READ) {
        [self http2data:URL_TEST delegate:self];
    }
}



- (BOOL)shouldAutorotateToInterfaceOrientation:
    (UIInterfaceOrientation)orientation {
    return YES;
}
@end

NSData 구현예

// NSDictionary으로 NSData를생성
NSDictionary *dic =[NSDictionary dictionaryWithObject:@"" forKey:@""];
NSData *d = [NSKeyedArchiver archivedDataWithRootObject:dic];

//파일으로 NSData 생성
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:@"파일명" ofType:@"확장자"];
NSData *d = [[NSData alloc] initWithContentsOfFile:path];


// NSDictionary형→NSData형→NSDictionary


 


// NSDictionary오브젝트 생성


NSDictionary *dic =[NSDictionary dictionaryWithObject:@"hoge" forKey:@"KEY"];


 


//생성한 오브젝트를 NSData형으로 변환


NSData *d = [NSKeyedArchiver archivedDataWithRootObject:dic];


 


// NSData형의 오브젝트를NSDictionary형으로 변환


NSDictionary *reverse = [NSKeyedUnarchiver unarchiveObjectWithData:d];


 


 



UIActivityIndicatorView 구현예
로딩등의 이유로 처리지연시 유저에게 처리중임을 표시해야할경우 사용

// 일반생성예
UIActivityIndicatorView *ai = [[UIActivityIndicatorView alloc] init];

// 사이즈를 지정해서 생성
UIActivityIndicatorView *ai =
    [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];

// 스타일을 지정해서 생성
UIActivityIndicatorView  *ai =
    [[UIActivityIndicatorView alloc]
        initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];


 


UIActivityIndicatorView 주요 프로퍼티】


 



프로퍼티명/반환형

설명

hidesWhenStopped
BOOL

에니메이션이정지되었을때 표시를 설정
 YES:인디케이터를 비표시함(디폴트)
 NO:인디케이터를 표시함

activityIndicatorViewStyle
UIActivityIndicatorViewStyle

스타일을 설정
 UIActivityIndicatorViewStyleWhite:표준사이즈(흰색)
 UIActivityIndicatorViewStyleGray:표준사이즈(회색)
 UIActivityIndicatorViewStyleWhiteLarge:큰사이즈(흰색)


 

 

 

UIActivityIndicatorView의주요메소드】


메소드

설명

-(void)startAnimating

에니메이션을 개시함
(예)[ai startAnimating];

-(void)stopAnimating

에니메이션을 정지함
(예)[ai stopAnimating];

-(BOOL)isAnimating

에니메이션중인지 아닌지를 반환
(예)BOOL b = [ai isAnimating];



 

// 인디케이터 예문

UIActivityIndicatorView *ai = [[UIActivityIndicatorView alloc] init];

ai.frame = CGRectMake(0, 0, 50, 50);

ai.center = self.view.center;

ai.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;

[self.view addSubview:ai];

 

[ai startAnimating];  // 에니메이션을 개시하고 싶을때 호출

[ai stopAnimating];  // 에니메이션을 중지하고 싶을때 호출

 

 

NSURLRequestNSMutableURLRequest 차이점

  • NSMutableURLRequest 생성한 인스턴스의 할용도가 높다
  • NSMutableURLRequest post방식으로 전송가능
  • NSMutableURLRequest http헤더를 설정가능
Posted by 김반장78
,
Posted by 김반장78
,

メッセージングの仕組み

Objective-C では、メッセージは実行時までメソッド実装にバインドされません。コンパイラは、次のメッセージ式を変換します。

[receiver message]

上記のメッセージは、メッセージ関数の呼び出し objc_msgSend に変換されます。この関数は、メッセージに記述されたレシーバ とメソッドの名前(メソッドセレクタ)を 2 つの主要なパラメータとして利用します。

objc_msgSend(receiver, selector)

メッセージに渡された引数は、objc_msgSendにも渡されます。

objc_msgSend(receiver, selector, arg1, arg2, ...)

メッセージング関数は、動的バインディングに必要なことをすべて実行します。

  • まず、セレクタが参照するプロシージャ(メソッド実装)を探します。同じメソッドを別々のクラスでそれぞれ実装できるため、メッセージング関数が探す正確なプロシージャはレシーバのクラスによって決まります。
  • 次に、プロシージャを呼び出し、メソッドに指定された引数と一緒に、受信側オブジェクト(そのデータへのポインタ)を渡します。
  • 最終的に、プロシージャの戻り値を自身の戻り値として渡します。

注意:メッセージング関数の呼び出しは、コンパイラによって生成されます。自分が作成するコードの中で直接呼び出してはなりません。

メッセージングのポイントは、コンパイラが各クラスとオブジェクトに対して構築する構造にあります。あらゆるクラス構造には、次の2つの重要な要素が含まれています。

  • スーパークラスへのポインタ。
  • クラスのディスパッチテーブル。このテーブルには、メソッドセレクタとそれらが識別するメソッドのクラス固有のアドレスを関連付けるエントリがあります。たとえば、setOrigin:: メソッドのセレクタは setOrigin::(を実装するプロシージャ)のアドレスと関連付けられ、display メソッドのセレクタは display のアドレスと関連付けられています。

新しいオブジェクトが作成されると、そのメモリが割り当てられ、そのインスタンス変数が初期化されます。オブジェクトの変数の中で最初のものはクラス構造のポインタです。このポインタは isa と呼ばれ、クラス、および継承されるすべてのクラスにアクセスする手段をオブジェクトに提供します。

注意:厳密には言語の一部ではありませんが、オブジェクトが Objective-C ランタイムシステムと連携するには isa ポインタが必要になります。オブジェクトは、構造に定義されるどのようなフィールドでも struct objc_objectobjc/objc.h で定義)と「同等」でなければなりません。しかし、独自にルートオブジェクトを作成する必要が生じることは、あったとしても非常にまれで、NSObject または NSProxy を継承するオブジェクトは isa 変数を自動的に持っています。

これらのクラスとオブジェクト構造の要素を、図 2-5 に示します。


図 2-5 メッセージングフレームワーク

図 2-5 メッセージングフレームワーク

メッセージをオブジェクトに送信すると、メッセージング関数は、オブジェクトの isa ポインタをたどってクラス構造に到達し、そこでディスパッチテーブルでメソッドセレクタを調べます。ディスパッチテーブルにセレクタが見つからない場合、objc_msgSend はポインタをたどってスーパークラスに到達し、そのディスパッチテーブルの中でセレクタを探します。失敗し続けると、objc_msgSend は NSObject クラスに達するまでクラス階層を遡ることになります。セレクタが見つけると、この関数はテーブルに含まれているメソッドを呼び出し、受信側オブジェクトのデータ構造を渡します。

これが、実行時にメソッド実装が選択される方法です。オブジェクト指向プログラミング特有の言い回しをすれば、メソッドがメッセージへ動的にバインドされるといいます。

メッセージング処理をスピードアップするため、ランタイムシステムはセレクタの使用に伴って、セレクタと、対応するメソッドのアドレスをキャッシュします。クラスごとに個別のキャッシュがあり、クラスで定義したメソッドのセレクタだけでなく、継承したメソッドのセレクタを含むこともできます。ディスパッチテーブルを検索する前に、メッセージングルーチンはまず、受信側オブジェクトのクラスのキャッシュを確認します(一度使用したメソッドは再度使用する可能性があるため)。キャッシュにメソッドセレクタがある場合、メッセージングは関数呼び出しより若干遅いだけです。キャッシュを「ウォームアップ」するのに十分な時間、プログラムが実行されると、そのプログラムが送信するほとんどすべてのメッセージは、対応するキャッシュされたメソッドが見つかります。プログラムの実行に伴い、新しいメッセージに対応するため、キャッシュは動的に成長します。

このセクションの内容:

セレクタ
隠し引数
self と super に対するメッセージ

セレクタ

効率化のため、コンパイル済みのコードでは完全な ASCII 名をメソッドセレクタとして使用しません。その代わりに、コンパイラは各メソッド名をテーブルに書き込み、その名前を実行時にメソッドを示す一意の識別子と組み合わせます。ランタイムシステムによって、各識別子が一意であることが保証されます。2 つのセレクタが同じであることはなく、同じ名前のメソッドはすべて同じセレクタに対応します。コンパイル済みのセレクタは、他のデータと区別するため、特別な型 SEL に割り当てられます。有効なセレクタは 0 であることはありません。メソッドへの SEL 識別子の割り当てはシステムに任せる必要があります。任意に割り当てても無駄になります。

@selector() ディレクティブにより、Objective-C のソースコードは完全なメソッド名ではなく、コンパイル済みのセレクタを参照することができます。次の例では、setWidth:height: のセレクタを、setWidthHeight 変数に代入しています。

SEL  setWidthHeight;
setWidthHeight = @selector(setWidth:height:);

コンパイル時に @selector() ディレクティブを使用して、SEL 変数に値を代入するのが最も効率的です。しかし、場合によっては、プログラムで実行時に文字列をセレクタに変換する必要があります。これを実行するには、NSSelectorFromString 関数を使います。

setWidthHeight = NSSelectorFromString(aBuffer);

逆方向の変換も可能です。NSStringFromSelector 関数はセレクタに対応するメソッド名を返します。

NSString *method;
method = NSStringFromSelector(setWidthHeight);

このようなランタイム関数については、Cocoa フレームワークリファレンスドキュメントで説明しています。


メソッドとセレクタ

コンパイル済みのセレクタは、メソッド実装ではなく、メソッド名を識別します。たとえば、Rectangle の display メソッドには、他のクラスで定義された display メソッドと同じセレクタが対応します。これはポリモーフィズム(多態性)と動的バインディングには不可欠です。これにより、さまざまなクラスに属するレシーバに、同じメッセージを送信することができます。メソッド実装ごとに 1 つのセレクタがあったとしたら、メッセージは関数呼び出しと変わりません。

クラスメソッドと同じ名前のインスタンスメソッドは、同じセレクタに割り当てられます。しかし、それらは別々のドメインに属するため、2 つの間に混乱はありません。クラスでは、display インスタンスメソッドに加えて、display クラスメソッドを定義することができます。


メソッドの戻り値と引数の型

メッセージングルーチンはセレクタを通してのみメソッド実装にアクセスできるため、同じセレクタに対応するすべてのメソッドを同等に扱います。ルーチンは、セレクタに基づいてメソッドの戻り型と引数のデータ型を知ります。したがって、静的に型定義されたレシーバに送信されたメッセージを除いて、動的バインディングでは、同じ名前を持つメソッドのすべての実装で、戻り型と引数型が同じである必要があります(コンパイラはクラス型からメソッド実装を知ることができるため、静的に型定義されたレシーバはこのルールの例外です)。

同じ名前のクラスメソッドとインスタンスメソッドは、同じセレクタで表されますが、引数と戻り型が異なる可能性があります。


実行時のメッセージ変更

performSelector:performSelector:withObject:、および performSelector:withObject:withObject: メソッドは NSObject プロトコルで定義されており、SEL 識別子を初期引数として利用します。3 つのメソッドはすべて、メッセージング関数に直接マップされます。たとえば、次のように記述します。

[friend performSelector:@selector(gossipAbout:)
    withObject:aNeighbor];

次のように記述しても同じです。

[friend gossipAbout:aNeighbor];

これらのメソッドにより、メッセージを受信するオブジェクトを変更できるのと同じように、実行時にメッセージを変更できます。メッセージ式を構成する両方の要素に変数名を使用することができます。

id   helper = getTheReceiver();
SEL  request = getTheSelector();
[helper performSelector:request];

上記の例では、レシーバ(helper)は実行時に(架空の getTheReceiver 関数によって)選択され、レシーバが実行するように要求されるメソッド(request)も実行時に(同様に架空の getTheSelector 関数によって)決められます。

注意:performSelector: とその関連メソッドは id を返します。実行されるメソッドが別の型を返す場合は、適切な型にキャストする必要があります(ただし、キャストがすべての型に有効なわけではありません。メソッドはポインタまたはポインタと互換性のある型を返す必要があります)。


ターゲットアクションパラダイム

ユーザインタフェース制御の処理において、Application Kit はレシーバとメッセージの両方を変更する方法を有効に利用しています。

NSControls は、アプリケーションへの指示を指定するのに使用できるグラフィカルデバイスです。大部分はボタン、スイッチ、ノブ、テキストフィールド、ダイヤル、メニュー項目など、現実世界の制御デバイスに似ています。ソフトウェアでは、これらのデバイスがアプリケーションとユーザの間に介在します。これらのデバイスは、キーボードやマウスなどのハードウェアデバイスから発されるイベントを解釈し、アプリケーション固有の命令に変換します。たとえば、「検索」というラベルの付いたボタンはマウスクリックを、アプリケーションが何かの検索を開始する命令に変換します。

Application Kit は制御デバイスを作成するためのテンプレートを定義し、「そのまま」使用できる独自のデバイスもいくつか定義します。たとえば、NSButtonCell クラスでは、NSMatrix に割り当てて、サイズ、ラベル、ピクチャ、フォント、およびキーボードショートカットを初期化できるオブジェクトを定義します。ユーザがボタンをクリックすると(あるいは、キーボードショートカットを使用すると)、NSButtonCell はアプリケーションに何かを実行するよう指示するメッセージを送信します。これを行うには、NSButtonCell を画像、サイズ、およびラベルだけでなく、どんなメッセージを送信し、誰に送信するかに関する指示においても初期化する必要があります。したがって、NSButtonCell はアクションメッセージ、送信するメッセージで使用するメソッドセレクタ、ターゲット(メッセージを受信するオブジェクト)で初期化することができます。

[myButtonCell setAction:@selector(reapTheWind:)];
[myButtonCell setTarget:anObject];

NSButtonCell は、NSObject の performSelector:withObject: メソッドを使用してメッセージを送信します。すべてのアクションメッセージは 1 つの引数、つまりメッセージを送信する制御デバイスの id を受け取ります。

Objective-C でメッセージを変更できないとしたら、すべての NSButtonCells が同じメッセージを送信しなければならなず、メソッドの名前が NSButtonCell ソースコードで固定されます。ユーザ操作をアクションメッセージに変換するメカニズムを単に実装するのではなく、NSButtonCell などのコントロールでメッセージの内容に制約を課す必要が生じます。これでは、どのようなオブジェクトも、複数の NSButtonCell に対応するのが困難になります。ボタンごとに 1 つのターゲットを用意するか、ターゲットオブジェクトがメッセージを送信したボタンを検出し、それに応じて動作する必要が生じます。ユーザインタフェースを再配置するたびに、アクションメッセージに応答するメソッドも再実装する必要が生じます。幸いにも、Objective-C では、このように不要な複雑さが回避されています。


メッセージングエラーの回避

オブジェクトが、レパートリーにないメソッドを実行するメッセージを受信すると、エラーが発生します。これは、存在しない関数を呼び出した場合と同じ種類のエラーです。しかし、メッセージングは実行時に行われるため、多くの場合、プログラムを実行するまでエラーが明らかになりません。

メッセージセレクタが不変で、受信側オブジェクトのクラスが分かっている場合、このようなエラーを回避するのは比較的簡単です。プログラムを記述するときに、レシーバが応答できることを確認しておけばよいからです。レシーバが静的に型定義されていれば、コンパイラがそのテストを実行してくれます。

しかし、メッセージセレクタまたはレシーバのクラスが可変の場合、そのテストを実行時まで延期しなければならない場合もあります。NSObject クラスで定義されている respondsToSelector: メソッドを使用してレシーバがメッセージに応答できるかどうかを調べることができます。引数としてメソッドセレクタを受け取り、レシーバがセレクタに一致するメソッドにアクセスできるかどうかを返します。

if ( [anObject respondsToSelector:@selector(setOrigin::)] )
    [anObject setOrigin:0.0 :0.0];
else
    fprintf(stderr, "%s can’t be placed\n",
        [NSStringFromClass([anObject class]) cString]);

respondsToSelector: テストが特に重要なのは、コンパイル時に制御の及ぶ範囲内にないオブジェクトにメッセージを送信する場合です。たとえば、他から設定可能な変数によって指定されるオブジェクトにメッセージを送信するコードを記述する場合は、必ずメッセージに応答できるメソッドをレシーバが実装するようにします。

注意:また、オブジェクトは、自身で直接応答できない場合、受信したメッセージを他のオブジェクトに転送するように準備することもできます。その場合、メッセージを別のオブジェクトに割り当てて間接的に応答しているにも関わらず、オブジェクトがメッセージを処理できるように見えます。詳細については、「転送」を参照してください。


隠し引数

メッセージング関数はメソッドを実装するプロシージャを見つけると、そのプロシージャを呼び出し、メッセージのすべての引数を渡します。また、次の 2 つの隠し引数をプロシージャに渡します。

  • 受信側オブジェクト
  • メソッドのセレクタ

これらの引数はすべてのメソッド実装に、当該実装を呼び出したメッセージ式の両方の構成要素に関する明確な情報を提供します。それらの引数は、メソッドを定義するソースコードで宣言されないため、「隠し」引数と呼ばれています。これらは、コードのコンパイル時に実装に挿入されます。

これらの引数は明示的には宣言されませんが、ソースコードは(受信側オブジェクトのインスタンス変数を参照できるのと同じように)隠し引数を参照することができます。メソッドは受信側オブジェクトを self として、自身のセレクタを _cmd として参照します。次の例では、_cmdstrange メソッドのセレクタを参照し、selfstrange メッセージを受信するオブジェクトを参照します。

- strange
{
    id  target = getTheReceiver();
    SEL method = getTheMethod();
    if ( target == self || method == _cmd )
        return nil;
    return [target performSelector:method];
}

この 2 つの引数のうち、self のほうが有用です。実際、これは受信側オブジェクトのインスタンス変数を、メソッド定義で利用可能にする方法です。


selfsuper に対するメッセージ

Objective-C では、メソッドを実行するオブジェクトを参照するためにメソッド定義内で使用できる 2 つのキーワード、selfsuper が提供されています。

たとえば、操作対象となるすべてのオブジェクトの座標を変更する必要がある、reposition メソッドを定義するとします。そのメソッドは、変更を行う setOrigin:: メソッドを呼び出すことができます。必要なのは、reposition メッセージ自体の送信先となった同じオブジェクトに、setOrigin:: メッセージを送信することだけです。位置変更コードを記述する際には、そのオブジェクトを self または super のいずれかとして参照することができます。reposition メソッドはどちらも読み取ることができます。

- reposition
{
    ...
    [self setOrigin:someX :someY];
    ...
}

または

- reposition
{
    ...
    [super setOrigin:someX :someY];
    ...
}

この場合、どのようなオブジェクトであっても、selfsuper はどちらも reposition メッセージを受信するオブジェクトを参照します。ただし、この 2 つのキーワードはまったく異なるものです。self は、メッセージングルーチンがすべてのメソッドに渡す隠し引数の 1 つであり、インスタンス変数の名前と同じように、メソッド実装内で自由に使用できるローカル変数です。super は、メッセージ式でレシーバとしてのみ self の代わりに使用できるキーワードです。レシーバーから見ると、2 つのキーワードは、主にメッセージング処理に与える影響が異なります。

  • self は受信側オブジェクトのクラスのディスパッチテーブルから始まり、通常の方法でメソッド実装を検索します。上記の例では、再配置メッセージを受信するオブジェクトのクラスから検索を始めます。
  • super は、まったく異なる場所でメソッド実装の検索を開始します。検索は、super が出現するメソッドを定義する、クラスのスーパークラスから始まります。上記の例では、再配置が定義されるクラスのスーパークラスから検索を始めます。

どこで super がメッセージを受信しても、コンパイラは objc_msgSend 関数の代わりに別のメッセージングルーチンを使用します。代替ルーチンは、メッセージを受信するオブジェクトのクラスではなく、定義クラスのスーパークラス、つまり super にメッセージを送信するクラスのスーパークラスを直接参照します。


selfsuper の違いは、3 つのクラスの階層で明確になります。たとえば、Low というクラスに属するオブジェクトを作成するとします。Low のスーパークラスは Mid で、Mid のスーパークラスは High です。3 つのクラスすべてで negotiate というメソッドを定義し、さまざまな用途に使用します。さらに、Mid では makeLastingPeace という高度なメソッドを定義しますが、これは negotiate メソッドも必要とします。次の図 2-6 にこれを図示します。


図 2-6 High、Mid、Low

図 2-6 High、Mid、Low

ここで、makeLastingPeace メソッドを実行するために Low オブジェクトにメッセージを送信します。すると、makeLastingPeace は同じ Low オブジェクトに negotiate メッセージを送信します。ソースコードの中でメッセージの送信対象オブジェクトを self と呼ぶ場合には、次のようになります。

- makeLastingPeace
{
    [self negotiate]; 
    ...
}

メッセージングルーチンは、self の実際のクラスである Low に定義されているバージョンの negotiate を探します。しかし、Mid のソースコードで送信対象のオブジェクトを super と呼ぶ場合には、次のようになります。

- makeLastingPeace
{
    [super negotiate]; 
    ...
}

メッセージングルーチンは、High に定義されているバージョンの negotiate を探します。makeLastingPeace は Mid で定義されているため、メッセージングルーチンは受信側オブジェクトのクラス (Low) を無視して、Mid のスーパークラスにスキップします。どちらのメッセージも、Mid バージョンの negotiate を探しません。

この例に示すように、super は別のメソッドをオーバーライドするメソッドをバイパスする手段を提供します。この場合は、makeLastingPeace が、元の High バージョンの negotiate を再定義する Mid バージョンを無視することを可能にしました。

Mid バージョンの negotiate に到達できないのは欠陥のように見えるかもしれませんが、このような状況ではそれを回避するほうが適切です。

  • Low クラスの作成者が意図的に Mid バージョンの negotiate をオーバーライドして、Low クラス(およびそのサブクラス)のインスタンスが、再定義されたバージョンのメソッドを代わりに呼び出すようにしています。Low の設計者は、Low オブジェクトに継承メソッドを実行させないようにしたわけです。
  • super にメッセージを送信することで、Mid の makeLastingPeace メソッドの作成者は、Mid バージョンの negotiate(および Mid を継承する Low などのクラスで定義するバージョン)を意図的にスキップして、High クラスに定義されているバージョンを実行するようにしました。Mid の設計者は、negotiate の High バージョンだけを使用するようにしたいわけです。

それでも Mid バージョンの negotiate を使用することはできますが、そのためには Mid インスタンスに直接メッセージを送信する必要があります。


super の使用

super へのメッセージにより、メソッド実装を複数のクラスに分散することができます。既存のメソッドをオーバーライドして変更や追加を行う一方で、元のメソッドをその変更に組む込むことができます。

- negotiate
{
    ...
    return [super negotiate]; 
}

処理によっては、継承階層の各クラスで作業の一部を行い、残りの作業についてはメッセージを super に渡して処理するメソッドを実装することができます。新たに割り当てられたインスタンスを初期化する init メソッドは、このように動作するように設計されています。それぞれの init メソッドは、クラスに定義されているインスタンス変数を初期化する 役割を持っています。しかし、初期化の前に、init メッセージを super に送信して、継承元のクラスにインスタンス変数を初期化させます。init の各バージョンがこの手続きに従うため、クラスは継承の順序に従ってインスタンス変数を初期化することになります。

- (id)init
{
    [super init];
    ...
}

また、中核的な機能をスーパークラスに定義する 1 つのメソッドに集中させ、サブクラスにおいて super へのメッセージを使用してそのメソッドを組み込むこともできます。たとえば、インスタンスを作成するすべてのクラスメソッドは、新しいオブジェクトにデータ記憶域を割り当て、isa ポインタをクラス構造で初期化する必要があります。これは、通常、NSObject クラスに定義されている alloc および allocWithZone: メソッドに委ねられます。別のクラスでこれらのメソッドをオーバーライドする場合も(まれなケース)、そのメソッドでメッセージを super に送信することによって基本機能を利用することができます。


self の再定義

super は実行するメソッドの検索を始める場所をコンパイラに伝える単なるフラグで、メッセージのレシーバとしてのみ使用します。しかし、self は変数名で、いろいろな方法で使用でき、新しい値を代入することもできます。

クラスメソッドの定義では、まさにそうすることがよくあります。クラスメソッドは多くの場合、クラスオブジェクトではなく、クラスのインスタンスを対象としています。たとえば、多くのクラスメソッドがインスタンスの割り当てと初期化を結合し、多くの場合、同時にインスタンス変数値も設定します。このようなメソッドでは、インスタンスメソッドの場合と同様に、新たに割り当てられたインスタンスにメッセージを送信して、self インスタンスを呼び出すことも考えられます。しかし、これはエラーになります。selfsuperは、どちらも受信側オブジェクト(メソッドを実行するように指示するメッセージを取得するオブジェクト)を参照します。インスタンスメソッド内では self はインスタンスを参照しますが、クラスメソッド内では self はクラスオブジェクトを参照します。次の例は、してはいけないことを示します。

+ (Rectangle *)rectangleOfColor:(NSColor *) color
{
    self = [[self alloc] init]; // だめ
    [self setColor:color];
    return [self autorelease]; 
}

混乱を避けるために、通常はクラスメソッド内のインスタンスを参照するとき、self ではなく、変数を使用するほうが適切です。

+ (id)rectangleOfColor:(NSColor *)color
{
    id newInstance = [[self alloc] init]; // よい
    [newInstance setColor:color];
    return [newInstance autorelease];
}

実際、クラスメソッドの中で selfalloc メッセージを送信するよりも、多くの場合は alloc[self class] に送信するほうが有効です。こうしておけば、クラスをサブクラス化し、サブクラスが rectangleOfColor: メッセージを受信した場合、返されるインスタンスはそのサブクラスと同じ型になります。

+ (id)rectangleOfColor:(NSColor *)color
{
    id newInstance = [[[self class] alloc] init]; // 最良
    [newInstance setColor:color];
    return [newInstance autorelease];
}

オブジェクト割り当ての詳細については、「メモリ管理」を参照してください。



ps. 이건 걍 읽어나 봐야겠다..ㅡ.ㅡ
Posted by 김반장78
,

Tab Bar Controller

 

 

u     Tab Bar인터페이스

n         용도

같은 데이터셋에대해 다른 표현방법을 제공해야할 경우

기능별로 나누어서 어플리케이션을 구성해야할 경우

 

n         Tab Bar View 컨포넌트

화면 하단에 표시

어플리케이션의 각종 모드간의 화면 전환기능을 지원

각 모드의 상태에 관한 정보를 표시가능

 

n         Tab Bar ViewController 오브젝트

Tab Bar View를 작성하고 관리

각 모드별 뷰를 관리하는 커스텀뷰컨트롤러를 관리

 

n         Tab Bar View는 통상의 커스터마이즈 가능한 오브젝트이나 Tab Bar인터페이스에 포함된경우에는 변경해서는 안됨

Tab Bar인터페이스에서는 Tab Bar뷰가 Tab Bar컨트롤러에 소유된 프라이베이트한 뷰계층의 일부로 간주함

액티브한 탭 리스트의 변경이 필요한때에는 반드시 Tab Bar컨트롤러의 메소드를 사용해야함

u     Tab Bar인터페이스의 오브젝트

n         종류

UITabBarController 오브젝트

탭별 한개씩 존재하는 커스텀 ViewController 오브젝트

옵션의 델리게이트 오브젝트

 

n         설명

각 뷰컨트롤러에는 선택될때 표시되는 컨텐츠가 지정되어 있음

지정되는 뷰컨트롤러에는 단일 뷰를 표시하는 커스텀 뷰 컨트롤러나 네비게이션 컨트롤러도 사용가능. 하지만 탭바뷰컨트롤러는 사용 불가능

뷰컨트롤러 프로퍼티에 5개가 넘는 항목을 추가하면 탭바에 들어가지 못한 항목의 표시를 위해

특별한 뷰컨트롤러(MoreView Controller)를 자동적으로 삽입

 

n         MoreView Controller

5개이상의 뷰컨트롤러를 테이블형식으로 표시가능

커스터마이즈 하거나 선택하는건 불가능

탭바 컨트롤러가 관리하는 뷰 컨트롤러 리스트에 포함되어있지 않음

보통 필요한때에 자동으로 표시되어 커스텀콘텐츠로부터 독립되어있음

참조가 필요할 경우에는UITabBarControllermoreNavigationController 프로퍼티에 접근

 

 

u     Tab Bar 인터페이스의 작성

n         인터페이스 사용방법 결정

어플리케이션의 메인 윈도우에 직접 추가

Split view 인터페이스의 두개중 한개의 루트뷰중 한곳에 추가(iPad만 가능)

모드에 고유의 구성을 필요로하는 데이터를 표시하기위해 모달모드로 표시

Popover에서 표시(iPad만 가능)

 

n         주의사항

네비게이션 컨트롤러를 탭내에 내장하는것은 가능하나 그 반대의 경우는 불가능

 

n         탭바 인터페이스용의 커스텀 뷰 컨트롤러의 정의

탭바 인터페이스의 각 모드는 다른 모드들과는 독립되어 있음

각모드의 루트 컨트롤러가 탭 안의 콘텐츠를 정의하고 있음

모드의 콘텐츠가 복잡한 경우에는 네비게이션 컨트롤러를 인스톨함으로서 탭내에서의

조작을 지원

모드의 콘텐츠가 비교적 단순한 경우에는 단일뷰를 가진 커스텀 뷰 컨트롤러를 인스톨

 

 

n         NIB파일을 사용한 탭바 인터페이스의 작성

탭바컨트롤러를 nib파일에서 로드하는 경우는 커스텀 뷰 컨트롤러에서 로드하는 경우와 조금 다름

뷰컨트롤러의 경우 프로그램안에서 작성하는 경우나 다른 nib파일에서 로드하는 경우 똑같이 개별적으로 작성함

              탭바 컨트롤러의 경우 뷰는 반드시 프로그램안에서 작성하기때문에 독립된 nib파일에 격납할 뷰는

              존재하지 않기때문에 탭바컨트롤러가 nib파일을 관리할 일이 없음

              대신에 탭바컨트롤러와 nib파일이 관계를 가지는 경우는 탭바컨트롤러 자체가 nib파일에

포함될 경우

그렇기 때문에 대부분의 경우에 탭바컨트롤러는 다른 오브젝트가 관리하는 닙파일에 포함됨

가장 이상적인 구성은 탭뷰컨트롤러를 어플리케이션의 메인nib파일에 포함시키는 것

              탭바 컨트롤러 자신이 어플리케이션 윈도우의 메인뷰를 제공하는 경우 모달 모드에서 표시 되는

              탭바 컨트롤러를 nib파일에서 로드하는것도 가능하지만 최적은 아님

              실제로는 탭바컨트롤러를 필요할때 프로그램안에서 작성해서 쓰는게 일반적

 

              위 그림에서 각 커스텀 뷰 컨트롤러는 한개의 탭에 연결된 루트 뷰 컨트롤러를 표시함

              각 뷰컨트롤러는 커스텀 뷰 컨트롤러이기때문에 뷰를 포함하고 있는 nib파일을 참조하고 있음

              메인nib파일에 각각의 커스텀 뷰를 포함시키는것도 가능하지만 추천하지 않음

              뷰를 별도의 nib파일에 포함시키는것으로 시스템에서 필요에따라 뷰를 메모리에서

완전히 파기하는게 가능해짐

 

n         텝바컨트롤러의 작성 순서 예(메인 윈도우 nib에 포함시킬경우)

탭바 어플리케이션 템플리트를 사용할경우 1,2과정은 스킵

1.       탭바컨트롤러 오브젝트를 라이브러리에서 인터페이스 빌더의 도큐멘트윈도우에 드래그함

탭바컨트롤러를 nib파일에 추가하면 인터페이스 빌더에 의해 1개의 탭바뷰, 2개의 루트뷰컨트롤러, 2개의 탭바아이콘이 추가됨

2.       아웃렛을 사용해서 탭바컨트롤러에의 참조를 저장함

실행시에 이 탭바컨트롤러에 엑세스하기위해선 아웃렛을 사용하거나 닙파일을 로드할때 닙파일의 최상위 레벨의 오브젝트를 명시적으로 취하는 방법이 있음

일반적으로 아웃렛을 사용

 

아웃렛을 추가하는 방법

@interface MyAppDelegate :NSObject <UIApplicationDelegate> {

IBOutlet UITabBarController* myTabBarController;

}

@end

아웃렛의 정의를 추가하고 아웃렛에서 탭바컨트롤러오브젝트에 접속을 작성

3.       인터페이스에 표시하고싶은 탭수에 맞춰서 뷰컨트롤러를 추가하거나 삭제함

탭바 컨트롤러 오브젝트에 포함된 뷰컨트롤러 수에 의해 탭바 인터페이스에 표시되는 탭의 수가 정해짐

최종적인 탭바컨트롤러에는 최소한 2개의 뷰컨트롤러가 포함되야함

인터페이스 빌더의 라이브러리에서 뷰컨트롤러나 네비게이션컨트롤러 테이블뷰컨트롤러를 드래그해서 탭과 연결시키는것이 가능함

뷰컨트롤러를 추가하는 방법은 아래와 같음

■ 적절한 오브젝트를 라이브러리에서 편집서페이스내의 탭바에 드래그함

■ 오브젝트 라이브러리에서 인터페이스 빌더의 도큐먼트윈도우안의 탭바 컨트롤러에 드래그

윈도우는 아웃라인모드 이여야함

네비게이션 컨트롤러나 테이블뷰 컨트롤러를 인터페이스에 추가할 경우에는 해당 오브젝트를 라이브러리에서 드래그하거나 탭바 컨트롤러를 선택해서Attributes인스펙터를 사용해서 뷰컨트롤러의 종류를 설정

범용 뷰컨트롤러 오브젝트를 닙파일에 드래그해서 클래스명을 원하는 클래스타입으로 변경

                           

4.       화면에 표시할 순서대로 뷰컨트롤러를 정렬

탭바 컨트롤러의 편집서페이스에 표시된 탭을 드래그하거나 인터페이스빌더의 도큐먼트윈도우에 뷰컨트롤러를 드래그함으로서 (아웃라인모드인 경우) 뷰컨트롤러의 순서를 바꾸는것이 가능함

편집서페이스에는 모든 탭이 표시되나 실행시에는 5개만 표시됨

탭바 컨트롤러에 6개이상의 뷰컨트롤러가 포함된 경우에는 초기화상태의 탭바에는 최초의 4개만 표시됨 5번째의 탭에는 나머지 뷰컨트롤러를 표시하는More뷰컨트롤러용으로 예약됨

5.       각 탭에 루트뷰컨트롤러를 설정

각 루트뷰컨트롤러에는 다음과같은 속성을 설정해야만함

Identity」인스펙터를 사용해서 임의의 뷰컨트롤러 오브젝트의 클래스를 설정함

루트뷰컨트롤러가 범용의 뷰컨트롤러오브젝트이거나 테이블뷰컨트롤러오브젝트인 경우에는 클래스명을 커스텀서브클래스로 변경가능

루트뷰컨트롤러가 네비게이션 컨트롤러 오브젝트인경우에는 클래스명을 변경해서는 안됨

■ 뷰컨트롤러에 뷰를 설정

가장 일반적으로 뷰컨트롤러의 닙네임속성을 뷰를 포함한 닙파일의 이름으로 설정하는 방법이 사용

뷰를 메인 닙파일에 포함시키는것도 가능은 하나 추천하지 않음

■ 필요에 따라서 뷰컨트롤러의 스타일을 설정함

루트뷰컨트롤러중 네비게이션컨트롤러를 사용할 경우에는

6.       각뷰컨트롤러에 탭바 아이템을 설정

탭바컨트롤러의 편집서페이스 혹은 인터페이스 빌더의 도큐먼트윈도우(아웃라인모드 혹인 브라우져모드의 경우)에서 탭바이이템을 선택가능함 인터페이스빌더를 사용해서 탭바아이템의 타이틀, 화상, 뱃지를 설정할수 있음

혹은 Attributes인스펙터로 Identifier프로퍼티의 값을 할당함으로 탭바아이템을 표준의 시스템탭 한개에 설정하는것도 가능

7.       어플리케이션 델리게이트의applicationDidFinishLaunching메소드안에서 탭바컨트롤러뷰를 메인윈도우에 추가함

탭바 컨트롤러를 자동으로 어플리케이션의 윈도우에 인스톨하는것은 불가능 아래의 코드로 직접인스톨해야함

- (void)applicationDidFinishLaunching:(UIApplication *)application {

[window addSubview:myTabBarController.view];

}

8.       닙파일을 저장

 

n         프로그램으로 탭바인터페이스를 작성

탭바컨트롤러를 프로그램안에 작성하고 싶을 때 가장 권장하는 위치는 어플리케이션 델리게이트의 applicationDidFinishLaunching 메소드 임

통상 탭바컨트롤러는 어플리케이션 윈도우의 루트뷰를 저공하므로 어플리케이션을 기동한 직후 윈도우를 표시하기전에 탭바컨트롤러를 작성할 필요가 있음

프로그램안에 작성 순서

1.      신규의UITabBarController오브젝트를 작성

2.      탭별로 한 개씩의 커스텀 루트 뷰 컨트롤러를 작성

3.      루트뷰컨트롤러들을 배결에 추가해 탭바컨트롤러의 viewControllers프로퍼티에 할당

4.      탭바컨트롤러의 뷰를 어플리케이션의 메인윈도우에 추가

어플리케이션의 메인윈도우에 탭바 컨트롤러의 인터페이스를 작성해서 인스톨하기위해 필요한 기본적인 코드

- (void)applicationDidFinishLaunching:(UIApplication *)application {

tabBarController = [[UITabBarController alloc] init];

MyViewController* vc1 = [[MyViewController alloc] init];

MyOtherViewController* vc2 = [[MyOtherViewController alloc] init];

NSArray* controllers = [NSArray arrayWithObjects:vc1, vc2, nil];

tabBarController.viewControllers = controllers;

// Tab Bar Controllerの現在のビュをウインドウのサブビュとして追加する

[window addSubview:tabBarController.view];

}

 

n         프로그램으로 탭바아이템을 작성

탭바인터페이스의 각 루트뷰 컨트롤러에는 각각에 대응하는 탭에 표시하는 화상과 텍스트를 가진 UITabBarItem 오브젝트를 제공해야함

탭바 인터페이스가 표시되기전에는 언제든 탭바 아이템을 뷰 컨트롤러에 연결가능함

해당 오브젝트는 탭바아이템을 각각에 대응하는 뷰컨트롤러의 tabBarItem프로퍼티에 할당

탭바아이템을 작성하는 이상적인 시기는 뷰컨트롤러자신의 초기화중이지만 통상 위의 경우는 커스텀뷰컨트롤러의 경우뿐임 뷰컨트롤러를 작성해서 초기화하고 탭바아이템을 작성해서 연결시키는 것이 가능함

커스텀뷰컨트롤러에 탭바아이템을 작성하는 예

- (id)init {

if (self = [super initWithNibName:@"MyViewController" bundle:nil]) {

self.title = @"My View Controller";

UIImage* anImage = [UIImage imageNamed:@"MyViewControllerImage.png"];

UITabBarItem* theItem = [[UITabBarItem alloc] initWithTitle:@"Home"

image:anImage tag:0];

self.tabBarItem = theItem;

[theItem release];

}

return self;

}

 

u     실행시 탭의 관리

n         탭바 인터페이스를 작성한후에는 몇가지의 방법을 사용해 인터페이스를 변경하거나 어플리케이션내의 변화에 대응가능

탭의 추가나 삭제가 가능

델리게이트오브젝트를 사용해서 동적인 조건을 기반으로 탭의 선택을 금지시키는것도 가능

각각의 탭에 뱃지를 추가해서 유저에게 해당탭에 주의시키는것도 가능

 

n         탭의 삭제와 추가

탭바 인터페이스안 탭의 수가 동적으로 변화할 경우 필요에 따라 실행시에 적절한 변경이 가능함

작성시에 탭을 설정하는 방법과 같이 적절한 뷰컨트롤러셋을 탭바컨트롤러에 할당함으로서 실행시에 탭을 변경함

유저에게 시각적인 효과를 주면서 탭을 추가하거나 삭제할경우에는 setViewControllers:animated:를 사용해서 탭변경을 에니메이션화 하는 것 도 가능

현재 선택된 탭내의 특정버튼에 의해 해당탭을 삭제하는 메소드

- (IBAction)processUserInformation:(id)sender {

if ([self userDataIsValid]) {

NSMutableArray* newArray = [NSMutableArray

arrayWithArray:self.tabBarController.viewControllers];

[newArray removeObject:self];

[self.tabBarController setViewControllers:newArray animated:YES];

}

}

 

n         탭 선택 금지

유저가 탭을 선택하지 못하게 할경우에는 델리게이트오브젝트를 준비해서 tabBarController:shouldSelectViewController:메소드를 작성함

탭의 선택을 금지하는 경우는 예를들면 어플리케이션에서 유저에게 아이디 패스워드의 입력을 요구할경우 입력을 받는 태그이외의 태그를 무효로 하는 것이 가능

위의 상황의 예제 코드 hasValidLogin메소드는 입력된 정보를 검증하기위해 작성한 커스텀 메소드

shouldSelectViewController:(UIViewController *)viewController {

if (![self hasValidLogin] && (viewController != [aTabBar.viewControllersobjectAtIndex:0]) ) {

return NO;

}

return YES;

}

 

n         유저의 의한 탭의 변경을 감시

탭바에서 유저에의해 발생하는 변경에는 아래의 두가지가 있음

유저가 탭을 선택함

유저가 탭의 배치를 변경함

두경우 모두 탭바컨트롤러의 델리게이트에 보고됨

델리게이트는 UITabBarControllerDelegate프로토콜에 준비한 오브젝트임

델리게이트를 준비해서 유저에의한 변경을 추적하거나 변경에따라서 어플리케이션의

상태정보를 갱신가능

다만 표시나 비표시중의 뷰컨트롤러가 일반적으로 처리하는 작업을 실행하기위해 위의

통지를 사용하는건 안됨

예를들어 현재선택된 뷰의 스타일에 어울리는 스테이터스바의 디자인을 변경하기위해

탭바컨트롤러의 델리게이트를 사용하지 않음

위의 경우에는 커스텀뷰컨트롤러에서 처리하는게 최선임

 

n         탭의 커스터마이즈 금지

More뷰 컨트롤러에는 탭바에 표시하는 항목을 유저가 수정가능하게 하는 기능이 내장되어있음

여러 개의 탭을 가진 어플리케이션의 경우 유저는 위의 기능을 이용해서 바로 엑세스 가능한 화면과

엑세스하기위해 추가의 네비게이터가 필요하게되는 화면을 선택 가능함

아래 화면에서 왼쪽화면 상단의 edit버튼을 탭하면 오른쪽화면으로 자동으로 표시전환됨

이화면에서 새로운 항목을 탭바에 드래그함으로서 탭바의 내용을 교체하는게 가능함

대부분의 경우에는 탭의 배치변경을 유저에게 허가하지만 특정탭을 탭바에서 삭제하거나 특정 탭을

탭바에 배치하는 조작을 유저에게 허가하고싶지 않을경우에는 뷰컨트롤러오브젝트의 배열을

customizableViewControllers프로퍼티에 할당함 이 배열에는 배치를 변경해도 좋은 뷰컨트롤러의

서브셋을 포함함 위의 배열에 포함되지않은 뷰컨트롤러는 배치변경화면에 표시되지 않음

따라서 탭바에 표시되고 있는 뷰컨트롤러를 탭바에서 삭제하는 것은 불가능함

중요 : 탭바인터페이스에서 뷰컨트롤러를 추가하거나 삭제하거나하면 커스터마이즈가능한

뷰컨트롤러의 배열도 디폴트값으로 리셋되어 모든 뷰컨트롤러가 커스터마이즈가능한 상태로 돌아감

따라서 viewControllers프로퍼티를(직접 또는 setViewControllers:animated:메소드를 호출해서)

변경했을 때 계속해서 커스터마이즈 가능한 뷰컨트롤러를 제어할경우에는

 customizableViewControllers프로퍼티내의 오브젝트의 배열도 변경할 필요가 있음

 

n         뱃지의 변경

통상 탭바인터페이스의 탭의 외견은 그탭이 선택될 때 이외에는 변화하지 않음

다만 특정의 탭에 주의를 주고싶은 경우에는 (해당탭에 유저에게 보이고싶은 새로은 컨텐츠가

생긴경우 등) 배지를 추가하는 것이 가능

              뱃지는 탭의 구석에 표시되는 빨간 표시임 뱃지의 내부에는 개발자가 제공하는 특정

텍스트가 표시됨

              통상 뱃지에는 그탭에서 이용가능한 신규항목의 수를 표시하는 숫자가 표시되나 짧은

문자를 지정하는것도 가능함

 

              탭에 뱃지를 추가할때는 해당 탭바아이템의 badgeValue프로퍼티에 nil이외의 값을 할당함

              예를들어 뱃지내에 신규항목의 수를 표시하는 뷰 컨트롤러에는 아래와 같은 코드를 사용해서

뱃지의 값을 작성함

              if (self.numberOfNewItems == 0)

self.tabBarItem.badgeValue = nil;

else

self.tabBarItem.badgeValue = [NSString stringWithFormat:@"%d",self.numberOfNewItems];

              뱃지의 값을 표시하거나 변경하는 타이밍을 결정하는 것은 개발자의 책임임

              다만 뷰컨트롤러에 뱃지용의 값을 가진 프로퍼티가 포함된 경우에는 KVO통지를 사용해서 값의

              변화를 검출해서 그것에 따라 뱃지를 갱신가능함

             

u     탭바 컨트롤러와 뷰의 회전

n         탭바 컨트롤러는 디폴트로 세로방향을 서포트함 모든 루트뷰컨트롤러가 가로방향을 서포트하지않는한 가로방향으로 회전하지 않음 디바이스의 방향이 변화하면 탭바컨트롤러는 뷰컨트롤러의 배열에 문의해 1개라도 가로방향을 서포트하지않는 뷰컨트롤러가 있으면 회전 하지 않음

 

u     탭바와 풀스크린레이아웃

n         탭바 컨트롤러는 다른 대부분의 뷰컨트롤러와는 다른 방법으로 풀스크린레이아웃을 서포트함

스테이터스바나 네비게이션바의 배경에 뷰를 겹치고 싶을때는 커스텀뷰컨트롤러의 wantsFullScreenLayout프로퍼티를 YES로 설정함

위의 프로퍼티를 YES로 설정해도 탭바뷰의 배경에 뷰를 겹치는 것은 불가능

탭바 컨트롤러는 탭바의 배경에 뷰가 겹치지 않도록 항상 뷰의 사이즈를 변경함

 

 

 ps. 번역이 점점 빨라진다..ㅎ 코딩해야하는데 ㅡ.ㅡ

 

 

Posted by 김반장78
,

정말 오랜만에 본 영화..
보고나서 기분좋은 영화..
막 우연에 내용은 거의 환타지 이지만 이건 이거대로 매력이..ㅎㅎ
앵글도 재미있고 결정적으로 감독이름..깜짝!

'취미' 카테고리의 다른 글

주말 우에노 나들이..  (0) 2011.03.09
[영화] 아저씨  (0) 2011.02.28
[게임] 스타크레프트2 이정훈  (0) 2010.12.07
[게임] 몬스터헌터3rd 포터블  (0) 2010.12.06
메이지 신궁 산보..  (0) 2010.12.06
Posted by 김반장78
,