본문 바로가기
프로그래밍 놀이터/iOS

[iOS Study] 저장, 읽기, 앱 상태

by 돼지왕 왕돼지 2016. 3. 7.
반응형


 [iOS Study] 저장, 읽기, 앱 상태


출처 : 아론 힐리가스의 iOS 프로그래밍


(BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)options;, (void)applicationDidBecomeActive:(UIApplication *)app;, (void)applicationDidEnterBackgroun:(UIApplication *)app;, (void)applicationWillEnterForeground:(UIApplication *)app;, (void)applicationWillResignActive:(UIApplication *)app;, 0, 1, 10초 후, Active, addObserver:selector:name:object:, app bundle, app state, AppDelegate, application bundle, application sandbox, application:didFinishLaunchingWithOptions:, application:willFinishLaunchingWithOptions:, applicationDidBecomeActive:, applicationdidenterbackground, applicationDidEnterBackground:, applicationWillEnterForeground:, applicationWillResignActive:, Archive, archiveRootObject:toFile:, archving, background state, binary data, broadcast, build phases, c 표준 라이브러리, caches, CGRect, convinience method, copy bundle resources, DATABASE, defaultCenter, defaultManager, didReceiveMemoryWarning, document, documentation, Documents, encodeInt:forKey:, encodeObject:forKey:, encodeWithCoder:, file, file system, Finder, float, HardWare, icloud, imageWithContentsOfFile:, inactive state, initWithCoder:, initWithContentsOfFile:, IOS, ios study, ios tutorial, iTunes, jpeg, jpeg to uiimage, Key, key-value, key-value pair, Library, library/preferences, local notification, localizedDescription, mainbundle, memory kill, memory kill callback, Model, model-view-controller, Model-View-Controller-Store, MVC, nib, nil, not running, notification, notification center, NSArray, nsbundle, nscachesdirectory, nscoder, nscoding, NSData, NSDate, nsdecoder, NSDictionary, nserror, NSException, NSException vs NSError, NSFileManager, NSKeyedArchiver, NSKeyedUnarchiver, NSNotification, nsnotificationcenter, NSNumber, NSSearchPathForDirectoriesInDomains, NSString, nsstringfromselector, NSTemporaryDirectory, NSUserDefaults, nsuserdomainmask, NSValue, object, Objective-C, option click, OS, OS X, pathForResource:ofType:, property list serializable, protocol, Push, Push Notification, Ram, recursive, removeItemAtPath:, Serializable, Serialization, Serialize, Show, Show Package Contents, simulate memory warning, simulator, SMS, status bar, Store, suspended state, Target, tmp, uialertview, UIApplicationDelegate, UIApplicationDidChangeStatusBarFrameNotification, UIApplicationDidreceiveMemoryWarningNotification, UIApplicationStatusBarFrameUserInfoKey, UIImage, UIImageJPEGRepresentation, UIView, unarchiveObjectWithFile:, unarchiving, userInfo, view controller, Web Service, writeToFile:, writeToFile:atomically:, writeToFile:atomically:encoding:error, xcode, xcode 6, XIB, xml, xml property list, [iOS Study] 저장, _cmd, ~/Library/Developer/CoreSimulator/Devices, 강제 전환, 경고뷰, 경로, 교체, 노티피케이션, 노티피케이션 센터, 단축키, 데이터베이스, 동기화, 동기화 백업, 디렉토리, 디자인 패턴, 딕셔너리, 레퍼런스 문서, 로우 메모리 경고, 리소스 해제, 멀티테스킹, 메모리, 메모리 킬, 메모리 킬 함수, 메소드, 메소드의 셀렉터, 모델-뷰-컨트롤러, 문자열 배열, 바이너리, 방어벽, 백그라운드, 백그라운드 상태, 백그라운드 시간, 백업, 복구, 불가, 비활성화, 비활성화 상태, 삭제, 상태 저장, 상태바, 스트림, 시간 의존, 시스템 메모리, 시스템 이벤트, 실행 파일, 아론 힐리가스, 아이클라우드, 아이튠즈, 아카이빙, 알람, 알림, 암시적 변수, 압축품질, 앱, 앱 리소스, 앱 번들, 앱 상태, 앱 샌드박스, 언아카이빙, 오디오, 오버레이, 옵저버, 운영체제, 웹 서비스 통신, 이미지, 이벤트, 인코딩, 인터페이스, 읽기, 읽기 전용, 임시 데이터, 잠근 버튼, 장치, 재귀, 저장, 전체 경로, 전화, 정지 상태, 제거, 추가, 컨비니언스 함수, 클래스, 키-값, 타입, 파일, 파일 삭제, 파일 시스템, 패키지 내용 보기, 포인터 주소, 폴더, 표준 파일 i/o, 푸쉬, 프로그래머 오류, 프로토콜, 프로퍼티, 프로퍼티 리스트 직렬화 객체, 핸들러, 홈 더블클릭, 홈 버튼, 활성화, 활성화 상태


