'Technique/iOS Dev'에 해당되는 글 14건

  1. 2011/07/27 [iOS] Document + 디렉토리/파일 (2)
  2. 2011/07/14 [Cocoa Design Pattern] 24.Bundle
  3. 2011/07/13 [Cocoa Design pattern] 23. Decorator
  4. 2011/07/12 [Cocoa Design Pattern] 22. Flyweight pattern
  5. 2011/07/12 [Cocoa Design Pattern] 21. Prototype
  6. 2011/07/12 [iOS] Create Directory
  7. 2011/06/18 [Cocoa Design Pattern]18ch. Responder Chain
  8. 2011/06/11 [Cocoa Design Pattern] 17ch. Outlet, Target, Action
  9. 2011/06/05 [iOS] UIImagePicker 호출 후, ViewDidLoad가 호출되는 이유.
  10. 2011/05/09 [iOS] HTML 파싱 - Java Script 와 UIWebView 이용하기

[iOS] Document + 디렉토리/파일

매일매일 개발하는 소스코드를 올리고 있습니다. 원래는 프로젝트가 끝나고 올리려고 했으나, 그러다 보니 까먹는 경우가 있어서 이렇게 매일매일 올리는 소스코드 입니다. 제가 쓴 소스코드의 문제 혹은 개선점이 있으면 언제든지 댓글 달아 주세요 


아이폰 어플은 Document 폴더에서만 작업을 할 수 있다는 장점아닌 단점을 가지고 있는데 그래서 대부분의 작업이 Document 에서 이루어지기 마련이러더라구요. 그래서 Document 폴더 path를 가져오는 함수를 따로 만들어 두고 해당 폴더 혹은 파일을 Document Path와 연결해 주는 코드입니다. Release는 알아서~

 


-(NSString*) GetDocPath //document 경로 반환

{

        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

        

        NSString *documentsDirectory = [paths objectAtIndex:0];

        

        return documentsDirectory;

    

}



-(NSString*) DocPathAppendDirecory:(NSString*) dic

{

    

    NSString * doc_path = [self GetDocPath];

    

    NSString * user_path = [doc_path stringByAppendingFormat:@"/%@",dic];

    

    return user_path;

}



 

저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/07/27 11:39
Trackback 0 : 댓글을 오로지 페이스북으로만.

[Cocoa Design Pattern] 24.Bundle



번들이란?

- 실행코드와 이미지, 사운드, 문자열, NIB 파일과 같은 리소스의 모음
- 각 리소스의 다른 버전을 동시에 저장, 사용자의 언어나 지역 설정에 따라 
  다른 버전의 리소스를 사용 가능하게 함.

- 자바의 JAR(Java ARchive), C# 프로그래밍의 리소스



패턴이 만들어진 동기

- 필요한 리소스가 내부 저장 공간에 여러버전과 여러 파일로 구성되어있는 경우에도,
   한 곳에 모을 수 있도록 한다. 

- 실행코드와 리소스를 동적으로 로드 할 수 있도록 유연한 플러그인 기법을 구현한다. 

패턴으로 문제 해결

- 번들 = 디렉토리 : 코드, 리소스등을 파일시스템 디렉토리를 통해서 만든것 
- 계층구조로 구성되어 있다. 

구성
* Contents
- 모든 번들 리소스 담고 있다. 
  
  * Info.plist : 번들에 대한 정보, Unique 하게 식별 가능한 번들 식별자 문자열을 저장하고 있음. 
  * Mac OS : 애플리케이션 실행 파일 
  * Resources : nib 파일, 그래픽, 문자열, 리소스 파일, 지역별버전(.lproj) 폴더 


- 사용자에게 하나의 파일처럼 보이게 하는 효과 있음. (패키지)
- 그러나 언제든지 파인더를 통해서 내부 파일을 볼수 있다. 


* 번들의 장점 
- 번들은 패키지이자, 표준 파일 뷰어로 볼수 있기 때문에 편집이 가능하다. 
- 이동 복사, 삭제가 가능
- 순진한 사용자는 내부 파일을 볼 일이 없어서 변경의 가능성이 줄어든다. 
- 다국어 , 지역화 지원. 원치않는 지역화 리소스 쉽게 제거 
- 여러버전 저장 및 실행코드의 여러버전을 포함 할 수 있음. 
- 특정기능에 의존적이 아니라, 서버 또는 다양한 파일시스템에 저장할 수 있다. 

*배포 

- CD : 번들을 CD로 복사 
- 네트워크 : 문제 야기의 가능성 있음, 번들의 일부만 다운로드 받을 가능성
- DMG : 디스크이미지로 생성, 이동식 디스크로 마운트 됨 

* 항상 번들을 사용해야하는 것은 아니다. (독립형 커맨드라인 프로그램 개발 가능)

- 번들 제작시, 자동으로 XCode가 이미지, 사운드 파일등과 같은 표준 리소스를 자신이 속하는 곳에 위치시킨다. 

 
코코아 사용 예제

- 번들을 NSBundle 클래스로 캡슐화 
- 하나의 어플은 적어도 하나의 번들을 가지며, 메인 번들은 [NSBundle mainBundle]을 통해서 접근 가능함. 
- NSApplication - mainBundle - load nib file. 

- 동적으로 실행코드와 리소스를 불러올 수 있다. (375p)

- 현재 언어와 지역 설정에 적합한 버전의 경로 반환
- 지정된 지역화에 해당하는 리소스 버전에 대한 경로 반환 하는 등의 리소스 접근 관련 메소드를 제공함. 

