'IOS'에 해당되는 글 51건

  1. 2015.11.05 디버깅 (Crash 핸들링) 1
  2. 2015.11.05 [iOS 9] Search
  3. 2015.11.05 [IOS 9] 개요
  4. 2015.08.23 멀티 스레드 프로그램
  5. 2015.08.22 메소드의 동적 결합
  6. 2015.08.20 Property List
  7. 2015.08.20 Archive
  8. 2015.08.18 Copy
  9. 2015.08.18 Zone
  10. 2015.08.12 클래스 클러스터


개발 환경: XCode (6.4), iOS (8.4)

Crash 종류!

먼저, Crash 타입에는 크게 2가지 유형이 있다.

1. SIGABRT ( EXC_CRASH로 불리기도 함)

- Signal Abort, 해당 Signal은 프로그램 스스로 error를 감지하여 abort signal을 보내는 것이다.(This signal indicates an error detected by the program itself and reported by calling abort. )

- C stdlib중에 abort()라는 함수가 있다. 이 함수는 프로그램을 비정상적으로 종료시키는 함수로, 호출한 프로세스에게 SIGABRT를 날려서 프로그램을 종료시킨다. 즉 App이 프로그램 실행 도중 의도치 않은 동작을 감지 했을때 abort()를 호출하여 App을 종료시키는 것이다. 

- 이 경우는 Crash 원인을 찾기에 비교적 쉬운 타입에 속한다. 왜냐하면 App(프로그램)이 Crash 원인을 알고 있어서 Debug Output에 Crash 원인을 출력해주기 때문이다.


2. EXC_BAD_ACCESS( SIGBUS, SIGSEGV )

- SIGSEGV : signal segmentation violation, 할당된 메모리의 범위를 벗어나는곳에서 읽거나 쓰기를 시도할 때 발생됨.(프로그램 자신의 영역이 아닌 다른 영역의 메모리를 접근했을 때) 또는 readonly 메모리에 대하여 write를 시도했을때 발생되는 error signal 이다.

- SIGBUS : signal bus, SIGSEGV와 같이 메모리에 비정상적인 접근을 할 때 발생하는데, SIGSEGV는 valid한 메모리에 비 정상적인 접근을 할 때 발생하며, SIGBUS는 invalid한 메모리에 접근할 때 발생한다.

- 이 경우는 Crash 원인을 찾기가 어렵다. App(프로그램)이 Crash원인을 감지하고 App을 중단 시킨것이 아니기 떄문에 Debug Output에 Crash원인을 출력하지 않는다.

다행인점은, XCode가 업그레이드 되면서 EXC_BAD_ACCESS Crash가 일어나야 되는 상황도 미리 감지하여 SIGABRT Crash를 발생시키는 것으로 보인다. 실제로 old 버젼 XCode에서 EXC_BAD_ACCESS Crash가 일어나던 것이 최신 버젼에서는 SIGABRT Crash를 발생시키는 사례를 종종 볼 수 있다.

Crash 대처법

- 위에서 소개한 SIGABRT, EXC_BADACCESS Crash 둘다 XCode가 업데이트 되면서 왠만한 Crash들은 해당 code line 위치에서 break point가 걸린다. 하지만 그렇지 않은경우 해당 crash를 해결하기 위한 기본적인 팁을 소개하겠다.

1. SIGABRT

- 위 Crash는 SIGABRT 타입이기 때문에  debug output에 Exeption Reason이 출력된다. 하지만 해당 Exeption이 일어난 위치를 확인하고 싶을때는 All Exception BreakPoint를 설정해 준다.


- 왼쪽 Navigator에서 BreakPoint Navigator를 활성화 시킨다. 


- 왼쪽 하단에 '+' 버튼을 눌러 모든 Exception에 Breakpoint를 지정한다.


이제 SIGABRT Crash가 발생되기 직전 exception이 발생된 코드 라인에 break point가 걸려 있을것이다. 해당 기능을 사용하면 좀 더 빠른시간안에 crash원인을 찾을 수 있다.

2. EXC_BAD_ACCESS

- EXC_BAD_ACCESS Crash의 대부분의 원인은 release retain 메커니즘 오류이다. 보통 MRC 모드에서 많이 발생되나, ARC 모드에서도 간혹 발생된다.

- 위 스샷 처럼 Crash가 난 위치에서 break point가 잡히지 않았을때는 Zombie Objects를 이용한다.


- 메뉴 Product -> Scheme -> Edit Scheme 에서 Enable Zombie Objects를 활성화 한다.

- Zombie Objects가 하는 일은 메모리에 할당된 객체가 release될때 dealloc 시키지 않고 모니터링 하는 것이다. 해당 객체를 모니터링 하는 도중 프로그램이 객체에 접근하면 에러 메시지를 날려 어떤 객체에 invalid한 메모리 접근이 일어났는지 알려주는 것이다.


* 요약: main 함수에서 SIGABRT Crash가 발생되면 All Exception Break Point를 지정하고 다시 실행해서 정확한 Crash 위치를 확인해라, EXC_BAD_ACCESS Crash가 발생되면 Zombie Objects를 활성화 시켜 어느 객체에서 메모리 접근 오류가 발생했는지 확인해라.

* http://stackoverflow.com/questions/3327828/xcode-lldb-how-to-get-information-about-an-exception-that-was-just-thrown (exception print)



'IOS > 공통' 카테고리의 다른 글

About Bundle  (0) 2017.02.14
iOS Architecture  (0) 2016.12.18
UIApplicationMain?  (0) 2016.02.18
[iOS 9] Search  (0) 2015.11.05
[IOS 9] 개요  (0) 2015.11.05
Posted by 홍성곤
,

[iOS 9] Search

IOS/공통 2015. 11. 5. 12:15
 (1)NSUserActivity, (2)Core Spotlight Framework를 통해 Searchable Data를 구성하는 방법을 자세히 알아보겠습니다.


1.NSUserActivity
- 정의
NSUserActivity는 Hand-Off 기능을 지원하는 클래스로서, iOS 8에서 release 되었습니다.(Hand-Off 기능관련 해서는 다음에 자세히 알아보겠습니다.)
iOS 9에서는 기존 Hand-Off 기능이외에 Search 기능을 가능하게 하기 위해 몇가지 property들을 추가했습니다. 이로써 개발자들은 원하는 데이터를 NSUserActivity를 통해 Searchable하게 만들 수 있고, 유저들은 Spotlight(검색창)을 통해 해당 데이터를 검색할 수 있습니다.

- Detail


- NSUserActivity 객체를 만들때 activityType으로 unique identifier를 지정하고, 해당 unique identifier를 info.plist파일에 지정해야 합니다.

static NSString *const kActivityType   = @"com.nhnent.HSG2510.IOSNinePrj.employee";
static NSString *const kSearchTitleKey = @"searchTitleKey";
static NSString *const kDescriptionkey = @"descriptionKey";