-
여기서는 iOS 에서 파일 시스템을 통해 읽고 쓰는 데 필요한 개념과 기법을 배운다.


-
아카이빙은 iOS 에서 모델 객체를 저장하는 가장 흔한 방법 중 하나이다.
객체의 아카이빙은 그 객체의 프로퍼티들을 모두 기록하고 파일시스템에 그 내용을 저장하는 것을 포함한다.
언아카이빙(unarchiving)은 아카이브한 데이터로부터 객체를 다시 만든다.


-
인스턴스들을 아카이브하고 언아카이브해야 할 클래스들은 NSCoding 프로토콜을 반드시 따라야 하며, 두 필수 메소드 encodeWithCoder: 와 initWithCoder: 를 구현해야 한다.


-
encodeWithCoder:  메시지를 받으면, 전달된 인자인 NSCoder 객체 안에 모든 프로퍼티들을 인코딩한다.
저장 과정 중에 데이터 스트림을 저장하기 위해 NSCoder 를 사용한다.
그 스트림은 키-값 쌍으로 구성되어 파일 시스템에 저장된다.


-
NSCoder 객체를 이용하여 값들을 저장한다.
[aCoder encodeObject:self.itemName forKey:@“itemName”]
...
[aCode encodeInt:self.value forKey:@“value”];


-
객체가 인코딩될 때 그 객체는 encodeWithCoder:  메시지를 받는다.
encodeObject:forKey: 에서 object 에 해당하는 녀석이 encodeWithCoder: 메시지를 받는다는 의미이다.
따라서 객체를 인코딩하는 것은 각 객체가 자신의 친구를 인코딩하고 다시 그 친구가 친구를 인코딩하는 등의 재귀적인 동작이다.


-
객체를 인코딩하기 위해서는 NSCoding 프로토콜을 따라야 한다.
NSString, NSDate 등의 클래스는 기본으로 이 프로토콜을 따른다.


-
cf)
Option + Class Click 은 documentation 을 보여준다.
이는 클래스, 메소드, 타입, 프로토콜 등 많은 곳에 사용될 수 있다.


-
아카이브에서 로드되는 객체들은 initWithCoder: 메시지를 받는다.
이 메소드는 encodeWithCoder: 에서 인코딩된 모든 객체들을 잡아서 적절한 인스턴스 변수에 할당해야 한다.


-
아카이빙은 XIB 파일을 만드는 방법이기도 하다.
UIView 는 NSCoding 프로토콜을 따른다.
UIView 의 인스턴스는 캔버스 영역에 그것을 드래그할 때 생성된다.
XIB 파일이 저장되면 이 뷰들은 그 XIB 파일에 아카이브된다.
프로그램이 시작되면 XIB 파일에서 뷰들을 언아카이브한다.
XIB 파일과 표준 아카이브 간에 약간의 차이점이 있지만 전반적으로 과정을 같다.


-
모든 IOS 앱은 앱 샌드박스(application sandbox)를 가진다.
앱 샌드박스는 파일시스템에서 나머지 부분으로부터 방어벽으로 차단된 디렉터리이다.
앱은 반드시 자식의 샌드박스 안에 위치해야 하고 다른 앱들은 그 샌드박스에 접근할 수 없다.


-
앱 샌드박스는 여러 디렉터리를 갖는다.

앱 번들
     실행 파일과 NIB 파일과 이미지 등과 같은 모든 앱 리소스를 포함한다.
     읽기 전용이다.