- NSBundle은 Foundation 프레임워크에 소속되어 있지만, ApplicationKit 프레임워크에서 카테고리를 통해서 
  NSBundle을 여러 방면으로 확장한다. 

* 메인 번들 뿐만아니라 실행코드를 담고 있는 번들에 접근하는 것도 가능함. (I don't know)


동적으로 실행코드 로드하기

- 번들은 어플리케이션 구동시 자동 로드된다. 
- 번들을 동적으로 불러들이려면 

+(NSBundle*)bundleWithPath:(NSString*)fullPath : NSBundle 인스턴스 생성

377p 예제 : myPlugin.bundle 을 로드

- 번들 인스턴스 만들고 캡슐화 해도 자동 로드되지 않는다. 해당 코드를 사용할필요가 있을시까지 기다린다. 
- 강제로 실행코드를 어플리케이션에 링크하게 하려면, NSBundle의 load 메소드 또는 principalClass 메소드 사용 (I don't know) 



패턴 사용 결과  

-  실행코드와 관련 리소스를 한곳에 두어, 어플리케이션 구동시, 리소스 경로를 하드코딩 하지 않아도 된다. 
-  리소스와 코드를 저장시, 디렉토리 계층 사용의 장단점
    : 사용자가 해당 어플리케이션의 번들의 내용물을 보고 편집 할수 있다는 점
    : 그러나, 다른 사용자가 어플리케이션을 언제든지 확인, 수정,삭제가 가능하다는 것.  

저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/07/14 17:48
Trackback 0 : 댓글을 오로지 페이스북으로만.

[Cocoa Design pattern] 23. Decorator

 



데코레이터란?

- 서브클래싱을 통해 기능을 추가하는 대신 컴포지션을 통해서 공통적으로 재사용 가능한 기능을 객체에 추가
- 서브 클래싱은 컴파일 단계에서 정의해야 하지만, 데코레이터는 런타임 단계에서 추가 및 구성 가능함. 

ex) NSScrollView 

패턴이 만들어진 동기

- 기존 객체에 여러가지 기능을 추가하고 싶음. 그러나, 클래스 수의 증가가 문제임. 
- 서브 클래스 = is - a 관계

Text - RulerText - BorderedRulerText

- 상속을 통해서 필요한 기능을 확장해 나가는 형태, 특정 기능을 위해 계층이 복잡해짐. 
- 다중 상속을 통해서 간단한 계층을 시도하지만,
  다중상속은 클래스의 수를 줄이는것 보다는 상속 관계를 바꿔줌. 



데코레이터 패턴의 목표 

1. 상속 대신 조합으로 어플리케이션의 동작을 사용자화 한다. 
2. 런타임의 유연성 제공, 런타임 상태에서 기능을 동적으로 추가 및 제거 가능
3. 클래스 대신 각각의 인스턴스에 기능을 추가한다. 
4. 필요한 클래스의 수를 줄여준다.



패턴으로 문제 해결

- 조합(Composition)은 Has - a 관계를 정의한다. 데코레이터 패턴은 암묵적으로 has-a 관계를 사용한다. 

ex) 
NSClipView 인스턴스가 자신의 도큐먼트 뷰를 데코레이트한다. 
= NSClipVIew 인스턴스가 도큐먼트 뷰를 소유한다 
- 조합은 런타임시에 구성되고, 동적으로 바꿀수 있다


* NSScrollView 
- setDocumentView 메소드를 제공해서 내장된 클립뷰의 도큐먼트 뷰를 설정하도록 제공 
- 도큐먼트 뷰는 NSView의 서브클래스라면 가능 즉, 사용자 정의의 커스텀 뷰도 가능하며, 숫자 제한이 없다. 



코코아 사용 예제


일반 적인 데코레이터 패턴의 사용 예제 : http://mrhook.co.kr/79


- 이 패턴은 주로 MVC의 뷰 단계 에서만 주로 사용된다. 

- 예외도 있다. 

NSAttributedString 
- NSString + (폰트, 문단 스타일, 이미지 내장 등등) : 속성을 데코레이트 
- 자신이 꾸미는 문자열을 수정하지 않는다. 단지, 그 문자열과 추가 정보만을 함께 저장함. 

365p. 표23.1 중요한 코코아 데코레이터 클래스 

액세서리 뷰 

-
코코아 표준 사용자 인터페이스 패널 : 사용자가 만든 데코레이터 추가 가능하다. 

NSSavePanel, NSColorPanel 등등
- setAccessoryView 메소드 제공 : 해당 패널에 원하는 액세서리뷰를 표시 할수 있음.  
- 표준 패널은 다양한 패널 클래스를 서브 클래싱 하지 않아도 기능을 추가 할 수 있다 


* OS X 10.5 부터 NSPrintPanel과 NSPageLayout 클래스에  addAccessoryContoller 메서드로 액세서리뷰를 관리 하는 새로운 방식 제공함. 

- 액세서리 뷰를 직접 사용하는 것에서 액세서리 뷰 컨트롤러를 사용하게 변화 
- MVC 패턴의 일관된 사용을 장려, 액세서리 뷰와 어플리케이션 로직 사이에 위치한 컨트롤러 코드를 어디에 구현해야 하는지 명확히 함. 

패턴 사용 결과
 

- 객체지향의 상속관계는 강력 그러나, 의존성의 원인임.
- 컴파일시 정적으로 설정되고, 서브클래스의 모든 인스턴스에 영향을 준다.