- (void)setupUserActivity
{
   
 NSUserActivity *sActivity = [[NSUserActivity alloc]initWithActivityType:kActivityType];
   
    [sActivity setTitle:mSearchTitle]; 
    [sActivity setUserInfo: @{ kSearchTitleKey : @“홍성곤",
                               kDescriptionkey : @“앱기술 개발팀, IOS 개발자"}];
   
   
 NSArray *sSearchKeywords = [[sActivity userInfo] allValues];
   
    [sActivity setKeywords:[NSSet setWithArray:sSearchKeywords]];
    [sActivity setEligibleForSearch:YES];
   
    [self setUserActivity:sActivity];
}

- (
void)updateUserActivityState:(NSUserActivity *)activity
{
    [activity
 addUserInfoEntriesFromDictionary:@{ kSearchTitleKey : mSearchTitle,
                                                 
 kDescriptionkey : mDescription}];
}
* activityType: activity를 unique하게 식별해 줄 수 있는 indentifier라고 보시면 되겠습니다. 애플에서는 reverse DNS formatted string을 쓰도록 강요하고 있습니다.
* title: activity 이름이라고 보시면 됩니다. 이것은 사용자가 검색창에서 검색할때 Primary Name란에 나타납니다.
* userInfo: NSUserActivity는 IOS 8에 소개된 feature로써 Hand-Off 기능을 가능하게 만드는 객체입니다. 유저가 지금까지 행한 동작들에 대한 정보를 부가적으로 설명하기 위한 Dictionary입니다. 다른 APP에서 해당 NSUserActivity객체를 받으면 이 객체 안에 들어있는 정보만을 가지고 유저가 어떤 행동을 했는지( 어떤 인터넷 뉴스를 읽었는지, 어떤 화면을 보고 있었는지) 인지하여 해당 화면 및 상태로 유도할 수 있도록 돕는 Dictionary입니다.
* keywords: 유저가 검색할 때 사용하는 keywords 입니다. 유저는 해당 UserActivity에 저장되어 있는 contents를 title, keywords로 검색할 수 있습니다.
* setEligibleForSearch값을 YES로 설정해서 해당 contents가 검색이 가능하도록 합니다.

기본적으로 NSUserActivity 저장 및 사용은 UIResponder의 하위 클래스에서만 동작이 되도록 구현되어 있습니다. updateUserActivityState: 함수는 UIResponder의 lifeCycle동안(사용자의 event를 감지) 여러번 불려집니다. 즉, 이 함수 안에서 UserActivity의 상태를 최신으로 update해야 합니다.


- (BOOL)application:(UIApplication *)aApplication continueUserActivity:(nonnullNSUserActivity *)aUserActivity restorationHandler:(nonnull void (^)(NSArray *_Nullable))aRestorationHandler
{
    //해당 화면 이동작업
   
   
 return YES;
}
사용자가 검색창에서 검색된 contents를 tap하면 해당하는 앱내에서 검색된 contents를 포함하고 있는 UserActivity가 전달 됩니다. 전달된 시점에 UserActivity정보를 이용해서 해당 contents가 있는 화면(일반적으로 viewController)으로 이동시켜 줘야 합니다. UserActivity가 전달되는 메시지는  AppDelegate의 "application:continueUserActivity:restorationHandler:" 입니다.


2.CoreSpotlight
- 정의
CoreSpotlight는 iOS9에서 Search 기능을 위해 release된 프레임워크 입니다.
Searcable Data에 좀더 많은 정보를 제공하거나, 한번에 많은 데이터를 searchable하게 만들때 주로 사용합니다.

- Detail
위에서 소개한 NSUserActivity만으로 search 화면에서 해당 contents가 검색되게 만들 수 있습니다. 하지만 좀 더 많은 정보를 제공해 주기 위해서는 coreSpotlight 프레임워크의 CSSearchableItemAttributeSet을 NSUserActivity에 지정해줘야 합니다.

- (CSSearchableItemAttributeSet *)attributeSet
{
   
 CSSearchableItemAttributeSet *sAttributeSet = [[CSSearchableItemAttributeSetalloc] initWithItemContentType:(__bridge NSString *)kUTTypeContact];
   
    [sAttributeSet
 setTitle:@"홍성곤"];
    [sAttributeSet
 setContentDescription:@"앱기술 개발팀, IOS 개발"];
    [sAttributeSet setThumbnailData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"bla~ bla~"]]];
    [sAttributeSet setSupportsPhoneCall:YES];
    [sAttributeSet setPhoneNumbers:@[ @"010xxxxxxx" ]];
    [sAttributeSet setKeywords:@[ @"앱기술 개발팀", @"IOS 개발" ]];
    [sAttributeSet setRelatedUniqueIdentifier:unique ID”];
   
   
 return sAttributeSet;
}

NSUserActivity *sActivity = [[NSUserActivity alloc]initWithActivityType:kActivityType];
[sActivity setContentAttributeSet:[self attributeSet]];
*CSSearchableItemAttributeSet은 CoreSpotlight framework에서 제공하는 객체 입니다. 이 객체에 좀더 자세하고 많은 정보를 넣을 수 있습니다.
*contentDescripton을 지정할 수 있습니다. 검색할때 Primary Name밑에 표시 됩니다. 
*ThumbnailImage 세팅이 가능하고, 전화번호가 지정 되어있다면 통화 기능까지 제공합니다.
 

CoreSpotlight는 이외에도 한꺼번에 많은 데이터를 Searchable하게 만들 수 있습니다.
예를 들어 json 파일이나 서버에서 넘어온 데이터들을 위에서 소개한 CSSearchbleItemAttributeSet객체를 생성하고 해당 AttributeSet을 CSSearchableItem에 지정합니다.

- (CSSearchableItem *)searchableItem
{
    CSSearchableItem *sSearchableItem = [[CSSearchableItem alloc]
                                         initWithUniqueIdentifier:”unique ID”
                                         domainIdentifier:kActivityType
                                         attributeSet:[self attributeSet]];
   
   
 return sSearchableItem;
}
* UniqueIdentifier : CSSearchbleItemAttributeSet 객체에서 지정한 unique ID와 같은 값을 지정합니다. 이는 NSUserActivity의 searchable Data와의 중복을 방지해 줍니다.
    예를 들어 NSUserActivity에 CSSearchbleItemAttributeSet를 지정해서 만든 searchable data와 CSSearchableItem으로 만든 data가 같을경우 
  유저가 검색창에 검색을 햇을때 중복 결과가 나타나지 않게 해줍니다.
* domainIdentifier : NSUserActivity를 생성할때 지정해줬던 kActivityType값과 같이 reverse DNS formatted string을 사용하여 지정합니다.


- (void)indexAllEmployees
{
   
 NSArray *sSearchableItems = [self searchableItemsFromEmployees];
   
    [[CSSearchableIndex defaultSearchableIndex] indexSearchableItems:sSearchableItems completionHandler:^(NSError * aError) {
       
 if (aError)
        {
            NSLog(
@"index searchableItem error");
        }
       
 else
        {
            NSLog(
@"employees is indexed");
        }
    }];
}
* json파일, 서버 등등에서 생성한 CSSearchableItem을 array로 생성하여 searchable하게 만드는 코드 입니다.