Documents/
     앱이 실행 중에 생성하고 앱을 실행할 때마다 유지할 데이터를 쓰는 곳.
     아이튠즈나 아이클라우드와 동기화할 때 백업된다.

Library/Caches/
     앱이 실행 중에 생성하고 앱을 실행할 때마다 유지할 데이터를 쓰는 곳이다.
     이 디렉터리는 아이튠즈나 아이클라우드와 동기화할 때 백업되지 않는다.
백업되지 않는 주된 원인은 데이터가 매우 커질 수 있고 장치에 동기화하려면 많은 시간이 걸리기 때문.

Library/Preferences/
     설정 내용이 저장되고 설정 앱이 앱의 설정을 찾는 장소이다.
     Library/Preferences 는 NSUserDefaults 클래스가 자동으로 처리하고 장치가 아이튠즈나 아이클라우드와 동기화될 때 백업된다.

tmp/
     앱 실행 중에 임시로 사용하는 데이터를 쓰느 장소이다.
     운영체제는 앱이 실행되지 않는 동안 이 디렉터리의 파일들을 제거할 것이다.
     하지만 더 이상 사용하지 않는 경우에는 이 디렉터리에서 파일들을 명시적으로 지워야 한다.
     이 디렉터리는 장치가 아이튠즈나 아이클라우드와 동기화될 때 백업되지 않는다.
     앱 샌드박스에서 tmp 디렉터리의 경로를 얻으려면 NSTemporaryDirectory 컨비니언스 함수를 사용할 수 있다.


-
NSSearchPathForDirectoriesInDomains 함수는 주어진 인자들에 따른 기준에 부합하는 경로를 파일시스템에서 검색한다.
이 함수의 마지막 두 인자는 iOS 에서 항상 같다.
첫번재 인자는 샌드박스에서 경로를 얻고자 하는 디렉터리를 지정한 상수이다.
예를 들어 NSCachesDirectory 를 검색하면 앱 샌드박스에서 Caches 디렉터리를 반환할 것이다.
이들 상수는 iOS 와 OS X가 함께 사용한다.
따라서 모든 상수가 iOS 에서 작동하는 것은 아니다.

반환값은 문자열 배열이다.
이것이 문자열 배열인 이유는 OS X 에서 왔기 때문이다.
OS X 에서는 검색 기준에 부합하는 경로가 여러 개 있을 수 있다.
반면 iOS 에서는 오직 하나뿐이다.
그 배열의 첫번째 결과가 해당 경로이다.

NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentDirectory = [documentDirectories firstObject];
return [documentDirectory stringByAppendingPathComponent:@"fileName.extension"];


-
[NSKeyedArchiver archiveRootObject:object toFile:path]; 를 통해 실제 아카이브를 저장한다.

이 함수가 호출되면 NSCoder 를 실체화한 NSKeyedArchiver 의 인스턴스를 만들고, 해당 instance 를 전달된 object 의 encodeWithCoder: 에 전달한다.

그럼 재귀적으로 이 녀석(NSKeyedArchiver)이 전달되면서 encodeWithCoder: 를 호출해 내용을 저장한다.


-
앱이 bg 로 갈 때 어떤 액션을 하고 싶다면 AppDelegate 의 applicationDidEnterBackground: 메시지를 오버라이드하면 된다.
예를 들어 사용자가 장치에서 홈 버튼을 누르면 이 녀석이 불린다.


-
Xcode 6 의 iphone simulator 폴더는 ~/Library/Developer/CoreSimulator/Devices 이다.
이 폴더 안에는 시뮬레이터를 위한 모든 앱과 그 앱들의 샌드박스가 저장되는 곳이다.
근데 이 앱들은 실제 앱 이름이 아니고 코드화되어 있어, 안쪽 data 를 보고 직접 찾아야 한다.

cf) 파인더에서 Command + Shift + G 를 눌러 한번에 이동할 수 있다.


-
unarchive 를 위해서는...

[NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; 를 통한다.

이 함수는 아카이브에서 루트 객체 타입을 검사하여 그 타입의 인스턴스를 만든다.

NSkeyedArchiver 와 마찬가지로 이 녀석은 자신을 NSDecoder 로 만들어 initWithCoder: 메시지를 재귀적으로 호출하며 내용을 복구한다.


-
앱이 실행되고 있지 않을 때는 실행 중이 아닌 not running 상태이다.
어떤 코드도 실행되지 않고 RAM 에서 메모리를 차지하지도 않는다.


-
사용자가 앱을 시작한 이후에는 활성화 active 상태에 진입한다.
활성화 상태에서는 화면에 앱의 인터페이스가 표시되고 이벤트를 받으면 그 이벤트를 처리한다.


-
앱이 활성화 상태에 있을 때 SMS 메시지, 푸시 알림, 전화, 알람 등과 같은 시스템 이벤트를 받으면 일시적으로 중단될 수 있다.
이 이벤트를 처리하기 위해 앱 위에 오버레이가 나타난다.
이 상태는 비활성화 상태(inactive state)이다.
비활성화 상태에서는 대부분 앱이 보이고(경고뷰가 나타나 앱 인터페이스의 일부를 가린다.) 코드가 실행되고 있지만 이벤트를 받을 수 없다.
일반적으로 앱들은 비활성화 상태에서 매우 짧은 시간을 소비한다.
장치 상단의 잠근 버튼을 눌러 활성 앱을 비활성화 상태로 강제로 전환할 수 있다.
그 앱은 장치가 잠금해제될 때까지 비활성화 상태에 머물러 있는다.






-
사용자가 홈 버튼을 누르거나 또 다른 방식으로 다른 앱으로 전환하면, 그 앱은 백그라운드 상태 background state 로 진입한다.
실제로는 백그라운드로 전환하기 전에 비활성화 상태에 잠시 머문다.
백그라운드 상태에서 앱의 인터페이스는 보이지 않고 이벤트를 받지 못 하지만 코드는 아직 실행할 수 있다.
기본적으로 백그라운드 상태에 진입한 앱은 약 10초 후에 정지 상태 suspended state 로 진입한다.
앱은 이 시간에 의존해서는 안 되며 사용자 데이터를 저장하고 모든 공유 리소스를 가능한 한 빨리 해제해야 한다.


-
앱이 시작되면 아래 함수들이 불리며 활성화 상태가 된다.
application:willFinishLaunchingWithOptions:
application:didFinishLaunchingWithOptions:
applicationDidBecomeActive:

홈 버튼이 눌리거나 전화가 오면 아래 함수가 불리며 비활성화가 되고..
applicationWillResignActive:

비활성화 상태에서 아래 함수가 불리며 백그라운드로 이동한다.
applicationDidEnterBackground:

정지된 상태에서 재활성화가 될 때는 아래 함수가 불린다.
applicationWillEnterForeground:
applicationDidBecomeActive:

정지된 상태에서 시스템 메모리가 부족하면 앱이 죽는다.
이 때 다시 앱에 다시 진입하면 application:willFinishLaunchingWithOptions: 부터 다시 불린다.

(BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)options;, (void)applicationDidBecomeActive:(UIApplication *)app;, (void)applicationDidEnterBackgroun:(UIApplication *)app;, (void)applicationWillEnterForeground:(UIApplication *)app;, (void)applicationWillResignActive:(UIApplication *)app;, 0, 1, 10초 후, Active, addObserver:selector:name:object:, app bundle, app state, AppDelegate, application bundle, application sandbox, application:didFinishLaunchingWithOptions:, application:willFinishLaunchingWithOptions:, applicationDidBecomeActive:, applicationdidenterbackground, applicationDidEnterBackground:, applicationWillEnterForeground:, applicationWillResignActive:, Archive, archiveRootObject:toFile:, archving, background state, binary data, broadcast, build phases, c 표준 라이브러리, caches, CGRect, convinience method, copy bundle resources, DATABASE, defaultCenter, defaultManager, didReceiveMemoryWarning, document, documentation, Documents, encodeInt:forKey:, encodeObject:forKey:, encodeWithCoder:, file, file system, Finder, float, HardWare, icloud, imageWithContentsOfFile:, inactive state, initWithCoder:, initWithContentsOfFile:, IOS, ios study, ios tutorial, iTunes, jpeg, jpeg to uiimage, Key, key-value, key-value pair, Library, library/preferences, local notification, localizedDescription, mainbundle, memory kill, memory kill callback, Model, model-view-controller, Model-View-Controller-Store, MVC, nib, nil, not running, notification, notification center, NSArray, nsbundle, nscachesdirectory, nscoder, nscoding, NSData, NSDate, nsdecoder, NSDictionary, nserror, NSException, NSException vs NSError, NSFileManager, NSKeyedArchiver, NSKeyedUnarchiver, NSNotification, nsnotificationcenter, NSNumber, NSSearchPathForDirectoriesInDomains, NSString, nsstringfromselector, NSTemporaryDirectory, NSUserDefaults, nsuserdomainmask, NSValue, object, Objective-C, option click, OS, OS X, pathForResource:ofType:, property list serializable, protocol, Push, Push Notification, Ram, recursive, removeItemAtPath:, Serializable, Serialization, Serialize, Show, Show Package Contents, simulate memory warning, simulator, SMS, status bar, Store, suspended state, Target, tmp, uialertview, UIApplicationDelegate, UIApplicationDidChangeStatusBarFrameNotification, UIApplicationDidreceiveMemoryWarningNotification, UIApplicationStatusBarFrameUserInfoKey, UIImage, UIImageJPEGRepresentation, UIView, unarchiveObjectWithFile:, unarchiving, userInfo, view controller, Web Service, writeToFile:, writeToFile:atomically:, writeToFile:atomically:encoding:error, xcode, xcode 6, XIB, xml, xml property list, [iOS Study] 저장, _cmd, ~/Library/Developer/CoreSimulator/Devices, 강제 전환, 경고뷰, 경로, 교체, 노티피케이션, 노티피케이션 센터, 단축키, 데이터베이스, 동기화, 동기화 백업, 디렉토리, 디자인 패턴, 딕셔너리, 레퍼런스 문서, 로우 메모리 경고, 리소스 해제, 멀티테스킹, 메모리, 메모리 킬, 메모리 킬 함수, 메소드, 메소드의 셀렉터, 모델-뷰-컨트롤러, 문자열 배열, 바이너리, 방어벽, 백그라운드, 백그라운드 상태, 백그라운드 시간, 백업, 복구, 불가, 비활성화, 비활성화 상태, 삭제, 상태 저장, 상태바, 스트림, 시간 의존, 시스템 메모리, 시스템 이벤트, 실행 파일, 아론 힐리가스, 아이클라우드, 아이튠즈, 아카이빙, 알람, 알림, 암시적 변수, 압축품질, 앱, 앱 리소스, 앱 번들, 앱 상태, 앱 샌드박스, 언아카이빙, 오디오, 오버레이, 옵저버, 운영체제, 웹 서비스 통신, 이미지, 이벤트, 인코딩, 인터페이스, 읽기, 읽기 전용, 임시 데이터, 잠근 버튼, 장치, 재귀, 저장, 전체 경로, 전화, 정지 상태, 제거, 추가, 컨비니언스 함수, 클래스, 키-값, 타입, 파일, 파일 삭제, 파일 시스템, 패키지 내용 보기, 포인터 주소, 폴더, 표준 파일 i/o, 푸쉬, 프로그래머 오류, 프로토콜, 프로퍼티, 프로퍼티 리스트 직렬화 객체, 핸들러, 홈 더블클릭, 홈 버튼, 활성화, 활성화 상태



-

상태 

보이는가

이벤트 수신가능 

코드 실행 

실행 중 아님 

NO 

NO 

NO 

활성화(Active) 

YES 

YES 

YES 

비활성화(Inactive) 

MOSTLY 

NO 

YES 

백그라운드(Background) 

NO 

NO 

NO 

정지 

NO 

NO 

NO 




-
정지 상태에 있는 앱은 코드를 실행할 수 없고 앱의 인터페이스 또한 볼 수 없다.
그리고 정지 상태 중에 필요하지 않은 모든 리소스는 소멸된다.
정지된 앱은 동결 상태가 되고 사용자가 앱을 다시 시작하면 빠르게 복원될 수 있다.


-
정지상태에 있는 앱은 시스템 메모리가 충분하다면 남아있을 것이다.
운영체제가 메모리가 점점 줄어든다고 판단하면 필요에 따라 정지 상태인 앱을 종료할 것이다.
정지된 앱은 종료에 관한 어떤 알림도 받지 못한다.
그저 단순히 메모리에서 삭제된다.
(앱은 종료된 뒤에도 멀티테스킹 화면(홈 버튼 더블클릭)에 남아있을 수 있지만 그 아이콘을 누르면 앱은 다시 시작될 것이다.)


-
앱이 상태를 바꾸면 앱 델리게이트는 메시지를 받는다.
다음은 앱 상태 전이를 알리는 UIApplicationDelegate 프로토콜의 메시지이다.

- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)options;
- (void)applicationDidBecomeActive:(UIApplication *)app;
- (void)applicationWillResignActive:(UIApplication *)app;
- (void)applicationDidEnterBackgroun:(UIApplication *)app;
- (void)applicationWillEnterForeground:(UIApplication *)app;