- 컴포지션은 보다 유연한 대안을 제공함.
- 객체를 런타임시 확장하는것은 더 동적이고, 클래스가 아닌 인스턴스 단우에서의 적용이 가능하다.
- 다수의 클래스 사용을 하지 않고도 더 컴포지션으로 다수의 기능을 추가하는 것이 가능하다. 

- 다른 프레임 워크 에서는 데코레이터가 꾸미는 객체와 동일한 인터페이스를 갖도록 요구함. 
- 코코아에서는 제약이 없음. 
 

저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/07/13 17:34
Trackback 0 : 댓글을 오로지 페이스북으로만.

[Cocoa Design Pattern] 22. Flyweight pattern



22. 플라이 웨이트 패턴 

플라이웨이트 패턴이란?
- 객체를 사용할 때 필요한 메모리의 양과 프로세서 오버헤드를 최소화시킨다. 
- 인스턴스 공유를 가능하게 하여, 실제 인스턴스의 수를 줄여준다. 

패턴이 만들어진 동기

- 비 - 객체 데이터를 캡슐화하여 객체가 필요한 컨텍스트에 그 데이터를 사용할수 있게 한다. 
- 많은 수의 인트선트가 필요할때 저장공간 요구를 줄여준다. 
- 다른 객체의 대역으로 행동한다. 


패턴으로 문제 해결

스프레드 시트의 경우 
- 행과 열의 모든 셀을 각각의 인스턴스로 표시할 것인가?
- 공유가능한 인스턴스 : 셀이 비어 있는 경우, 동일한 값을 가지고 있는 경우 (SpreadSheetCell)
- 포맷 정보의 분리 (SpreadSheetCellFormat)

- 인스턴스 공유를 통해서 총 사용하는 인스턴스의 수를 줄일수 있다. 
- 인스턴스에 저장된 정보의 일부를 따로 클래스화 함으로써 저장을 최소화 시킨다. 




코코아 사용 예제

3가지 목적 :

1. 비-객체 값을 캡슐화 
2. 메모리 사용 줄이기 
3. 다른 객체의 대역으로 사용



비-객체 값을 캡슐화 

* NSNumber
 - char, int, long, float 와 같은 숫자형 데이터 타입, bool 과 같인 데이터 타입도 객체형으로 전환 가능
 - NSNumber 의 슈퍼클래스인 NSValue 가 비객체 데이터 타입에 객체 래퍼를 제공. 

* NSDecimalNumber, NSDate, NSString 등과 같은 클래스 모두 비 객체 값이나 데이터 구조를 감싼다. 


저장공간 요구 감소 

NSNumber 인스턴스 공유 
- 최근에 사용한 혹은 자주 사용하는 NSNumber 인스턴스는 캐시에 저장한다. 그리고 요청이 오면 꺼내서 반환함. 
- 인스턴스 공윤는 해당 클래스가 수정 불가능 할때만 가능하다. 

NSFont, NSColor 역시 수정 불가능한 인스턴스를 캐시하고 재사용함. 

NSCell 
- NSCell 의 인스턴스는, NSString, NSImage 의 포인터와 같이 상대적으로 단순한 값만 저장. 
- NSView 가 80바이트를 사용함에 비해 NSCell은 20바이트 사용함. 

- NSTableView와 NSMatrix 에서 사용함으로써 저장공간 감소 효과 


다른 개개체의 대역으로 사용 

- 좀더 무거운 다른 객체의 임시 자리표시자 역할 수행

- NSTextView : 텍스트 표시와 입력을 다루는 클래스 
- 그러나, 배치 저장, 철자확인 과 같은 다양한 텍스트 관련 기능에 대한 부분은 다른 클래스와 협력한다. 

- 복잡한 텍스트 관리 시스템의 플라이웨이트 자리표시자로 NSCell을 사용 


패턴 사용 결과  

- 패턴을 사용하는 것은 늘 디자인을 복잡하게 한다. 
ex) C 언어의 데이터 타입과 NSNumber 사이에서의 데이터 변환 

- 분명히 저장공간과 성능의 최적화 효과가 있다. 
- 그러나, 만약 NSCell을 NSView 대신에 사용 했다면, 코어 애니메이션과 같은 고급 뷰 기능을 사용할 수 없다. 
- 성능적인 부분에도 문제가 있을수가 있다. 

- 플라이웨이트의 사용이 복잡도를 증가
- 개발하려는 어플리케이션에서 저장공간과 성능의 최적화에 대한 이슈가 있다면 사용해라. 아니면 권장하지 않는다. 
   


 
저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/07/12 18:02
Trackback 0 : 댓글을 오로지 페이스북으로만.

[Cocoa Design Pattern] 21. Prototype


프로토 타입이란?
- 기능 구현을 위해 복사해서 사용하는 객체
- 기존 객체를 복사해서 사용하는 것은, 새 인스턴스를 생성하는 것 보다 더 유연하다.
- 객체간의 강한 의존성 관계를 피하도록 해준다. '


패턴이 만들어진 동기 
- 새로 인스턴스를 생성하는 객체와 해당 객체의 타입간의 의존성을 최소화 
- 생성되는 객체의 종류에 대한 정보를 컴파일시 지정하지 않고, 런타임시 조절할 수 있도록 한다. 

패턴으로 문제 해결
- 핵심기능 : 복사 될수 있다는 것 
- NSCopying, NSCoding 프로토콜 제공



* NSCopying protocol  - copyWithZone  메소드
- 메소드를 수신하는 객체와 동일한 상태의 객체를 반환해야한다. 

1. Shallow Copy
- 복사되는 객체와 동일한 값을 저장한다. 
- 원본을 가리키는 또 다른 포인터를 만드는 것, 포인터 복사 