- (void)destroyEmployeesIndexing
{
    [[CSSearchableIndex defaultSearchableIndex] deleteAllSearchableItemsWithCompletionHandler:^(NSError * aError) {
       
 if (aError)
        {
            NSLog(
@"error deleting index");
        }
       
 else
        {
            NSLog(
@"employees indexing deleted");
        }
    }];
}
* 반대로 searchable데이터를 제거하는 코드 입니다.


지금까지 NSUserActivity와 CoreSpotlight 프레임워크를 이용해 searchableData를 만들어 봤습니다. 위에서 소개한 내용은 해당 객체와 프레임워크를 사용하는 가장 기본적인 튜토리얼 입니다. 좀더 많은 기능을 사용하기 위해서는 iOS 레퍼런스 사이트를 참고해 주세요.


출처 : NHN Ent 기술공유 게시판

'IOS > 공통' 카테고리의 다른 글

About Bundle  (0) 2017.02.14
iOS Architecture  (0) 2016.12.18
UIApplicationMain?  (0) 2016.02.18
디버깅 (Crash 핸들링)  (1) 2015.11.05
[IOS 9] 개요  (0) 2015.11.05
Posted by 홍성곤
,

[IOS 9] 개요

IOS/공통 2015. 11. 5. 12:13
[Live Photos]

라이브 포토는 사진 촬영 직전의 1.5초와 직후의 1.5초의 움직임을 소리까지 합해서 저장할 수 있게 만든 기술입니다. 유저 입장에서는 소히 말하는 움짤을 손쉽게 촬영할 수 있게 되었습니다. 참고로 iPhone 6S, 6S+ 기기에서만 사용할 수 있습니다.

라이브 포토는 PHLivePhoto 객체를 통해 다룰 수 있습니다. 라이브 포토가 들어있는 사용자의 앨범에 접근하기 위해서는 기존과 마찬가지로 PHImageManager 혹은 UIImagePickerController 클래스를 활용하면 됩니다.

iOS9.1에서 사진 관련 추가/변경된 사항은 다음 링크를 참고해주세요.



[Multitasking Enhancements for iPad]

iPad를 위한 멀티태스킹환경이 도입되었습니다. 이제 한 번에 앱을 2개씩 켜놓고 동시에 사용할 수 있게 되었는데요. 12인치나 되는 큰 화면의 아이패드에서 활용하면 편할 것 같은 모드들을 몇 가지 소개하겠습니다. 


(1) Slide Over


메인 앱을 사용하면서 서브 앱을 화면 한 쪽에서 작게 볼 수 있는 모드입니다.


(2) Split View

화면을 분할하여 동시에 두 앱을 실행하는 모드입니다. 가운데 구분 막대를 드래그하여 두 앱의 화면 비율을 조절할 수 있습니다. 슬라이드 오버 모드에서 바로 이 모드로 전환이 가능합니다.


(3) PIP(Picture in Picture)

다른 앱을 실행하는 와중에도 동영상 앱의 재생화면을 스크린에 띄워서 계속 볼 수 있습니다.



[3D Touch]

디스플레이에 포함된 센서가 터치의 강도를 탭, 누르기, 세게 누르기 3단계로 나누어 인식할 수 있는 기술입니다. iPhone 6S, 6S+ 기기에서만 활용가능합니다.

(1) Peek & Pop

Peek&Pop은 콘텐츠를 살짝 탭하면 내용을 미리 살펴볼 수 있고, 콘텐츠를 조금 더 강하게 누르면 팝업으로 띄워주는 기능입니다. 지금까지는 메일 목록에서 일련의 메일을 확인하기 위해서는 메일을 하나하나씩 클릭해 들어가서 내용을 보고 다시 백키를 눌러 리스트로 돌아오는 동작을 해야 했습니다. 3D Touch를 이용하면, 이렇게 메일들의 본문에 일일이 들어갔다가 다시 나오는 동작을 반복하는 대신 1번의 3D 터치만으로 메일의 본문을 간단히 확인할 수 있습니다. 즉 사용자가 빠르게 자신이 필요한 정보를 확인할 수 있도록 도와주어 편리성을 높여줍니다.

앱 내의 뷰 컨트롤러와 웹 뷰에서 Peek&Pop을 지원할 수 있습니다. 뷰 컨트롤러에 적용하려면 UIViewControllerPreviewing, UIViewControllerPreviewingDelegate 등 새롭게 추가된 클래스들을 살펴보세요. 또한 WKWebView와 UIWebView 클래스의 allowsLinkPreview 프로퍼티를 YES로 두면 자동으로 웹뷰에서 링크 미리보기 Peek&Pop이 적용됩니다. UITouch 클래스에 새롭게 추가된 프로퍼티들을 통해 터치의 압력 정도를 파악하여 그 강도에 따른 인터랙션을 제공할 수도 있습니다.


(2) Quick Actions

퀵 액션은 홈 화면에서 바로 각 앱들의 자주 사용하는 기능을 실행시킬 수 있도록 해주는 기능입니다. 이제 유저는 메일 앱 아이콘을 누르고 메일 앱을 켜고 메일 작성 버튼을 누르는 과정을 밟지 않아도, 홈 화면에서 한번에 메일 작성 화면으로 갈 수 있게 됩니다.

자신의 앱이 퀵 액션을 지원하게 하고 싶다면 유저에게 제공할 퀵 액션을 정의하세요. 퀵 액션은 static과 dynamic 두 가지 종류로 정의할 수 있습니다. static 퀵 액션은 앱이 설치될 때 퀵 액션이 정의되고 그 후 바뀔 일이 없는 경우에, dynamic 퀵 액션은 사용자의 동작이나 목적에 기반하여 앱의 런타임에서 퀵 액션이 변화되어야 할 경우에 사용하면 좋을 것 같습니다. static 퀵 액션은 Info.plist에 퀵 액션 아이템을 등록하면 됩니다. dynamic 퀵 액션은 코드 내에서 UIApplicationShortcutItem으로 퀵 액션을 정의하고, 필요한 때에 이것을 UIApplication의 shortcutItems 프로퍼티에 셋팅하면 됩니다.


[Search]

아이폰에 저장된 개인정보와 설치한 앱들이 가지고 있는 정보들을 활용한 새로운 검색시스템이 등장했습니다. 인터넷 검색은 외부 검색엔진을 사용할 수 있지만, 폰 내 검색은 민감한 개인정보를 포함하기 때문에 자체 플랫폼이 있어야만 한다는 필요성에서 나온것으로 보입니다. 앱 데이터를 검색한 결과를 선택하면  Deep Link를 통해 앱 안에 검색된 데이터를 보여주는 화면으로 바로 이동할 수 있으며, 검색 결과는 Siri도 접근할 수 있습니다.

기본적인 개념들을 몇 가지 소개합니다.

(1) NSUserActivity
사용자의 Activities을 캡쳐해 놓음으로써, 다른 Device에서도 해당 Activities를 이어서 할 수 있게 하는 클래스입니다.
예를들어, A사용자의 아이폰 사파리 브라우저에서 기사를 보는도중 사파리를 종료 하였더라도, 아이패드에서 사파리를 키면, 중단시점에 기사의 스크롤 위치 그대로 가져와서 보여줄 수 있습니다.
이 클래스를 활용해 사용자의 Activities를 저장해 놓고, Siri 또는 Reminder를 통해 해당 Activities를 검색할 수 있게 됩니다.