-
백그라운드 상태로 가는 중에 변경사항과 앱의 상태를 저장하는 것이 좋다.
앱이 정지 상태로 들어가기 전 코드를 실행할 수 있는 마지막 기회이기 때문이다.
앱이 정지 상태에 들어가고 나면 운영체제의 상황에 따라 종료될 수 있다.


-
Objective-C 프로그래머들은 버퍼에 단순히 메모리를 할당하는 대신에 버퍼를 생성하고 유지하고 소멸하는 데 편리한 클래스인 NSData 를 사용한다.
NSData 인스턴스는 바이너리 데이터의 바이트들을 가지고 있고 이를 사용하여 데이터를 저장하는 데 사용될 수 있다.


-
UIImageJPEGRepresentation 함수는 UIImage 와 압축품질 두 인자를 받는다.
압축 품질은 0부터 1까지의 float 값이다.
이 함수는 NSData 객체를 return 한다.


-
NSData 인스턴스는 writeToFile:atomically: 메시지를 보내서 파일 시스템에 쓰여질 수 있다.
첫번째 인자는 경로, 두번째 인자는 atomically boolean 값으로 YES 이면 파일시스템의 임시 장소에 파일을 쓴 다음 그 파일이 첫 번째 인자의 경로로 이름이 변경되고 기존의 파일이 있다면 교체된다.