2. Deep Copy
- 원본 객체에 저장된 값의 실제 복사본을 저장


* 프로토 타입 패턴은 딥 카피를 제공하는 객체와 가장 잘 동작,
  완벽히 독립적인 사본이 필요한 경우가 있기 때문임. 

ex) IB Library의 경우, 복사된 객체는 인터페이스 빌더가 종료된 후에도 동작해야함. 

그러나, 대부부의 코코아클래스는 NSCopying 프로토콜을 구현해서 Shallow copy를 반환함. 

* Deep Copy가 쉽지 않은 이유
  : 참조하고있는 객체중 Shallow copy를 반환하도록 구현되어 있다면, 섞이게 된다. 



* NSArchiver, NSUnarchiver class 는 쉬운 Deep Copy 방식을 제공 
- 복사되는 객체와 그 객체 내에서 참조하는 모든 객체들이 NSCoding Protocol을 따른다면, Deep Copy 반환
- 347p 예제 : 아카이빙 한 후, 언아카이빙하는 것은 딥 카피를 만들기 위한 억지 기법

-  IB 라이브러리에서 객체를 복사할때 사용하는 방식. 
- " 작업중인 .NIB 파일에 객체를 드래그 해서 옮기면, 객체는 기존의 라이브러리 인스턴스르에서 먼저 아카이브 되고나서 언 아카이브하여 추가 편집할 사본을 생성한다. 그리고 .NIB 파일이 저장될 때, 객체들은 다시 아카이브된다. .NIB파일이 로드되면 파일에서 객체가 언아카이브 되어서 IB에 복원된다."


* NSCell - NSCopying프로토콜의 다른 기법인 NSCopyObject() 함수 사용함. 

NSCopyObject : 원본이 차지하는 메모리를 그대로 복사해서 Shallow Copy 생성함. 
이후, NSCell의 -copyWithZone이 원본에 저장된 속성이 참조한느 객체에 copy 메시지를 보내 복사함. 
NSCell은 Shallow copy 와  Deep Copy를 섞어 씀. 


코코아 사용 예제 


- IB 라이브러리 객체는 모두 프로토타입 : 객체를 복사함으로써 IB를 재 컴파일 하지 않아도 확장이 가능함. 
- NSMatrix 클래스에서는 프로토타입 NSCell 인스턴스를 사용함.
- 매트릭스에서 행, 열 추가가 있을시에는 필요한 만큼 프로토타입 셀을 복사한다. 
- NSMatrix 클래스는 자신이 사용하는 셀에 의존하지 않는다. 

349p
NSCell의 서브 클래스 MYLabeledBarCell에서 정의한 barValue 역시 NSCopyObject()에 의해서 상속된 변수들과 함께 자동으로 복사된다.  



 

* NSCopyObject() 함수는 포인터를 저장하지 않는 클래스에만 사용해야 한다. 
* NSCell의 NSCopyObejct() 사용은 NSCell의 객체를 가리키는 인스턴스 변수를 추가하는 서브클래스 생성하기를 어렵게 만든다. 

패턴 사용 결과


- 객체를 복사하는 작업이 새로운 인스턴스를 생성하는 것 만큼 시간과 비용소요(절약되는 것이 아님)

- NSMatrix 의 경우, 필요한 셀의 수가 줄어들더라도 프로토타입의 셀 사본을 거의 릴리즈 하지 않는데, 다시 필요할 경우 유지하고 있는 사본을 사용한다. 그러나 메모리가 필요하지 않는 사본을 저장하는데 소비된다는 측며에서 보면 단점이다.

 
- 프로토타입 패턴 주의사항 : 프로토타입 객체를 지원하는데 필요한 행동을 문서화 하는 것이 필요함. 
















































 
저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/07/12 13:50
Trackback 0 : 댓글을 오로지 페이스북으로만.

[iOS] Create Directory

디렉토리를 생성하는 코드입니다. 일단 도큐먼트 경로를 가져와서, 해당 생성하려는 폴더 이름을 붙여주는 방식입니다. Objective-C 에서 파일 및 디렉토리 처리를 담당하는 부분은 NSFileManager 에서 담당하기 때문에 관련 된 사항이 있으면 그 부분을 보면 될것입니다. Release는 알아서 하시길. 

This code is that create directory in document path. First, get document path in app and add folder name. In Objective-C, the part of file & directory processing   is responsible to NSFileManager class. so that you find NSFileManager Document. 



    //create directory 

    NSString *temp_folder = @"temp";

    

    

    NSString *document_path = [self returnDocumentPath];

    

    NSString *new_directory_Path = [document_pat
    stringByAppendingFormat:@"/%@",temp_folder];

    

    NSFileManager *file_manager = [[NSFileManager alloc]init];

    bool IsSuccess = FALSE;

    

        

    IsSuccess = [file_manager createDirectoryAtPath:new_directory_Path withIntermediateDirectories:FALSE attributes:nil error:nil];

    

저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/07/12 00:38
Trackback 0 : 댓글을 오로지 페이스북으로만.

[Cocoa Design Pattern]18ch. Responder Chain

코코아 디자인 패턴 18장. 리소폰더 체인

리스폰더 체인이란? 

 
- 코코아 그래픽 애플리케이션의 핵심적이고 중요한 요소
 - 책임사슬 패턴(Chain of Responsibility)

패턴이 만들어진 동기 

 
- 사용자 이벤트의 정확한 전달
- 현재 활성화 되어 있는 인터페이스 객체는 무엇이고, 어떻게 액션 메시지를 전달할 것인가. 