(2) Core Spotlight Framework
 해당 앱 내에 있는 contents들을 카테고리 별로 indexing 해놓고 searchable하게 설정해 놓으면, 해당 contents들이 사용자의 검색어에 따라 노출되게 됩니다. 검색된 contents를 tap하면 해당 contents가 있는 app내에 navigation point로 이동합니다.

(3) Web markup
app content중 자신의 웹사이트에 추가적으로 제공해야 할 정보가 있다면 web markup을 사용해서 해당 web site로 유도할 수 있습니다.


[App Thinning]

앱스토어와 os에서 앱 설치를 최적화 하는 것으로 사용자 개개인의 기기에 맞게 앱 결과물을 만들어서 제공하는 기술입니다. 이 기술을 통해 앱의 용량 낭비를 줄이고 추후 업데이트에 대한 대응과 함께 빠른 다운로드를 유저에게 제공할 수 있습니다.

(1) Slicing (슬라이싱)
iOS 기기가 다양해져서 비트(32/64), 종류(아이폰/아이패드), 디스플레이(비레티나/레티나/3x레티나), 메모리 별로 필요한 요소가 많아졌습니다. 그래서 유저들은 자신의 기기에서는 사용하지 않는 불필요한 것들까지 다운을 받게 되었습니다. 이것을 해결하기 위해서, 이제 유저가 앱 다운 요청시 앱스토어가 해당 기종에 맞게 최적화된 버전을 사용자에게 제공해줍니다.

일반적으로 이미지의 경우 2x/3x 이미지를 동시에 넣는데, Slicing을 위해서는 Images.xcassets 에 이미지를 넣어서 관리해야만 기기에 맞게 이미지가 선택된다고 하니 주의해주세요.

(2) Bitcode 
앱을 중간형태(intermediate representation)로 컴파일해서 앱 스토어에 등록하면 앱스토어에서 알아서 다운로드 시점에 맞게 최적화된 실행 파일을 만들어서 배포를 합니다. ios의 경우는 기본적으로 설정되어 있지만 옵션이고 watchOS에서는 필수입니다. 비트코드를 제공하기 위해서는 앱 번들 내의 모든 앱과 프레임워크가 비트코드를 포함해야 합니다.

설정 방법: 'Build Settings' > 'Build Options' > 'Enable Bitcode'

(3) On-Demand Resources
이미지나 사운드와 같은 리소스에 키워드로 태킹을 하고 그룹화 하여 해당 리소스가 필요한 시점에만 그 자료를 다운받아서 사용하고 불필요한 부분을 삭제하여 전체적으로 앱 용량을 줄이는 방법입니다. 비록 네트워크를 사용하는 단점이 있지만 줄어든 용량의 앱을 빠르게 다운받고 처음 실행시 세팅 시간을 줄여주는 효과를 줍니다. On-Demand Resources에서도 마찬가지로 Slicing을 지원합니다.


[App Transport Security]

iOS9에서는 http 프로토콜 통신을 사용하는 경우에는 예외처리 등록이 필요하고, app to app 인증을 하려면 개별 schmem 등록이 필요합니다.


Apple iOS9 대응관련 레퍼런스


[Contacts and Contacts UI]

기존 Address Book / Address Book UI 프레임워크를 대신할 새로운 주소록 Contacts API가 도입되었습니다. Contacts API를 사용하는 대부분의 앱이 정보를 읽는데만 사용하기 때문에, 이 프레임워크는 read-only usage에 최적화 되어있습니다.

새로운 Contacts 클래스인 CNContact는 thread-safe 하며 NSDictionary와 비슷하게 mutable한 subclass CNMutableContact를 가집니다.
그리고 multi value를 가질 필요가 있는 프로퍼티를 위해 ( ex. 주소(집, 회사), 전화번호(집, 핸드폰)) 복수의 값을 담을 수 있는 CNLabeledValue를 제공합니다.

Contact를 위한 뷰 컨트롤러에는 CNContactPickerViewController, CNContactViewController 등이 있습니다. 이 뷰 컨트롤러들은 Contact를 displaying, editing, selecting, creating 하는 UI 인터페이스를 제공합니다.