atomically 는 파일 쓰기 과정 중 앱이 중단될 경우 데이터의 변조를 막는다.
NSData 인스턴스들도 아카이브될 수 있지만, writeToFile:atomically: 메소드를 사용하는 것은 NSdata 에서 바이트들을 파일시스템에 직접 복사하는 것.


-
파일의 삭제는

[[NSFileManager defaultManager] removeItemAtPath:imagePath error:nil];


-
JPEG 으로 저장된 파일에 대한 복구는..

[UIImage imageWithContentsOfFile:imagePath] 이다.


-
시스템에 램 부족 현상이 발생하면 실행 중인 앱에 로우 메모리 경고가 나타난다.
그 앱은 현재 필요하지 않고 재생성하기 쉬운 리소스들을 해제하는 것으로 대응한다.
뷰 컨트롤러는 로우 메모리 경고가 나타나면 didReceiveMemoryWarning 메시지를 받는다.


-
로우 메모리 경고에 응답할 수 있는 뷰 컨트롤러가 아닌 나머지 객체들은 노티피케이션 센터(notification center)를 사용해야 한다.
모든 앱은 똑똑한 게시판처럼 동작하는 NSNotificationCenter 의 인스턴스를 가진다.


-
로우 메모리 경고가 발생할 때마다 UIApplicationDidreceiveMemoryWarningNotification 이 노티피케이션 센터에 발송된다.

로우 메모리 경고 핸들러를 구현하길 원하는 객체는 이 노티피케이션에 등록할 수 있다.

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(clearCache:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];


-
Simulator 에서는 Hardware 메뉴의 Simulate Memory Warning 을 선택하면 로우 메모리 경고를 발생시킬 수 있다.


-
NSNotification 은 이름, 객체, 선택적인 사용자 정보 딕셔너리를 가진다.
이름은 옵저버를 찾기 위한 key 로 사용한다.
객체는 notification 을 게시할 책임을 가지는 객체이며,
선택적 딕셔너리는 옵저버가 알아야 할 추가 정보를 가진다.