패턴으로 문제 해결

책임사슬패턴은 메시지의 전송자와 수신자 객체 관계를 최대한 분리시키는 것이 목적 
- 수신객체들이 연결 리스트로 구성되어 있고, 각 객체들이 메시지를 무시 혹은 수신하는 순차적인 시스템 

용어 

 
NSResponder
 
- 사용자 입력을 다룰수 있는 개체들은 모두 NSResponder의 서브클래스
 - 키보드, 마우스, 터치등의 상자 입력에 대응하는 역할
 - NSWindow, NSView, NSViewController, NSDrawer 등이 모두 NSResponder의 서브 클래스

 * 사용자의 초점이 어디에 맞춰져 있는지 자동적으로 코코아 프레임워크에서 기억.

 Key Window
 
- 입력을 받는 윈도우를 키 윈도우

Main Window
 
- 현재 초점이 맞춰져 있는 문서 창을 메인 윈도우

* 키윈도우와 메인 윈도우가 하나의 인터페이스 인 경우도 있지만, 서로 다른 인터페이스인 경우 있음.

NSApplication 의 역할 

 
- 애플리케이션 객체는 키 윈도우와 메인 윈도우를 항상 기억하도록 되어 있음.
 - keyWindow, mainWindow 를 통해서 해당 개개체에 대한 레퍼런스를 얻을수 있음. 

FirstResponder
 
- 현재 초점이 맞춰져 있는 뷰를 지칭함
 - 리스폰더 체인의 첫번째 객체
 - -firstResponder : 첫번째 리스폰더에 대한 레퍼런스 리스폰더 체인
 
- 다수의 수신 객체가 엮여져 있는 형태로 액션 메시지의 대해서 각 노드가 ignore 또는 accept 를 하는 구조
 - nextResponder : 주어진 수신객체의 다음 수신객체를 반환
 - setNextResponder : 다음 객체를 재설정하고 싶을때 사용

 - 일반적으로 주어진 뷰의 다음 수신객체는 슈퍼뷰(super view)
 - 윈도우 내 콘텐츠 뷰의 다음 수신객체는 윈도우. 
 - 윈도우의 다음 수신 객체는 nil. 
 - 리스폰더 체인의 마지막 노드가 윈도우 창이다. 

 예외) NSWindowContorller에 의해서 제어되고 있는 윈도우 창은 컨트롤러가 최종 수신 객체임 
 예제) 304p
 
 - 모든 리스폰더 체인은 nil로 끊어지기 때문에, 무한 루프의 위험성이 없다.
 - 윈도우가 여러개인 환경에서는 모든 각각의 윈도우가 리스폰더 체인을 가짐.
 - 윈도우 내 사용자의 선택이 바뀔때 마다 리스폰더체인이 업데이트 됨.

 - acceptResponder : 새로운 수신객체가 될 객체에게 전달
 - resignFirstResponder : 현재 리스폰더에게 FirstResponder를 반환하라는 메시지를 전달
- becomeFirstResponder : 새로운 첫번째 리스폰더가 될 객체에게 전달 - 키보드가 마우스 입력의 경우,

NSApplcation 객체가 입력을 NSEvent 객체로 변환한 다음. 리스폰더 객체를 찾는다.
 - 리스폰더 체인은 계층구조를 이용해서 FirstResponder를 찾아냄. 


확장된 리스폰더 체인

 
- 키 윈도우와 메인 윈도우의 리스폰더 체인을 아우르고, 또한 공용의 NSApplication 인스턴스와
   NSDocumentController 인스턴스를 포함한 확장 리스폰더 체인.

 - nil을 target을 갖는 메시지를 담당.
 - 메뉴 항목의 경우 다양한 종류의 메시지 구현이 쉽지 않다.
 - 키 윈도우와 메인 윈도우의 리스폰더 체인 만으로는 이벤트 핸들링이 불충분한 경우.
 - 확장된 리스폰더 체인의 순서

 1. 키 윈도우의 리스폰더 체인의 첫번째 리스폰더를 처음 시도. 
 2. 뷰 계층 구조의 리스폰더 체인을 따라 메시지 전달.
 3. 윈도우 객체를 시도
 4. 윈도우의 델리게이트를 시도(주로 NSDocument의 인스턴스)
 5. 만약, NSWindowController가 있다면 시도.  
 6. 1-5의 순서를 메인 윈도우에 적용 
 7. NSApplication 객체와 그의 델리게이트를 시도
 8. NSDocumentController 가 있다면 시도. 

예제) 306P - 307P

- 키 윈도우 == 메인윈도우의 경우, 확장된 리스폰더 체임의 검색 길이는 짧아 짐. 
- 인터페이스 빌더 이용시, 컨트롤을 첫번째 리스폰더에 연결하면, 실제로는 해당 액션에 대한 target를 nil로 지정.
- 어떤 컨트롤의 액션메시지를 확장된 리스폰더 체인에 전달하고 싶다면 action의 target을 nil로 지정하면 됨. 

[mycontrol setAction:@selector(terminate)];
[mycontrol setTarget : nil];

NSApplication의 -sendAction:to:from: 메소드에서 확장된 리스폰더 체인으로 보내는 방법 

   [NSApp sendAction:@selector(terminate) to:nil from:self];

메시지를 보내지 않으면서 어떤 객체가 대응하도록 되어 있는지 알고 싶다면, 

     id myTarget = [NSApp  targetAction:@selector(terminate) to:nil from:self];