(1) Fetching Contacts(CNContactStore)
- user’s contacts database라고 생각하면 된다.
- fetch, save가능
- CNContactStore의 대부분 methods들은 synchronous 하기 때문에 background thread에서 사용하는 걸 추천한다. 필요하다면, fetch된 immutable data들을 main thread로 보낼 수 있다.
- predicates기능을 통한 filtering 가능
  -  ex)”AppleSeed”라는 이름을 가진 Contats정보를 fetch해오고 싶다. -> CNContact.predicateForContactsMathchingName(“AppleSeed")
- keysToFetch array를 이용해 지정한 key에 해당하는 것들만 Fetch가능

(2) Privacy 
- 사용자가 앱내에서 Contact 정보 접근권한을 얻는 도중에는 CNContactStore의 보내지는 모든 메세지는 block처리 된다. 즉, 해당 block으로 인해 mainThread block으로 이어지는 사태를 막기 위해서는
ContactStore의 비동기 메서드인 [CNContactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:]를 사용하거나 background thread에서의 사용을 권한다.

(3) Unified Contacts 
- 다른 계정에 있는 각각의 Contact라 할지라도 동일한 사람을 나타내면, 해당 Contacts들은 자동적으로 linked되어 Unified Contacts가 될 수 있다.(ex. iCloud계정의 Contact 정보 + FaceBook의 Contact 정보 = Unified Contact)
 - Unified Contact는 In-memory, temporary view 개념이다. (DB로 따지면 table이 아니라 view 개념)
 - Unified Contact는 Unique Identifier를 가지고 있는데 Unified Conatct에 포함된 Contact들의 Indentifier와는 구별된다. 즉, 해당 Unified Contact를 refetch를 하려면 Unified Contact의 Indentifier를 통해 수행해야 한다.

[Keychain]

OS X와 달리 iOS에서는 자신의 Appliction에 속한 Keychain Item들만 접근이 가능합니다. 또한 Keychain에 대한 권리는 해당 앱의 provisioning profile에 의존합니다. 그러므로 앱 버전이 다르더라도 같은 provisioning file을 사용하기를 권장합니다.

keychain은 여러가지 속성의 정보를 포함하고 있습니다. 그 중 password나 private key같은 정보들은 encrypt되어 저장되고, certificates같은 데이터들은 encrypt되지 않은 채 저장됩니다.

키체인에 접근할 때 touch id를 사용할 수 있습니다. (kSecAccessControlTouchIDAny 사용)
앱 비밀번호를 이용한 접근도 가능합니다. (kSecAccessControlApplicationPassword 사용)
또한 오직 touch id로, 또는 오직 앱 비밀번호만으로 접근할 수 있는 고유 데이터를 지정할 수 있습니다. 지문 데이터가 지워지면 데이터가 따라 지워지게 할 수도 있습니다.



[Additional Framework Changes]

앞서 언급한 것들을 제외한 프레임워크의 나머지 변경점들을 소개합니다.


(1) Foundation Framework

on-demand 로딩을 위해 NSBundle API들이 추가되었습니다. on-demand 로딩에 대한 개념과 설명은 [App Thinning] 부분에서 다루고 있으니 해당 부분을 참고해주세요. 추가된 API들의 주요 역할은 특정 리소스의 우선순위를 셋팅하는 것입니다.

전력과 열 관리를 위해 NSProcessInfo API들이 추가되었습니다. NSProcessInfo는 현재 실행중인 프로세스의 정보에 접근하는 것을 도와주는 클래스입니다. 이 클래스를 통하여 전력/열 관리를 제어할 수 있습니다. 예를 들어서, 새로 추가된 LowPowerModeEnabled 프로퍼티를 통해 현재 디바이스의 최소전력모드 활성화 여부를 알 수 있습니다. 이 프로퍼티의 값을 확인하여 개발자는 디바이스가 최소전력모드에 들어가있을 때 앱이 최소한의 동작만 하게 만들 수 있습니다.


(2) MapKit Framework

MapKit framwork에서 다음 사항들이 추가/변경되었습니다.
- 대중교통의 방향과 도착시간을 가져올 수 있게 되었습니다. MKLaunchOptions과 MKDirections 클래스를 활용하세요.
- 3D 플라이오버 뷰를 지원합니다.
- 어노테이션(Annotations)의 커스터마이징 범위가 늘었습니다. MKAnnotationView 클래스의 DetailCalloutAccessoryView 프로퍼티를 활용하세요.
- 검색 결과에 타임존 정보를 제공합니다.


(3) Safari Services Framework

앱 안에서 웹뷰를 띄울 수 있게 해주는 SFSafariViewController가 추가되었습니다. SFSafariViewController는 Safari와 쿠키, 데이터를 공유하며 Safari의 자동완성, 읽기도구 같은 주요 기능들도 사용할 수 있게 해줍니다. 그리고 주소창 옆에 Done 버튼을 제공해주는데, 이 버튼을 누르면 앱의 이전 화면으로 가게 됩니다.

SFSafariViewController는 사파리와 다르게 하나의 페이지를 보여주는 것에 적합합니다. WKWebView나 UIWebView 기반의 브라우저를 통해 웹 컨텐츠를 보여주고 있었다면 SFSafariViewController로 전환하는 것을 고려해보세요. 단순히 웹 컨텐츠를 표시하는 것 뿐이라면 훨씬 편한 것 같습니다.


(4) UIKit Framework


새로 추가된 UIStackView는 위와 같은 레이아웃을 다양한 화면 크기에 대응하여 편하게 구현할 수 있게 도와줍니다.
StackView라는 이름처럼, 서브뷰들을 마치 스택에 쌓는 것처럼 horizontal 정렬, vertical 정렬하여 쌓을 수 있습니다. layout constraint를 사용하지 않아도 가능합니다! 프로퍼티를 설정하는 것만으로 서브뷰의 정렬 방향을 손쉽게 바꿀 수 있고, 서브뷰 중 하나의 히든 속성이 바뀌면 자동으로 눈에 보이는 서브뷰들의 레이아웃을 재구성해줍니다. 이런 과정을 자동으로 해준다고 하니 수직/수평 정렬이 많이 필요한 뷰에서 유용하게 사용해볼 수 있을 것 같습니다.

그 외에도 다음과 같은 점들이 추가/변경되었습니다.
- UILayoutGuide 가 새롭게 추가되었습니다. 화면 크기에 따라 본문 텍스트의 좌우마진을 얼마나 가져야 하는지 자동으로 계산해주는 역할 등을 합니다.
- Peek&Pop, 퀵 액션, 애플와치와의 인터랙션 등을 위해서 UIApplicationDelegate에 새로운 메서드들이 추가되었습니다.
- UIUserNotificationAction에 behavior이라는 프로퍼티가 추가되었습니다. 알림이 도착했을 때 유저에게서 바로 텍스트를 입력받을 수 있도록 해줍니다.
- 모든 UI요소가 right-to-left 형식의 언어에 적합하게 flip 동작을 지원합니다.



[Deprecated APIs]
iOS9에서 Deprecated된 API 중 주요 몇 가지만 소개합니다.

(1) Address Book and Address Book UI frameworks
기존의 주소록 API가 Deprecated되고 새로운 주소록 API가 도입되었습니다. [Contacts and Contacts UI] 부분을 참고해주세요.

(2) NSURLConnection API
NSURLConnection API가 deprecated 되었습니다. init 메서드, 비동기 리퀘스트를 보내는 메서드 등이 deprecated되었는데요. 애플은 NSURLConnection으로 개발된 네트워크 관련 코드를 NSURLSession을 사용하는 코드로 전환할 것을 권장하고 있습니다. 앞으로 새로운 업데이트는 NSURLSession에만 이루어지며, watchOS에서는 NSURLConnection를 아예 지원하지 않습니다. 다행히 전환은 그렇게 어렵지 않다고 합니다. 참고로 iOS 프로젝트에 많이 쓰이고 있는 AFNetworking도 현재는 NSURLConnection을 사용하고 있지만 이후 릴리즈 버전에서는 해당 코드를 없애겠다고 밝혔습니다.

Deprecated 된 모든 API 목록을 보고 싶다면 아래 링크를 참고해주세요.


-출처 : NHN Ent 기술공유 게시판


'IOS > 공통' 카테고리의 다른 글

About Bundle  (0) 2017.02.14
iOS Architecture  (0) 2016.12.18
UIApplicationMain?  (0) 2016.02.18
디버깅 (Crash 핸들링)  (1) 2015.11.05
[iOS 9] Search  (0) 2015.11.05
Posted by 홍성곤
,

- 카운터 관리 방식을 사용할 경우, 자식 스레드 쪽에서는 객체가 누수되는 것을 막기 위해 부모 스레드와는 다른 자동 해제 풀을 만들어 관리할 필요가 있다.

- 스레드 세이프
    -- 여러 개의 스레드가 하나의 인스턴스를 조작할 때 오작동하지 않을 경우, 그 클래스는 스레드 세이프 하다고 말한다. 일반적으로 불변 객체는 스레드 세이프하고 가변 객체는 스레드 세이프 하지 않다. 즉, 가변 객체를 공유하기 위해서는 상호 배제나 동기화를 적절히 사용해야 한다.

- 스레드 생성                                                                                                                               
    -- NSThread                                                                                                                                       + (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument                                                                                                                          
    -- 객체 aTarget에 대한 메소드 호출을 새로운 스레드를 만들어 실행한다. aSelector는 id 타입의 인수를 하나만 사용해서 void를 리턴하는 액션 메소드여야만 한다. 카운터 관리 방식을 사용할 경우 실행되는 메소드 자체가 자동 해제풀을 관리할 필요가 있다. 인수 aTarget과 anArgument에 지정된 객체는 스레드를 만드는 것과 동시에 retain되어 스레드가 종료될때 release된다.

   -- NSApplication                                                                                                             
      --- + (void)detachDrawingThread:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
         ---- 위에 NSTherad의 스레드 생성 메서드를 사용하는데, 카운터 관리 방식일 경우 스레드를 위한자동 해제 풀을 만든다.
      --- + (BOOL)isMultiThreaded                                                                                                
          ---- 여러 개의 스레드가 병행으로 동작하고 있거나 그 시점에서 메인 스레드 밖에 없더라도 이제까지 스레드가 생성된 적이 있다면 YES를 리턴.

- 상호 배제
    -- 여러 개의 스레드 사이에서 전역 변수와 같은 공유 자원의 상호 배제를 하기 위해 NSLock 클래스를사용.
    -- Lock은 프로그램이 멀티 스레드로 동작하기 전에 만들어져야 함.
        --- 어떤 락에 대해 lock이 실행 되면 그 후 반드시 unlock을 1회만 실행해야 한다. lock을 한 후 unlock을 사용하는 것은 같은 스레드에서 해야함.                                                                          
    -- (void)Lock
        --- P조작: 락이 사용 중이라면 스레드는 휴면상태에 들어감. 사용중이 아니라면 락을 사용 중으로 바꾸고 실행을 계속함
    -- (void)unLock
        --- V조작: 사용 중이던 락을 해제, 그 락을 획득하기 위해 휴면 상태에 있는 스레드가 있다면 그 스레드가 해제된 락을 획득
                                                                                                       
    -- (BOOL)tryLock
        --- 리시버인 락 획득을 시도하고 획득을 성공한 경우 YES를 리턴함, 실패한 경우 휴면 상태에 들어가지 않고 NO를 리턴한 후, 실행을 계속함.

'IOS > Objective-C' 카테고리의 다른 글

Collections의 weak reference  (0) 2016.10.02
NSString과 NSMutableString의 copy  (0) 2016.02.18
메소드의 동적 결합  (0) 2015.08.22
Property List  (0) 2015.08.20
Archive  (0) 2015.08.20
Posted by 홍성곤
,

- Objective-C에서는 런타임 시스템의 기능을 사용해서 클래스의 일부 메소드를 런타임에 추가하거나 교체하는 것이 가능함. 

- 단 지나치게 남용하면 유지보수하기 어려움. 

- 최후의 수단으로 사용할 것을 권함.


- @dymamic을 지정한 프로퍼티는 이에 대응하는 접근자 메소드를 클래스에서 정의할수도 있지만, 정의하지 않아도 런타임에 함수를 동적으로 결합하는 것이 가능함.

- Objective-C의 메소드는 IMP 타입으로 표현되는 C함수이다. 첫번째 인수가 self(id타입), 두번째 인수가 SEL이 되어야 함.

- BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);

    - cls는 바인딩시키코 싶은 클래스이고, name은 메소드의 셀렉터, imp는 함수의 포인터, types는 함수의 타입 정보를 나열한 것이다. 바인딩에 성공한 경우 YES를 리턴.

- 실제 바인딩 하기

    - -(void)setList:(NSArray *)obj ----> void set_list(id, SEL, NSArray *)(프로토 타입) 

    - class_addMethod(self, @selector(setList:). (IMP)set_list, "v@:@"); 로 함수 바인딩(클래스 메소드 안에서 호출할 경우 첫번쨰 인수에 self를 집어넣으면 됨)


* @encode() 

 - Objective-C는 객체를 동적으로 다루는 일이 많아 데이터를 보존하거나 통신을 할 때, 그 데이터가 실제로 어떤 데이터 타입이라는 정보를 알려줘야 하는 경우가 있다.  

 - Objective-C는 데이터 타입을 표현하기 위해 C문자열(const char*)의 타입 코드를 사용하지만, 타입에서 문자열을 쉽게 얻을 수 있도록 @encode()라는 컴파일러 지시자가 제공됨.

 - @encode()는 인수로 타입명을 받아 컴파일할 떄 대응하는 타입으로 교체를 한다. 예를 들어 @encode(int)는 'i'가 되고, @encode(NSSize)는 '{_NSSize=ff}'가 된다.

 - 주요타입의 표

 코드

데이터 타입 

 c 

 char

 s

 short

 i

 int 

 l

 long 

 q

long long 

 f

 float 

 d

 double 

 C

 unsigned char 

 S

 unsigned short 

 I

 unsigned int 

 L

 unsigned long

 Q

 unsigned long long 

 V

 void 

 *

 C문자열(char *) 

 @

 객체 

 #

 킄래스 객체 

 :

 셀렉터 

 [타입]

 배열 

 {이름=타입...}

 구조체 

 ^타입

 타입의 포인터 

 ?

 정해지지 않은 타입이나 요소 


'IOS > Objective-C' 카테고리의 다른 글

NSString과 NSMutableString의 copy  (0) 2016.02.18
멀티 스레드 프로그램  (0) 2015.08.23
Property List  (0) 2015.08.20
Archive  (0) 2015.08.20
Copy  (0) 2015.08.18
Posted by 홍성곤
,

Property List

IOS/Objective-C 2015. 8. 20. 21:06

Cocoa 환경에서 여러 정보를 표현하고, 보존하기 위해 사용하는 표준적인 데이터 형식.

- ASCII, XML, 바이너리 형식의 세 종류 형식을 사용할 수 있음.

   - ASCII : NSString, NSData, NSArray, NSDictionary 표현 가능.

   - XML : 위의 네가지 + NSNumber, NSDate

   - 바이너리 : 위와 같은 형식을 텍스트가 아닌 바이너리 파일로 보존함.


- ASCII 형식의 Property List에서는 NSArray, NSDitionary의 인스턴스에 대해 description 메서드를 사용해서 문자열 형식으로 값을 얻을 수 있고, 이를 다시 객체의 구조로 복원하기 위해서 propertyList메서드를 사용해서 복원할 수 있다.

- XML 형식의 Property List에서는 NSArray, NSDictionary에 대해 writeToFile:atomically:를 사용해서 XML 형식의 프로퍼티 리스트를 파일에 쓸 수 있다. 파일에서 다시 객체로 복원하려면 initWithContentsOfFile을 사용해서 복원.

- 클래스 타입과 프로퍼티 리스트의 문자열 표현

  클래스

 XML 형식의 태그  

 ASCII 형식의 데이터 표현 

 NSString 

 <string> 

 "문자열" 

 NSNumber 

 <integer>, <real>, <true/>, <false/> 

  없음 

 NSData

 <data> 

 <16진수> 

 NSDate 

 <date> 

  없음 

 NSArray 

 <array> 

 (요소, 요소, ...) 

 NSDictionary 

 <dict> 

 {키 = 값; 키 = 값} 


- 프로퍼티 리스트의 변환과 검증

세 종류의 프로퍼티 리스트를 서로 변환하거나 형식을 검증하기 위한 클래스 NSPropertyListSerialization이 제공됨. 프로퍼티 리스트를 복원해서 얻는 객체의 구조를 가변 객체로 구성하는 것도 가능.

'IOS > Objective-C' 카테고리의 다른 글

멀티 스레드 프로그램  (0) 2015.08.23
메소드의 동적 결합  (0) 2015.08.22
Archive  (0) 2015.08.20
Copy  (0) 2015.08.18
Zone  (0) 2015.08.18
Posted by 홍성곤
,

Archive

IOS/Objective-C 2015. 8. 20. 19:48

객체 직렬화와 아카이브의 차이
: 코코아 프레임워크에서 직렬화(serialization)는 아카이브와 마찬가지로 객체 그래프를 따라 객체의 데이터 내용을 저장하는 방식이다. 다만, 아카이브와 달리 직렬화는 주로 문자열, 배열이나 사전 컬렉션에 담겨 있는 계층 구조와 참조하는 객체 데이터만 직접적으로 저장하며, 참조 관계에는 관심이 없고 데이터에만 관심이 있다. 예를 들어, 여러 곳에서 하나의 객체를 다중 참조하고 있으면 참조마다 동일한 내용을 각기 저장한다. 그러므로 deserialization 할 때에도, 동일한 객체를 다중 참조하는 것이 아니라 각기 다른 객체가 만들어진다는 것이다. 그리고 데이터에만 관심이 있기 때문에 해당 객체가 가변 객체였는지 불변 객체였는지 판단해서 복원할 수 없다.
객체 직렬화와 직접적으로 관련이 있는 클래스는 NSPropertyListSerialization이 있다. 이 클래스는 Foundation 객체 중에서 NSDictionary, NSArray, NSString, NSDate, NSData, NSNumber 타입으로 저장되어 있는 데이터 구조만 XML 기반 plist 파일로 직렬화 해서 저장한다. 
NSUserDefaults 클래스도 내부적으로 NSPropertyListSerialization을 사용해서 직렬화를 지원한다.

직렬화(Serialization)는 다중 참조 관계나 가변객체 여부등을 복원하지 못하고 저장할 수 있는 클래스 종류도 한정적이다. 이러한 제약 사항을 지원해야 하는 경우라면 <NSCopying> 프로토콜을 사용해야 한다. 

<NSCoding> 프로토콜

- 객체를 Archive, UnArchive하기 위해서는 NSKeyArchiver, NSKeyUnarchiver가 필요.
- Archive 대상이 되는 객체는 NSCoding 프로토콜을 따르고 있어야 함.
- NSCoding 프로토콜 : encodeWithCoder, initWithCoder:

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [super encodeWithCoder:aCoder];
    // 슈퍼 클래스가 NSCoder프로토콜을 따르지 않으면 불필요.
    [coder encodeObject:객체 forKey:키];
    [coder encodeDouble:실수 forKey:키];
    ....
}

