Friday, March 25, 2011

iphone 개발 수업 3주차

3/25
< Collection >
-객체들의 주소 저장
-크기가 가변
-검색, 삭제, 수정이 쉽다 (삭제, 수정, 추가 가능한 것들은 mutable이 들어간 클래스들).
NSSet <- NSMutableSet 이 상속 : 삽입한 순서와 저장 순서가 다름, 객체의 중복 저장이 안된다.
NSArray <- NSMutableArray 이 상속 : 포인터 배열, 삽입순서와 저장한 순서가 같다. 중복 저장 가능. 배열대신 사용하면 편리하다.
NSDictionary <- NSMutableDictionary 상속 :  key 값으로 value의 검색이 가능.
아래 그림은 12시 부터 시계 방향으로 NSSet, NSArray, NSDictionary 의 클래스 설명.


그 위의 객체에 이름이 objects로 끝나는 메소드를 사용하려면 마지막 인자로 반드시 nil 을 넣어줘야 한다.
NSDictionary의 key 는 중복이 안되는데 이는 사실 NSSet 으로 관리한다. 그렇기 때문에 key를 꺼낼때 NSSet 이 ordering 한 순서로 나온다.


클래스의 메소드가 - 이면 반드시 alloc을 해서 객체를 생성해서 사용해야 하는것이고, + 로 된 메소드는 클래스 메소드로서 객체 생성 없이 클래스 이름으로 사용할 수 있다. 그리고 + 으로 되어 있으면 autorelease 되어 진다. 그럼 뭘 사용해야 하느냐? 그건 선택 나름.


다시 한번 1주차의 마지막에 언급된 architecture와 life cycle 그리고 2주차의 view-based application 을 읽고 이해하길 바란다.
-------------------------------------------------------------------------------------------------


<Notification>
노티피케이션이 필요할 때 :
1.  2주차에서 마지막에 나온 예 MyPickerViewDelegate예제를 보면 InstaTwitViewController는 그 안의 객체인 MyPickerViewDelegate의 메모리 주소를 알고 있지만 반대로 MyPickerViewDelegate는 InstaTwitViewController 의 메모리 위치를 알지 못한다. 그렇기 때문에 InstaTwitViewController의 메소드를 사용할수가 없다. 이럴 때 노티피케이션을 사용하면 해결, 곧 사용하고자 하는 객체의 메모리 주소를 모를 때 사용
2. 이벤트 발생시 동시에 여러개 메소드를 호출할때
3. 호출되는 객체가 무엇이지 모를 때
예를 들어 MainWindow에 버튼이 있을때 그 버튼을 누를 때 객체 A,B,C 의 메소드가 동시에 실행되어져야 할때, 혹은 어떤 객체의 메소드가 호출되는지 모를때 노티피케이션을 사용한다.


이는 InstaTwitViewController객체가 NSNotificationCenter 객체에게 NSPickerView 선택시 알려달라고 요청함. 그러면 NSNotification이 백그라운드로 감시하다가 이벤트가 발생하면 InstaTwitViewContoller에게 알려준다.
그러면 통보하고자 하는 MyPickerViewDelegate에서 NSNotificationCenter에 통보하는 실행문을 넣는다. 그러면 MyPickerViewDelegate에서 특정 메소드가 호출될때 NSNotificationCenter에 통보를 하고 이 객체가 다시 InstaTwitViewController 객체에 NSNotification 객체(이 안에 정보가 다 있다)통보가 된다.


이 순서는 NSNotificationCenter 를 InstaTwitViewController객체 안에 생성하고 등록한다. 그러면 이벤트가 발생하였을 때 NSNotificationCenter가 InstaTwitViewController객체에게 통보를 하게 된다. 
생성 : NSNotification 은 어플 실행시 생성, 딱 하나만 생성, 리눅스의 데몬처럼 백그라운드로 실행, [NSNotificationCenter defaultCenter] 하면 NSNotification이 리턴된다.
등록 : [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(UiUpdate) name:@"name" object:nil userInfo:nil] ; self, 즉 자신 객체를 등록하고 이벤트 발생시 호출될 메소드는 UiUpdate라는 메소드이고(@selector는 메소드의 주소를 return)  이름은 name으로 하고 object는 nil 이다(object에는 주소를 넣을 수 있다, 이러면 NSNotificationCenter 객체가 이벤트 발생을 통보시, 즉 메소드 호출 시 그 주소를 인자로 넘긴다) 라는 의미.
통보 : [[NSNotificationCenter defaultCenter] postNotificationName:@"PickerViewDidChanged" object:self userInfo:nil] ; 통보하는 곳의 이름은 PickerViewDidChaged이고 self, 나 자신을 넘기고 더 넘기고자 하는 더 필요한 데이터는 없다라는 의미