확장된 리스폰더 체인 탐색하기
 
 - 리스폰더 체인의 정보를 출력해서 볼수가 있음 : 308p 예제 


리스폰더 체인에 객체 삽입하기 

 
- 수동으로 객체 삽입 가능 : NSResponder 의 서브클래스면 가능함.
 - 뷰와 뷰의 superView 사이에 뷰 컨트롤러를 삽입해야 하는 경우

 NSResponder * theNextResponder  = [myview nextResponder];
[myview setNextResponder : myViewController];
[myviewController setNextResponder:theNextResponder];

 - 뷰 컨트롤러가 뷰 다음에 위치하게 되면, 그 뷰가 활성화될 경우에만 작동하게 됨. 
  (주어진 윈도우가 하나 이상의 뷰/뷰 컨트롤러 짝을 가지고 있는 경우를 위해서임)
 
 - 리스폰더 체임의 어느위치에 객체를 삽입하느냐에 따라 컨트롤러가 언제 어느 식으로 사용자 입력에 대응하도록 할 것인지를 조정 할 수 있음


 
리스폰더 체인 활용하기 

 
- 이미 존재하고 있는 리스폰더 체인을 사용하는 것이 가장 편함. 
- 자동검열 기능, 텍스트의 선택여부에 따른 액션 지정 등은 컨텍스트에 민감한 행동 기능을 리스폰더 체인을 통해서 단순화 시킬수가 있다.

코코아 사용예제 

 
- 코코아에서 리스폰더 체인은 핵심임. 
 - 사용자 입력은 NSApplication 객체가 책임을 지고 적합한 리스폰더 체인에게 전달됨.
 - 키 윈도우와 메인 윈도우의 리스폰더 체인을 아우르고, 또한 공용의 NSApplication 인스턴스와
    NSDocumentController 인스턴스를 포함한 확장 리스폰더 체인.

 - nil을 target을 갖는 메시지를 담당.
 - 애플리케이션의 상태에 따라 목표물이 동적으로 좌우되는 액션을 구현해야 한다면, target을 nil로 지정.
 - 복사하기/붙여넣기, 눈금자 조절기능, undo/redo 등의 기능이 확장 리스폰더 체인의 대상
 - 컨텍스트 인식 메뉴들도 리스폰더 체인을 많이 활용  


 패턴 사용 결과

 - 다양한 사용자 입력을 처리 할수 있는 유연성을 제공함.
 - 다양한 액션 기능을 최소한의 코드로 구현 가능함.
 - 리스폰더 체인을 활용해서 애플리케이션에 특화된 컨텍스트 인식기능의 구현 가능.  
저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/06/18 07:47
Trackback 0 : 댓글을 오로지 페이스북으로만.

[Cocoa Design Pattern] 17ch. Outlet, Target, Action




아웃렛 타깃 액션

특화된 기능을 어플리케이션에 추가하고 싶다면?
 
방법 1 : 서브클래스를 구현하는것
-        단점 1: 특화되는 기능에 따른 서브 클래싱의 수가증가함
-        단점 2: MVC 시스템의 각 영역을 침범하게 됨
-        단점 3: 다른 인터페이스에서 비슷한 기능을 요구할시, 각각의 서브클래스에서 비슷한 코드가 생성되는 
                      중복성이 생김.
 
방법 2 : 객체 기반의 프레임워크에서 사용하는 사용자인터페이스에 고유한 ID를 부여하는 방식으로
           해당 ID에 따른 해당 객체를 매칭시키는 방식
 
-      단점 1: 객체와 컨트롤러 간의 ID 목록을 동일하게 동기화, 의존성 발생
-      단점 2 : 해당 ID에대한 관리 및 매칭을 위한 비용이 발생
 

코코아의 아웃렛, 타깃,액션 디자인 패턴을 이용하면?
-      인터페이스 구현 간소화
-      유연성과 유용성 증대



패턴이 만들어진동기
 
-      사용자 인터페이스 객체를 직접 설정 및 조정가능
-      액션 정의 가능
-      특화된 액션과 거리를 두어 의존성이 일어나지 않도록 한다.
-      코드 중복 X
-      컨텍스트 인식 가능
 
 
패턴으로 문제해결
 
아웃렛(Outlet)
-      사용자 인터페이스 객체에 대한 레퍼런스를 포인터로 저장해 놓은 인스턴스 변수
-      인터페이스 빌더, 런타임시 설정

-      명명법
       : IBOutlet
       : 인스턴스 변수 타입이 id 이고, 첫글자가 _ 이 아닌 경우
  
ex)
Id sampleOutlet ;
IBOutlet *smapleMatrix ;
Id _sambleVar; //not outlet
 
 
타깃(Target)

-      특별한 아웃렛의 종류중 하나
-      액션 메시지를 처리하는 장소(를 지정)
-      NSControl, NSActionCell,NSMenuItem 클래스에서는 target 아웃렛과 action이라는 인스턴스 변수 제공
 
-      nib 파일 로드시, 아웃렉 연결과 타깃 – 액션간의 연결도 이루어 진다.
-       프로그래밍 상에서 target, setTarget 메서드로설정가능
 
액션(Action)

-        void를 반환하며 객체 하나를 인자로 받는 메서드라면 액션 메서드로 가능 
-        프로그래밍 상에서 action, setAction 메서드로설정가능

-        @selector 로 액션메서드가 취급되어 저장됨.
         : objective-c 에서 메시지를 위한 고유 식별자
         : 컴파일러 지시자중 @selector() 사용
 
         [someControl setAction:@selector(copy:)];
 
       : NSSelectorFromString, NSStringFromSelector
 