먼저 슈퍼클래스가 NSCoding 프로토콜을 따르고 있으면 super의 encoderWithCoder를 호출해서 인코딩 후 자신을 인코딩함. 클래스가 독자적으로 가지고 있는 인스턴스 변수가 없고, 슈퍼클래스 에 encodeWithCoder:의 정의가 있는 경우라면 이 메소드 정의 자체가 필요 없음.
인코딩할때의 Key는 인스턴스 변수 각각에 다른 키를 지정해야 한다. 슈퍼 클래스에서 지정한 키를
서브 클래스에서 사용하면 안된다. 키는 같은 내부에서만 구별할 수 있으면 되기 때문에 다른 클래스
에서 같은키 사용 가능.
객체의 아카이브 메서드는 encodeObject:forKey:를 사용하는데, 이 함수는 첫 번째 인수인 객체에
대해 encodeWithCoder:를 호출해서 인코딩하므로, 이런 메소드는 재귀 호출한다. 객체 그래프에 순환 참조가 있는 경우, 같은 객체의 인코딩 요구가 여러 번 발생할 수 있지만 일단 아카이브한 객체를 중복해서 아키이브 하지 않음.

*encodeConditionalObject: (다른 곳에서 아카이브되어 있지 않으면 인코딩하지 않는 메서드)
- 아카이브 할때 인스턴스 변수 일부만 아카이브할 수가 있는데, 아카이브 하지 않은 인스턴스 변수를 객체 그래프의 순환참조가 있을경우 다른 곳에서 아카이브를 해버리면 복원하는 시점에 문제가 발생할 수 있다. 이때 사용하는 메서드.