원래 특정 이벤트의 발생을 감시하는 것은 UIApplication이 하는 일이였으나 UIApplication이 감시하는 이벤트는 시스템적인 이벤트, 그러니까 버튼이 눌리는 것 같은 이벤트, 그러나 나머지 이벤트 즉 시스템적인 이벤트를 제외한 이벤트는 NSNotificationCenter가 모니터링한다. 
-----------------------------------------------------------------------------------------------


속성을 다른 객체에서 사용하려면 1. set,get 메소드를 정의하거나 2. @property로 선언하거나 3. keyofvalue dictionary를 이용한다.


<Key Value Dictionary>
일반적으로 객체는 NSObject를 상속하는데 NSObject 클래스에는 NSMutableDictionary가 있어서 key 값으로 NSObject를 상속받은 클래스의 속성을, value로는 그 속성의 속성값(그러니까 속성안에 들어가 있는 값)을 가지고 있다. 이를 이용하면 코딩이 짧아짐.


그런데 이 key value observing이 꼭 대입이 되는 것은 아니다. 예를 들어 IBOulet으로 선언된 속성(즉 interface builder로 만든 view(xml에 정의된)의 주소를 넣을 속성)는 반드시 set,get 메소드를 만들거나 property로 선언해서 사용해야 한다.


사용방법 : NSObject 를 상속받은 클래스 MyCandle이라는 것이 있을때 keyofvalue Dictionary 를 사용하려면 [MyCandle valueForKey:@"candleState"];는 property로 사용할때의 MyCandle.candleState와 동일한 의미, [MyCandle setValue:NO forKey:@"candleState"];  는 MyCandle.candleState = NO; 과 동일.


<Key Value Observing>
NSObject를 상속받은 클래스 MyCandle의 속성과 keyofvalue dictionary는 MyCandle 이 감시하면서 그 두값을 같게 맞추는데 둘중 하나가 변했을때 알려달라, 곧 메소드를 호출해 달라. 그런데 Notification과는 달리 호출되는 메소드 이름(observeValueForKeyPath)이 정해져 있다. 그래서 메소드를 @selector로 해서 인자로 넘길일은 없다.


설정 : [MyCandle addObserver:self forKeyPath:@"candleState" option:NSKeyValueObservingOptionNew|NSKeyValueObservingOld context:nil]; candleState속성이 수정시 self, 즉 나 자신에게 수정된 값이 뭔지(NSKeyValueObservingOptionNew), 그리고 예전값이 뭐였는지(NSKeyValueObservingOld) 그리고 통보할때 nil(지금은 nil이기 때문에 아무것도 없다)을 전달하면서 알려달라라는 의미.
호출되는 메소드 : -(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context ; keyPath는 값이 수정된 속성이름, object는 통보자의 주소, change에는 바꾸기 전의 값과 바뀐후의 값이 dictionary(NSKeyValueChangeNewValue와 NSKeyValueChangeOldKey를 key로 갖는다)로, context 는 addObserver호출시 전달했던 인자.


등록시 option의 인자를 NSKeyValueObservingOptionInitial 은 원래 등록을 하면 감시가 시작되는 것이 아니라 등록하는 메소드(그러니까 등록 statement가 있는 메소드)가 끝나야 호출이 되는데(왜냐면 single thread이기 때문에) 이 option 을 사용하면 등록하는 순간 바로 monitoring 을 시작한다. 


notification과 key value observing 이랑 유사한데 그럼 언제 key value observing  를 사용하느냐? 값이 바뀌었을 때 통보할 때


이벤트가 발생했을때 호출되는 메소드는  return 값이 없다.

No comments:

Post a Comment