-
상태바의 프레임이 어떤 이유로든 변경되면 UIApplication 은 UIApplicationDidChangeStatusBarFrameNotification 을 사용자 정보 딕셔너리와 함께 알린다.
이 딕셔너리에는 상태바의 새로운 프레임이 들어있다.
딕셔너리 안에는 객체만 올 수 있기 때문에 CGRect 는 NSValue 로 감싸져서 온다.

NSDictionary* userInfo = [notification userInfo];
NSValue* wrappedRect = userInfo[UIApplicationStatusBarFrameUserInfoKey];
CGRect newFrame = [wrappedRect CGRectValue];






-
userInfo 딕셔너리 안에 무엇이 있는지 어떻게 알 수 있을까?
각 노티피케이션은 클래스 레퍼런스에 문서화 되어 있다.
대다수는 "이 노티피케이션은 userInfo 딕셔너리를 포함하지 않는다." 와 같이 쓰여있다.
userInfo 딕셔너리를 가진 노티피케이션은 모든 키와 키에 매핑된 것을 해당 문서에 나열할 것이다.


-
addObserver:selector:name:object: 메소드에서 보통 object 는 nil 이 assign 되는데,
특정 객체의 포인터를 지정하면 옵저버는 오직 그 객체가 보낸 노티피케이션만을 통지받는다.


-
Notification Center 의 한 가지 목적은 여러 객체가 동일한 이벤트에 콜백을 등록하는 것을 허용하는 것이다.
여러 객체가 같은 노티피케이션 이름에 대해 옵저버를 등록할 수 있다.
해당 Notification 이 발생하면 이 모든 객체들은 자신이 등록한 메시지를 받는다.(특별한 순서 없이)
따라서 Notification 은 여러 객체가 이벤트에 관심 가질 때 사용하기 좋은 해결책이다.


-
NSNotificationCenter 는 앱 간의 통신, 푸시 노티피케이션, 로컬 노티피케이션과는 아무 상관이 없다.
그저 단일 앱에서 객체들 사이에 통신하기에 간단하다.


-
표준 모델-뷰-컨트롤러 패턴은 컨트롤러가 모델 객체를 저장하고 불러오는 책임을 지도록 호출한다.
하지만 실제론 감당하기 힘들다.
컨트롤러는 단순히 아주 바쁘게 모델 객체와 뷰 객체 사이에 객체를 어떻게 가져오고 저장하는지의 상호 작용을 처리한다.
그러므로 모델 객체가 어디서 오는지와 객체가 다른 타입으로 어디에 저장되는지를 처리하는 로직을 저장소로 옮기는 편이 낫다.

저장소는 컨트롤러 객체가 모델 객체를 가져오고 저장하도록 하는 메소드들을 공개한다.
이 모델 객체가 어디서 오고 어떻게 도착하는지는 저장소에 달려있다.
저장소는 파일, 데이터베이스, 웹 서비스 통신 등의 여러 가지 방법이 될 수 있다.

이 방식을 사용하는 한 가지 이점은 컨트롤러 클래스를 단순화하는 것뿐만 아니라 저장소가 작동하는 방법을 컨트롤러나 앱의 다른 부분을 수정할 필요 없이 교체할 수 있다는 점이다.
이는 데이터의 디렉터리 구조처럼 간단한 변경 사항이 되거나 데이터의 포맷처럼 매우 큰 변화가 될 수도 있다.
그러므로 앱이 데이터의 읽고 저장해야 하는 컨트롤러 객체를 여러 개 가져도 단지 저장소 객체만 변경하면 된다.

모델-뷰-컨트롤러-스토어(Model-View-Controller-Store) 디자인 패턴이다.


-
_cmd 는 암시적 변수로 현재 메소드의 셀렉터를 나타낸다.
NSStringFromSelector(_cmd) 와 같이 사용하기 좋다.


-
NSData 는 바이너리 데이터에 잘 쓰인다.
C 표준 라이브러리의 표준 파일 I/O 를 쓸 수도 있긴 하지만, NSData, NSString 을 사용하는 것이 훨씬 편리하다.
텍스트 데이터용으로는 NSString 의 두 인스턴스 메소드 writeToFile:atomically:encoding:error 와 initWithContentsOfFile: 이 있다.