- (id)initWithCoder:(NSCoder *)aCoder
{
    self = [super initWithCoder:aCoder];
    //슈퍼 클래스가 NSCoding 프로토콜을 따르지 않으면 [super init]만 하면 됨.
    
    변수 = [[coder decodeObjectForKey:키] retain];
    .....
    return self;
    
    // 인코딩도 디코딩과 같은 키를 지정하기만 하면, 디코딩하는 순서는 상관없고 복원하지 않는 변수가 있어도 상관 없음.
}

 


'IOS > Objective-C' 카테고리의 다른 글

메소드의 동적 결합  (0) 2015.08.22
Property List  (0) 2015.08.20
Copy  (0) 2015.08.18
Zone  (0) 2015.08.18
클래스 클러스터  (0) 2015.08.12
Posted by 홍성곤
,

Copy

IOS/Objective-C 2015. 8. 18. 12:04

copy, mutableCopy

NSObject에는  리시버를 복사하는 copy라는 메서드가 있다. 단, 실제 복사 처리를 하는것은 copy가 아니라 copyWithZone:이라는 인스턴스 메서드이다. 인스턴스 객체에 copy메세지를 보내면 인수로 NULL을 지정해서 자기 자신의 copyWithZone을 호출해서 Default Zone에 새로운 인스턴스를 만들 수 있다.

이러한 원리로, 인스턴스가 복사되도록 하기 위해서는 copy 메소드가 아닌 copyWithZone: 메소드를 정의해야 한다. 만약 복사가 실패했을 경우 copy, copyWithZone 둘 다 nil을 리턴한다.

copyWithZone:은 NSCopying 프로토콜 내에서 선언되어 있으므로 이 프로토콜을 적용해서 구현한다.


*인스턴스 객체를 바이트 배열로 간주하고 통째로 복사해서 다른 객체를 리턴하는 함수가 제공 됨.

 - id NSCopyObject(id anObject, NSUInteger extraBytes, NSZone *zone)

   - 인수의 anObject가 원본 객체이고 extraBytes는 보통 0을 지정함, 인수 zone에 NULL을 지정하면 default zone이 사용됨.

   -  문제점 : 원본 객체의 인스턴스 객체들까지 copy가 되지 않는다.(객체 내용의 바이트 배열을 복사하기만 하므로..) 즉, 원본객체와 복사객체 모두 해당 인스턴스 객체를 강한 참조하게 된다, 또한 MRC를 사용할 경우 해당 인스턴스 객체에 retain count가 자동 증가되지 않기 때문에 copy 후 retain을 해줘야 함. -> 즉, 단순히 값을 복사하기만 하면 되는 인스턴스가 많을 경우 유용.


- 불변객체에서 가변객체 복사를 생성하려면 mutableCopy메서드가 위에 copy메서드와 대응되고,    mutablecopyWithZone:이 copyWithZone:과 대응된다. 동작 메커니즘은 똑같다.