-      각 클래스 마다 생성되는 이벤트의 경우가 다르다. (touch,slide.. etc)
 
-      액션메시지는 NSApplication 의 –sendAction:to:from: 메서를 사용해서 메시지 전송됨.
 
-      NSApplciation은 싱글톤 패턴의 예)

       [NSApplication sharedApplication];
 
sendAction : @selector 로 보낼 메시지를지정
to : 어디로 보낼것인지. (target)
from : 메시지를 전달하는객체로 메서드로 전달될 객체
 
  

* 인터페이스 객체와 아웃렛의 연결

NSNibOutletConnector 클래스
-      아웃렛과 다른 객체간의 연결관계 정보 저장
       
nib 파일로 부터 인터페이스 객체 로드
       establishConnection() 실행 : 인터페이스 객체와 연결되어야 하는 아웃렉을 찾아서 기록
       
아웃렛 접근자 메서드가 있으면, 런타임시, 해당 접근자찾아서 호출
 
287p 예제
 
 
액션과 리스폰더 체인
 
NSApplication 의 역할
 
만약, sendAction:to:from: 에서 to:nil 이라면?
-      리스폰더 체인을 사용하여, 어느 객체가 처리할수 있는지검색후 전달.
-      현재 컨텍스트에 민감하게 되는셈.
-      리스폰더 체인중 제일 먼저 수신가능한 객체(firstResponder)에게액션 메시지 전달
-      만약, 수신가능한 객체가 없다면 비프음을 냄
 
* 코코아의 자동메뉴 항목/컨트롤 검증기능
 
-      송신 객체가 활성화되어 있는지를 체크함.
-      동일한 리스폰더 체인 사용
-      만약 메시지를 처리할수 있는 객체가 없다면, 
        이미객체를 비 활성화 시키고, 액션메시지를 보낼수 없도록 차단한다.
 
-      모든 클래스가 제공하는 action을 자동으로 찾아서인터페이스 빌더에서 사용할 수 있도록 제공 한다.
-      IBAction 전처리 매크로 , void 혀응로 변환됨.
-      파라미터가 꼭 id 형일 필요는 없음.
 
-      (IBAction)volumeSliderDidChange:(NSSilder*) sender
 
 
코코아 사용 예제
                   
아웃렛/타깃/액션과 MVC 패턴
 
-      오직 View 와 Controller와연결되어 있음.
-      모델 서브 시스템은  연관성이 거의 없음.
 
-     뷰의 특정 인터페이스 객체에 대한 액션을 Controller에서처리하도록 액션 메서드를 지정하고, 해당  
       Controller의 액션 메서드에서는 완전 독립적인 모델 시스템을 통해서작업을 수행한다.
 
 
패턴 사용 결과
 
-      기존의 수동적인 이벤트 핸드럴 기반의 시스템의 대체자 역할
-      고유한 ID로 관리할 경우의 비 효율적인 부분이 없다.
-      유연성이 증가.
-      인터페이스 설계를 그래픽으로 가능
-      인터페이스와  코드 연결을 위한 추가 코드가 필요 없다.
-      서브 클래스를 작성하여 사용하는 경우가 거의 없다. 
        때문에의존성이 줄어들고 유지/관리 해야하는 코드의 분량이 줄어 든다.
저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/06/11 17:02
Trackback 0 : 댓글을 오로지 페이스북으로만.

[iOS] UIImagePicker 호출 후, ViewDidLoad가 호출되는 이유.

최근 개발하고 있는 프로젝트에 겪었던 기 현상을 먼저 이야기 하자면 이렇다. 

ViewController 에서 UIImagePicker 를 호출해서 카메라 혹은 사진 앨범을 띄워서  선택을 하고 나서 ViewDidLoad 함수가 호출되는 현상을 목격했습니다.  

맥부기에 물어본 결과. 

 

윤찬파파(azone)
정회원 
2011.06.01 13:56
uiimagepickercontroller 를 사용하시면 (modal 로 띄우겠죠?) 대부분 memory warning 이 발생합니다. 
memory warning 이 생기면 여러가지 떠 있는 viewcontroller 들 중에 보이지 않는 controller 들의 viewDidUnload 를 호출합니다.
그리고 카메라를 다 사용하고 나면 (dismiss 시키게되면) .. 원래 controller 의   viewDidLoad 를 호출합니다.

그래서 viewDidLoad 가 호출되는 것처럼 보일 수 있습니다.

UIImagePickerController 를 띄우는 Controller 에서 viewDidUnload  에서 적절한 처리를 해 주시면 됩니다.
 
이렇다고 하네요, 결과적으로는 카메라 호출로 인해서 생기는 "메모리 경고"로 인한 ViewDidLoad의 문제 였습니다. 확인해 본 결과 실제로 카메라 혹은 포토라이브러리 호출로 인한 메모리 경고시에는 해당 뷰가 ViewUnload가 호출되고 dismissModal 후 ViewLoad가 다시 호출되는 것을 확인하였습니다. 때문에 한번만 호출된다는 개념을 가지고 접근해서 코드를 ViewDidLoad 에 작성해서는 안될것 같습니다. 그리고 이런 호출이 있는 경우를 잘 체크해서 코드를 작성해야 할것 같습니다.  
저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/06/05 01:04
Trackback 0 : 댓글을 오로지 페이스북으로만.

[iOS] HTML 파싱 - Java Script 와 UIWebView 이용하기