여기서 NSError 는 발생하는 에러를 저장하는 객체.
NSError 는 포인터 주소 &error 를 전달한다.
에러가 발생했을 때, NSError.localizedDescription 메시지를 보내면 에러 메시지를 얻을 수 있다.


-
사용자에게 오류를 보여주길 원할 때 보통 UIAlertView 를 사용한다.

UIAlertView *a = [[UIAlertView alloc] initWithTitle:@“Read Failed” message:[err localizedDescription] delegate:nil cancelButtonTitle:@“OK” otherButtonTitles:nil];
[a show];


-
Objective-C 프로그래머들 사이에는 예외가 거의 항상 프로그래머 오류를 나타내는 데 사용된다.
예외가 발생하면 그 오류에 대한 정보는 NSException 객체에 담긴다.


-
언제 NSException 을 사용하고 또 언제 NSError 를 사용할까?
인자로 홀수만을 전달하여 호출해야 하는 메소드를 작성하고 있을 경우, 짝수로 호출하면 예외를 던진다.
호출한 곳에서 에러를 만들어 자신의 방식대로 오류를 찾도록 프로그래머에게 도움을 준다.
특정 디렉토리의 내용을 읽는 메소드를 작성하고 있는데 해당 권한을 가지고 있지 않다면, NSError 를 만들어 이 요청을 수행할 수 없는 이유를 담아 호출한 곳으로 다시 전달한다.


-
NSString, NSDictionary, NSArray 모두 writeToFile: 과 initWithContentsOfFile: 메소드를 가진다.

이 메소드들로 파일시스템에 컬렉션 객체를 쓰려면 반드시 프로퍼티 리스트 직렬화(property list serializable) 객체만을 담고 있어야 한다.
프로퍼티 리스트 직렬화 객체는 NSString, NSNumber, NSDate, NSData, NSArray, NSDictionary 뿐이다.

NSArray 나 NSDictionary 를 파일 시스템에 쓰면 XML 프로퍼티 리스트가 만들어진다.
XML 프로퍼티 리스트는 거의 모든 시스템에서 읽을 수 있기 때문에, 데이터를 저장하는 편리한 방법이다.
많은 웹 서비스 앱들이 입출력에서 프로퍼티 리스트를 사용한다.



-
XCode 에서 iOS 앱 프로젝트를 빌드하면 앱 번들(application bundle)이 만들어진다.
앱 번들은 앱 실행 파일과 앱과 함께 패키지된 모든 리소스를 포함한다.
리소스는 XIB 파일, 이미지, 오디오 파일처럼 실행 중에 사용되는 파일이다.
Xcode 는 리소스 파일을 프로젝트에 추가하면 자동으로 앱과 패키징돼야 하는 것을 인식한다.


-
타깃에서 Build Phases 패널에 나오는 항목들이
프로젝트를 빌드할 때 발생하는 단계들 중 하나이다.
Copy Bundle Resources 단계에서는 프로젝트 안의 모든 리소스들이 앱 번들에 복사된다.


-
시뮬레이터에 앱을 설치한 후 파일시스템에서 앱 번들이 어떻게 보이는지 확인할 수 있다.
해당 앱 홈 폴더로 가서 앱 이름을 클릭하고 우클릭하여 [Show Package Contents] (패키지 내용 보기) 를 선택하면 된다.


-
실행중에 앱 번들에서 파일을 불러올 수 있다.
앱 번들에서 파일의 전체 경로를 얻으려면 앱 번들의 포인터가 필요하다.
그리고 리소스의 경로를 앱 번들에 요청한다.

NSBundle *applicationBundle = [NSBundle mainBundle];
NSString *path = [applicationBundle pathForResource:@“myImage” ofType:@“png”];

없는 파일을 요청하면 nil 을 반환한다.
파일이 존재하면 전체 경로를 반환한다.


-
앱 번들에 있는 파일들은 읽기 전용이다.
앱 번들에 있는 파일들은 일반적으로 버튼 이미지, 인터페이스 사운드 효과, 초기 상태의 데이터베이스 등과 같은 것들이다.









반응형

댓글