얕은복사 vs 깊은
복사
: 얕은복사는 메모리 주소를 복사한다는 것이다. 즉, 똑같은 인스턴스를 두개의 포인터가 가리키고 있게 된다.
깊은 복사는 새로운 메모리 공간을 할당해서 인스턴스의 값을 복사한다는 것이다. 서로 다른 공간의 메모리가 생기고 두개의 포인터는 각각의 메모리 공간을 가리키게 된다.

: NSArray와 같은 파운데이션 프레임워크에 있는 모든 클래스는 얕은 복사를 지원한다. 즉, NSArray에 copy메세지를 보내도 array가 포함하고 있는 각 객체들에게 copy 메세지를 보내서 복사하는게 아니라 메모리 주소만 복사한다.
깊은 복사를 하기 위해서는 array계열 클래스는 'initWithArray:copyItems:' 메서드가 있고, 다른 컬렉션 클래스에도 비슷하게 'copyItems:' 으로 끝나는 메서드가 존재한다. 해당 메서드를 호출할 때 copyItems 인자에 'YES'를 넘기면 각 컬렉션들이 포함하고 있는 객체에 copy메세지를 보내 복사하게 된다. 단 각 객체가 <NSCopying> 프로토콜을 conform 하지 않으면 런타임 에러가 발생한다. 


'IOS > Objective-C' 카테고리의 다른 글

Property List  (0) 2015.08.20
Archive  (0) 2015.08.20
Zone  (0) 2015.08.18
클래스 클러스터  (0) 2015.08.12
BOOL  (0) 2015.08.12
Posted by 홍성곤
,

Zone

IOS/Objective-C 2015. 8. 18. 10:55

Cocoa에서는 동적으로 확보되는 메모리를 관리하기 위해 zone이라는 영역을 사용한다.

동적으로 메모리를 할당하고 해제하는 작업을 반복할 경우 서로 관계가 있는 내용의 데이터가 메모리 상에서는 멀리 떨어진 곳에 흩어질 가능성이 있다. 그래서 메모리 공간에 여러 개의 힙을 만들어 서로 밀접한 관계에 있는 데이터나 객체는 특정 힙 내에서 메모리가 할당되도록 한다. 

이렇게 메모리 상에 만들 수 있는 힙 영역을 Zone이라 부른다.

Zone은 각각 메모리 관리 기능이 있고, 필요에 따라 그 크기가 증가한다. 프로그램이 실행된 직후부터 존재하는 Zone을 Default Zone이라 한다. 그리고 따로 지정하지 않을 경우 인스턴스 객체는 Default Zone에 만들어 진다.

*가비지 컬렉션을 사용하는 경우 Zone 사용 불가.

'IOS > Objective-C' 카테고리의 다른 글

Property List  (0) 2015.08.20
Archive  (0) 2015.08.20
Copy  (0) 2015.08.18
클래스 클러스터  (0) 2015.08.12
BOOL  (0) 2015.08.12
Posted by 홍성곤
,

- Objective-C 에서는 클래스 클러스터를 만들기 위한 언어 자체의 매커니즘은 없다. 하지만 일반적으로, 공개클래스는 추상 클래스로, 구체적인 클래스는 공개 클래스의 비공개 서브 클래스로 구현되어 있음.

- Cocoa에서 많은 클래스가 실제로는 클래스 클러스터로 구현되어 있다. 대표적으로 NSData, NSDate, NSArray, NSDictionary, NSSet, NSString, NSNumber, NSValue 등이 있다. 이들 클래스는 일반적인 방법으로 서브 클래싱을 할 수가 없다.


- 클래스 클러스터 인스턴스의 소속을 확인할 경우.

   - 클래스 클러스터에서 각 인스턴스는 비공개 서브 클래스의 인스턴스이다. 따라서 공개 클래스를 인수로 한 메소드 isMemberOfClass:를 사용해도 어떤 결과가 나올지 알 수 없다. 인스턴스가 속하는 클래스를 확인하기 위해서는 isKindOfClass:나 respondsToSelector:로 확인하는것이 바람직하다.

- 서브 클래스를 만드는 경우 밑에 두가지 방법이 있다. 

1) True Subclass

1. 비공개 데이터 구조를 결정한다.

- 인스턴스 변수로 가질 데이터 구조를 결정한다. 슈퍼 클래스인 클래스 클러스터가 가지는 데이터 구조는 절대 사용하면 안됨.

2. 이니셜라이저를 정의한다.

- init 이외의 슈퍼클래스의 이니셜라이저를 상속받아 사용하면 안됨. 비공개 데이터 구조가 없다면 init을 사용하면 되므로 이니셜라이저의 정의는 필요 없음.

3. 컨비니언스 컨스트럭터를 정의한다. 

- 필요할 경우, 데이터 타입명으로 시작하는 임시 객체를 생성하는 클래스 메소드를 정의합니다. 슈퍼 클래스의 같은 메소드를 상속받아 사용하면 안됩니다.

4. 원시(primitive) 메소드를 정의한다.
- 원시 메소드는 각 클래스 클러스터의 레퍼런스 문서에 나와있다.

5. 그외의 메소드를 정의한다.

- 원시 메소드를 정의하면 공개 클래스에서 선언된 메소드가 일단 동작은 한다. 다만 그 데이터 구조의 특징을 살리기 위해 메소드를 오버라이드 해서 사용할 수 있다.

2) Composite Object

Composite Object의 경우 역시 abstract superclass를 상속 받은 후 데이터 모델을 직접 설계하지 않고 기존의 private cluster object를 맴버로 가지고 그것을 그대로 사용하는 방식입니다.

문제는 실제 데이터가 모두 맴버 변수에 저장되어있기 때문에 primitive methods들을 모두 구현하되 내부에 가지고 있는 private cluster object와 연결 해주어야 합니다.


뭐, 자주 쓰일 일은 없을 것 같지만 일단 두가지 방법으로 서브클래싱이 가능하기 때문에 특정 동작을 위한 컬랙션 같은 것을 구성할 때 편하게 사용할 수 있을듯 합니다.


그럼 어떤 때 이런 Class Cluster에 대한 subclassing이 필요할까요?

먼저 생각이 떠오른 것은,


True subclass의 경우 NSValue가 지원하지 않는형태의 value를 사용해야 한다던지.. (물론 valueWithBytes:objCType: 같은 것으로 해결 할 수도 있을것 같습니다.) file 같은 것에 매핑된 거대한 array같은 것을 사용한다던지, 심지어 서버와 통신하면서 동작하는 NSArray를 구현한다던지(아.. 너무 오버인것 같기도 합니다. 큰 데이터에 sorting 같은 걸 하면 안드로메다 가겠습니다.) 등등 응용분야는 많을듯 합니다.


Composite object의 경우 기존의 collection에 validation처리를 한다던지, logging을 한다던지, 데이터 처리 자체를 변경하지 않는 범위에서 무엇인가 추가작업을 간결하게 하고자 하면 유용할듯 합니다.


  *출처 -  http://maccrazy.tistory.com/102

'IOS > Objective-C' 카테고리의 다른 글

Property List  (0) 2015.08.20
Archive  (0) 2015.08.20
Copy  (0) 2015.08.18
Zone  (0) 2015.08.18
BOOL  (0) 2015.08.12
Posted by 홍성곤
,