HTML 파싱에 관한 부분은 한우찾기 1.0 및 2.0 에 걸쳐서 가장 핵심적인 부분이라고 할수 있습니다. 총 2가지 방법을 사용해서 웹 사이트에 있는 HTML 데이터를 파싱해서 가져오고 있습니다. 

1. Java Script + UIWebView 를 이용하는 방식

2. xpath 를 이용하는 방식



이 두가지는 장단점이 있기 때문에 적절하게 사용해야 할것 같습니다. 일단 이번 포스팅에서는 첫번째, 즉 Java Script 와 UIWebView 를 이용해서 개발하는 부분을 보도록 하겠습니다. 

자바스크립트로 파싱을 한다?

HTML 로 파싱을 하기 위해서 어떻게 해야할까? 라는 고민을 처음 하게 되었는데, 첫번째로 방법이 바로 UIWebView 에 해당 HTML 을 불러와서 UIWebView의 stringByEvaluatingJavaScriptFromString 함수를 이용해서 처리하는 것 이었습니다.

해당 함수에 대해서 알아 볼까요?

stringByEvaluatingJavaScriptFromString:

Returns the result of running a script.

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script

Parameters

script

The script to run.

Return Value

The result of running script or nil if it fails. 


파라미터로 자바스크립트를 받고 리턴 값으로 해당 결과 혹은 실패일 경우에는 nil 값을 전달해 주는 것입니다. 즉, 이 함수를 통해서 html 에 있는 특정 값을 가져오기 위해서는 자바 스크립트가 필요합니다. 자바 스크립트를 조금 공부하셔야 하는게 있긴 한데 일단 제가 썼던 소스를 기반으로 보여드리습니다. 

먼저 해당 파싱 대상의 HTML사이트의 소스를 봐야 합니다. 


<table class="tblBasic" style="margin bottom:25px;">


<tr>


<th style="font-size:9pt;">개체식별번호</th>

<td class="num"><font color="#f76f02"><spanid="lblAnimalNo">002&nbsp;012&nbsp;028&nbsp;625</span></font></td>


<th style="font-size:9pt;">출생년월일</th>


<td class="date"><span id="lblBirthDate">2007-11-24</span></td>


</tr>
.... 


실제 HTML 페이지의 일 부분입니다. 제가 가져오고 싶은 데이터가 있는 부분은 2007-11-24 라고 가정했을때 저는 다음과 같은 자바스크립트를 구성했습니다. 
 

var d = document.getElementById('lblBirthDate');
d = d.innerHTML;d;



간단히 말하자면 'id가 lblBirthDate 라고 있는 곳의 innerHTML 을 가져와라'. 그럼 이 자바스크립트는 전체 HTML 문서의 id 중에서 lblBirthData 부분을 찾고, 그 태그 안에 있는 2007-11-24를 반환하게 되는 것입니다. 실제 코드를 보겠습니다. (사실 저는 자바스크립트를 처음 써 보았습니다.) 


NSString *js = @" var d = document.getElementById('lblAnimalNo');d= d.innerText; ";

NSString *result = [webView stringByEvaluatingJavaScriptFromString: js];


  

보시는 것 처럼 매우 간단합니다. webView 란, UIWebView의 인스턴스이고 거기에서 위에서 언급한 함수의 파라미터에 자바스크립트를 넣어주고 그럼, webView가 해당 자바스크립트를 실행 시켜서 데이터를 가져오는 것이다. 즉, 웹 브라우저가 자바스크립트를 실행 시켜서 데이터를 가져온다고 볼 수 있다. 


다 좋은데? 문제는 뭐?

일단 이 방식을 사용할때의 가장 큰 걸림돌이 여러가지가 있습니다. 

첫번째, 과연 자바스크립트를 쓸 수가 있는가?

저 같은 경우에는 자바스크립트가 처음이라 조금 고생했지만, 아시는 분이라면 getElementById 라는 것을 통해서 전체 html 문서 내 지정한 id를 찾는것을 기반으로 한다는것을 알 수 있을것 입니다. 그런데 문제는 간혹 html 페이지 자체가 전혀 id 를 쓰지 않은채 제작된 html 페이지도 있다는 것입니다. 그럴 경우에는 이 방법을 사용 할 수 없겠지요. 

두번째, 이게 최선 입니까?

한우 찾기 2.0 을 실행해 보면 처음 12자리를 입력하고 들어가는 부분에서는 로딩뷰가 뜨는것을 확인 할 수가 있습니다. 사실상 로딩뷰는 위의 UIWebView가 파싱 하려는 사이트를 로딩시작할때 시작하고 끝나면 끝나게 되어 있습니다. 그렇기 때문에 사실상 찾으려는 텍스트 데이터 임에도 불구하고 html 페이지 자체에 이미지가 있는 경우에는 UIWebView에서 해당 이미지를 로딩해야 하기 때문에 속도적인 부분에서 오래 걸릴수가 있습니다. 1분, 2분은 아니더라도 단 몇초라도 사용자 입장에서는 길게 느낄수가 있으니까요. 


정리해볼까요?

자바스크립트를 사용할 경우에는 반드시, HTML 페이지 소스에서 id가 있는지 확인하세요. 
한번쯤 프로토타입을 만들어서 시간을 측정해 보시고, 적용하세요. 



다음 포스팅에서는 한우 찾기 2.0 에서 사용한 XPath를 이용한 방법에 대해서 알아 보도록 하겠습니다. 

 
저작자 표시 비영리 변경 금지
Technique/iOS Dev 2011/05/09 00:32
Trackback 0 : 댓글을 오로지 페이스북으로만.