Core Data 상속 구현하기

Core Data에서 Entity에 상속을 적용할 수 있다.

방법은 의외로 간단하다.

1. 관계 설정하기

우선 Entity를 아래와 같이 추가한다.

cd1

그리고 우선 부모 Entity에 Abstract Entity 체크를 해준다. 체크를 해주는 부분은 오른쪽에서 3번째 버튼을 누르면, 체크 할 수 있는 화면이 나온다.

cd2

그리고 자식 Entity 설정에서 부모 Entity를 선택해주면 된다.

cd3   cd4

그리고 다시 미리보기로 가면 화살표로 상속 관계가 표시되는 걸 볼 수 있다.

cd5

2. 모델 파일 생성하기

모델 파일을 만들경우, 기본 파일을 만들어서 NSManagedObject 를 상속받게하는식으로 직접 작업할 수 있다.

하지만 XCode 에서 새로운 파일 생성 시 NSManagedObject 파일을 선택하면, 좀 더 편하게 모델파일을 만들 수 있다.

cd6

NSManagedObject 를 선택하면 모델을 선택하는 화면이 나온다.

cd7

모델을 선택하면 Entity를 선택할 수 있다.

cd8

그러면 파일이 생성된다. 또, Entity를 여러개 선택해서 한번에 파일을 추가할 수 있다.

cd9

아래는 Entity를 여러개 선택한 후 한번에 파일이 만들어진 화면이다.

cd10

3. 모델 파일 확인

모델 클래스를 확인해보면 상속관계까지 알아서 처리되어있는 것을 볼 수 있다.

person.h

 
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface Person : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * age;

@end

Person.m

 
#import "Person.h"

@implementation Person

@dynamic name;
@dynamic age;

@end

Student.h

 
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Person.h"

@interface Student : Person

@property (nonatomic, retain) NSString * hobby;

@end

Student.m

 
#import "Student.h"

@implementation Student

@dynamic hobby;

@end

Teacher.h

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Person.h"

@interface Teacher : Person

@property (nonatomic, retain) NSNumber * salary;

@end

Teacher.m

#import "Teacher.h"

@implementation Teacher

@dynamic salary;

@end

인자 접근 방법은 다른 상속관계 접근하는 방법과 같다.

참고 링크 : Managed Object Models

Concurrency Programming Guide 요약

Concurrency Programming Guide

concurrency and application design

예전에는 일하는 시간이 CPU의 clock 속도로 결정이 됐었다. 칩의 효율이 점점 발전하니까 다른 성능을 발전시킬 방법이 없나 찾게됬고, 결국 해결방법은 각 칩의 프로세서 코어의 숫자를 늘리는 것. 이제 속도는 빨라지게 됬지만,  신경써야 할 점은 어떻게 추가된 코어의 이점을 이용할 것인가가 되었다. 여러개의 코어의 이점을 얻기 위해서는 소프트웨어가 여러가지 일을 동시에 하도록 만들어져야 한다. 여러개의 코어를 사용하는 방법은 스레드를 여러개 만드는 것인데, 이 방법은 문제가 있다. 그 문제는 스레드를 위한  코드가 임의의 숫자인 코어들을 잘 사용하지 못하는 것 이다. 알아야 할 것은 효율적으로 사용될 수 있는 코어의 숫자이다. 그 숫자를 알아도 처리해야 할 일은 많은데, 그 문제를 해결하기 위해 os가 도와준다.

The Move Away from Thread

스레드를 사용하는 대신, iOS랑 OS X는 concurrency 문제를 해결하기 위해서 asynchronous design approach를 사용한다. 비동기 방식은 나온지 꽤 됬는데, 데이터를 읽거나 하는 오랜 시간이 걸리는 일에 사용 된다. 이게 불리면 씬 뒤에서 해야 하는 일을 하고 실제로 완성될 때 쯤에 리턴을 한다. 보통 백그라운드 스레드를 얻어서, 해야 하는 일을 스레드에서 하고, 일이 완료되면 부른 애한테 결과 Notification을 보낸다. (보통 이건 콜백 함수) 예전에는 asynchronous function을 위해서 직접 코드를 짜야 했지만 요즘은 OS에서 기술을 제공해준다.

OS에서 제공해주는 기술 중 하나가 GCD.
이 기술이 보통 어플리케이션에 쓸 스레드 관리하는 코드를 시스템 레벨로 옮긴다. 우리가 해야하는 건 실행되기 원하는 task를 정의하고 적절한 dispatch queue에 추가를 하면 된다. GCD가 필요한 스레드를 만들고 task들을 스케쥴링해서 스레드를 실행하는 일들을 해준다. 스레드 관리는 이제 시스템이 하니까, GCD는 task 관리와 실행을 하도록 전체적으로 접근하게 해주고, 예전 스레드 만드는 방식보다 효율이 좋게 해준다.

다른 방법은 Operation Queue.
이건 dispatch queue같이 작동하는 objective-c 객체이다. 이것도 실행하기 원하는 일을 task로 정의하고 operation queue에 추가한다. GCD처럼 operation queue가 스레드 관리를 하고 task가 가능하면 빨리, 효율적으로 실행될 수 있도록 해준다.

Dispatch Queue

Dispatch queue는 task를 실행하기 위한 C 기반의 매커니즘이다. dispatch queue는 순차적으로나 동시적으로 일을 실행하는데, 언제나 FIFO다. 순차적인 큐는 한번에 하나의 task만 실행한다. 대조적으로 동시적인 큐는 가능하면 많은 task를
시작하고, 이미 시작한 task가 끝나는걸 기다리지 않는다.

dispatch queue 의 이점 :
직관적이고 간단한 프로그래밍 인터페이스를 제공한다 자동적이고, 전체적인 스레드 관리 풀을 제공한다.
어셈블리를 변경해서 빠르게 했다.
메모리 효율적임 (어플리케이션 메모리 안에서 스레드 스택이 남아있지 않기 때문)
They do not trap to the kernel under load task 를 asynch 하게 dispatch하면 데드락에 걸릴 수 없다.
They scale gracefully under contention.
순차적인 dispatch 큐는 락이나 다른 synchronization 의 기본 요소에 대한 효율적인 대안점을 제공함. dispatch queue에 보내는 task는 함수 안이나 block 객체 안에 요약되어있어야 한다. block함수는 C언어 기능인데, iOS4.0부터 지원이 된다.
개념상으로는 함수 포인터와 비슷하다. 하지만 추가적인 이익이 있다. 블락은 블락의 문법적인 공간에 정의하는 대신에, 다른 함수나 메소드 안에 정의한다. 그래서 그래서 블락이 그 함수나 메소드 안의 다른 변수들에 접근 할 수 있다.
dispatch queue에 블락을 보내면 원래의 범위에서 옮겨져서 힙으로 복사될 수 있다. Dispatch Queue는 GCD 와C runtime 기술 파트 중에 하나이다.

Dispatch Sources

Dispatch Source는 특정한 시스템 이벤트를 asynchronous하게 처리하기 위한 C 기반의 메커니즘이다.
Dispatch Source는 이벤트가 발생하면, 특정한 시스템 이벤트 타입에 대한 정보를 요약하고 정해진 block 객체나 함수를 dispatch queue로 보낸다.

Dispatch source는 아래 시스템 이벤트 타입으로 모니터 할 수 있다.

Timers
Signal handlers
Descriptor-related events
Process-related events
Mach port events
Custom events that you trigger

Dispatch source도 GCD 기술 중 하나

Operation Queues

Operation Queue는 concurrent dispatch queue와 동등한 Cocoa이다. 그리고 NSOperationQueue 클래스에 의해 구현되어있다. Dispatch Queue는 언제나 FIFO로 실행되지만, Operation Queue는 task의 실행 순서를 결정할 때 다른 factor도 계산에
넣는다. 이런 factor중 중요한 점은 주어진 task가 다른 task의 완성에 영향을 받는지 안받는지 이다.
task를 정의할 때 이런 의존도를 설정할 수 있다. Operation Queue 에 보내는 task는 NSOperation의 instance여야한다. Operation Object는 Objective-C 객체이고, 수행했으면 하는 일과 그 일에 필요한 데이터가 요약되어있다. NSOperation은 기본적으로 base 클래스를 상속받기 때문에, 보통 task를 수행하게 하기 위해서 커스텀한 서브클래스를 정의한다. Foundation 프레임워크가 이런 서브클래스들을 정해서 포함하고 있다. Operation 객체는 Key-value observing (KVO)
노티피케이션을 만드는데, 이건 task의 처리가 어떻게 되어가는지 모니터링하기에 좋다. Operation 큐가 언제나 operation을 concurrently하게 실행을 하더라도, dependency를 이용해서 필요하면 순차적으로 실행되게 할 수 있다.

Asynchronous Design techniques

코드가 Concurrency 하도록 디자인을 다시 고려할 때, 이게 정말 필요한건지 생각해볼 필요가 있다.
Concurrency 메인 스레드가 사용자 이벤트에 편하게 응답하도록 코드의 반응이 빨라지게 개선할 수 있다. 코어 를 더 써서 일을하게 만들어서 효율적으로 코드가 돌게 할 수도 있다. 그렇지만 코드의 복잡성과 오버헤드는 증가한다. 코드 쓰기도 힘들게 하고 디버깅 하기도 힘들게 된다. 디자인을 잘 하지않으면 더 느려질 수 있기 때문에 조심해야 한다.
어플리케이션마다 다른 요구사항과 task일이 다르기 때문에 가이드를 정할 수는 없다.

Define Your Application’s Expected Behavior
어플리케이션이 무슨 일을 할지 이해하면, 디자인이 결정된다. 처음 해야 할 일은 어플리케이션이 수행하는 일과 그 task 에 연관된 객체나 데이터 구조를 열거해야 한다. 처음에는 사용자가 메뉴 버튼을 눌러서 시작하는 task가 있을수도 있고, 사용자와는 상관없는 타이머 기반의 task가 있을 수 있다.
high-level의 task를 나열한 후, 각 task를 작은일로 쪼갠다. 그리고 각 객체와 데이터 구조의 의존성도 확인해야한다. 예를들어 배열을 여러 객체에서 고칠 때, 다른 객체도 그 사실을 알아야 한다. 아니면 그 배열이 각 객체마다 독립적으로 수정된다면, concurrent하게 수행되도 된다.

Factor Out Executable Units of Work
dispatch queue와 operation queue를 쓰는 장점은 기존의 스레드를 쓰는 것보다 많은 경우에 cost가 적게 든다. 언제나 성능을 측정하고 task의 사이즈를 알맞게 적용해야 하지만, 너무 task를 작게 고려하지 않아도 된다.

Identify the Queue You Need
task를 블락 객체나 Operation 객체를 이용해서 작게 만들었으면, 이제 큐를 정해야 한다. 만약 블락을 써서 task를 구현하면, 순차적이나 동시적으로 큐에 추가할 수 있다.
정해진 순서대로 실행을 해야되면, 순차적인 dispatch 큐에다가 블락을 추가해야한다. 순서가 필요하지않으면 concurrent dispatch 큐에 블락을 추가하거나 몇개의 다른 큐들에다가 추가를 할 수 있다. Operation 객체를 써서 task를구현하면, 큐에대한 선택보다는 객체에 더 신경을 쓴다. operation 객체를 순차적으로 실행하기위해서, 객체와 관계된 의존성을 신경써야한다.

Tips for Improving Efficiency

메모리 사용을하면 값을 task 안에서 직접적으로 계산하는걸 고려해야한다.  
직접 값을 계산하는게 메인 메모리에 캐쉬 된 값을 로딩하는 것보다 빠르다. 레지스터나 프로세서 코어의 캐쉬를 사용해서 직접 값을 계산하는게, 메인메모리보다 빠르다.
순차적인 task를 먼저 확인하고, 더 concurrent하게 처리할 수 있도록 한다.
공유된 자원때문에 순차적으로 실행되어야 한다면, 그 공유된 자원을 지우도록 설계를 바꾸는걸 고려해보는게 좋다. 리소스의 카피를 만들 수도 있다.
lock 거는걸 피하는게 좋다.
이걸 위해서 dispatch queue나 operation queue는 lock을 대부분의 상황에서 필요없게만들고 있다. 공유된 자원에 lock을 거는 것 보다는 순차적인 큐를 써서 task를 실행하는게 더 낫다.
가능하다면 시스템 프레임워크에 의존해라. 
가장 좋은 concurrency의 이점을 얻는 방법은 시스템 프레임워크에서 제공해주는 것을 이용하는 것이다. 많은 프레임워크들이 concurrent한 것을 구현하기 위해서 내부적으로 스레드랑 다른 기술을 사용하고 있다.

Performance Implications

Operation Queue, dispatch queue, dispatch source가 코드를 concurrent하게 하는데 도움을 많이 주지만 무조건 어플리케이션이 개선되고 효율적으로 된다는 보장은 없다. 이건 여전히 큐를 사용하는 개발자의 책임이다. 예를들어 10000개의 operation 객체를 만들어서 큐에 넣을수는 있더라도 어플리케이션이 적지않은 양의 메모리를 할당하게 만들고, 페이징을 유발하거나 성능이 좋지않게 만들게 된다. 툴을 이용해서 이런 성능을 체크 해 보는게 좋다.

Concurrency and Other Technologies

OpenCL Threads 오퍼레이션 큐랑 디스페치 큐가 task를 동시적으로 수행하는데 선호되는 방식이라 하더라도, 만병통치약은 아니다. 어플리케이션에 따라서 커스텀 스레드를 만들 필요도 있다. 만약 커스텀 스레드를 만든다면 가능하면 스레드를 조금 만들려고 노력하고, 딱 필요한 task만 사용하도록 해야한다. 스레드는 여전히 실시간으로 코드가 실행되도록 구현하는데 좋은 방법이다. 디스페치 큐가 가능하면 task가 빨리 실행되도록 하지만 실시간은 아니다. 만약 백그라운드에서 예측할수있는 일을 하는 코드를 실행하려면, 스레드가 여전히 좋은 방법이다.

링크 : 애플
iOS 개발자 사이트 

Core Data Performance

Entity가 Attribute와 Property를 많이 가지고 있더라도 10000 개의 객체는 Data set으로는 꽤 작은 사이즈로 고려한다.

Fetching Managed Objects

가능하면 request 숫자를 줄이고, 메모리에 있는 객체의 숫자를 최소화

Fetch Predicates

어떻게 predicate를 사용하냐에 따라서 성능에 상당히 영향을 줄 수 있다. 만약에 fetch request가 predicate를 복합적으로 해야한다면, 가장 제한적인 predicate를 먼저 써서 좀 더 효율적으로 fetch할 수 있다. 특히 predicate가 텍스트 매칭(contains, endWith, like, matches) 을 포함할 때 좋다. 왜냐하면 정확한 Unicode 검색이 느리기 때문이다.
만약에 텍스트랑 텍스트가 아닌 비교가 섞여 잇으면, 텍스트가 아닌 predicate를 먼저 사용하는게 좋다. ex > (salary > 5000000) AND (lastName LIKE ‘Quincey’)

predicate guide 

참고 : ios developer site

About GCD

GCD를 알아보게 되었는데, 알아본걸 요약하면, GCD 는 스레드가 사용하고 관리하기 어려우니 기존의 스레드를 대체하기 위해 프레임워크에서 제공해주는 기술 중 하나다. 다른 기술은 NSOperation 이다.

각자 사용방법도 조금씩 다르고, 장단점도 있어서 레퍼런스 문서를 보며 더 알아봐야 할 것 같다.

GCD와 NSThread의 차이점

Dispatch의 이점

필요한 코드를 간단하게 줄여서 쉽게 사용할 수 있다. 그리고 여러모로 효율적으로 구현되어있다. (예를들어 커널 콜을 하는 경우를 줄였다든지 하는 경우)

Thread의 이점

Dispatch 큐는 만병통치약이 아니다. Dispatch 큐가 지원하는 async 모델은 latency가 별로 문제가 되지 않을 경우에 적절하다.
Dispatch 큐 안에 있는 task가 우선순위를 준다고 해도, 높은 우선순위를 가진 task가 원하는 시간에 실행된다는 보장이 없다.
그래서, 오디오나 비디오 재생을 하는 경우 같이 최소한의 latency가 필요한 경우에는 스레드를 사용하는 것이 더 적절하다.

링크 : http://stackoverflow.com/questions/9238135/grand-central-dispatch-vs-nsthreads

NSOperationQueue 와 GCD의 차이점

기능

NSOperation은 GCD를 이용하도록 만들어졌다. 결국 NSOperation을 써도 GCD를 쓰는게 된다.
차이점이 있다면 NSOperation은 부피가 크다. 그리고 써줘야 할 코드가 많다. 대신 그만큼 기능도 많다.

NSOperationQueue를 쓰는 이유는 기능이 더 많기 때문이다. 아래 기능들이 필요하다면 NSOperation을 사용하는 것이 적절할 것 같다.

    • Older OS support
    • KVO on operation properties
    • Dependencies
    • Queue width limiting (although you can do this fairly easily in GCD with dispatch_semaphore_t)

실행방법

Operation 큐는 순차적으로 보여도 내부에서 스레드를 만들어서 쓰기 때문에 concurrent하게 실행된다. 실행되는 max 숫자를 1로 설정해도 우선순위나 의존도에 따른 준비된 정도에 따라 실행순서가 달라질수 있다.

Dispatch 큐는 순차적인 큐가 있다. 그리고 실행되는 순서는 FIFO이다.

링크 : http://stackoverflow.com/questions/8033465/nsoperationqueue-vs-gcd

Union

기억이 안나서, 오랜만에 찾아본..

1. Union (공용체)

Union은 구조체랑 문법이 비슷하고, 사용법도 비슷하지만 주소를 공유하냐 안하냐의 차이를 가지고 있다.

예를들어,

struct {int a; short b}

구조체는 메모리를 [a | b] 이렇게 int 4바이트, short 2 바이트를 차지를 한다.

하지만,

union {int a; short b}

공용체는 가장 큰 메모리인 int 4바이트를 차지한다.
[  a  ]
[ b   ]

참조 : http://en.wikipedia.org/wiki/Union_type

2. 사용하는 경우

보통 같은 값이지만, 타입을 바꿔서 사용할 경우에 자주 사용한다고 한다.

union
 {
 int i;
 float f;
 } u;
// Convert floating-point bits to integer:
 u.f = 3.14159f;
 printf("As integer: %08x\n", u.i);

출처 : http://stackoverflow.com/questions/252552/why-do-we-need-c-unions

Should

should가 개인적인 반응, 감정을 나타낼 때도 쓰인다.

He was shocked that Julie should have given him a cold answer.

줄리로부터 쌀쌀맞은 대답을 듣고 그는 기가 막혔다.

I’m sorry you should think I did it on purpose.

내가 고의적으로 그렇게 했다고 생각하다니 유감이다.

Quote about Rudeness

TCT 책 보다가 좋은 구문을 발견했다

Rudeness is often a sign of weakness. A rude man is secretly convinced of his own inferiority.

다른사람에게 무례한 사람은 흔히 자신이 약하다는 것을 나타낸다는 것으로,
속으로는 자신이 다른 사람보다 열등하다는 사실을 알고 있다는 내용이다.

왠지 모르게 기억하고 싶어서 적어놓고 싶었다.
남에게 좋은 태도로 있어야지… 하는 마음에 🙂

arc4random()

랜덤함수를 쓰다가 arc4random() 이라는 함수를 알게 되었다.
이 함수는 iPhone에 설치된 몇가지 랜덤함수 중 하나인데, 보통 rand() 함수 쓰는 것보다 좋은 점이 몇가지 있다.

1.srandom(time(NULL))을 사용할 필요가 없다.

arc4random()함수를 쓸 경우 자동적으로 seed를 하기 때문에, seed할 필요가 없다.

2.리턴받는 숫자의 범위가 넓다.

아이폰에서 RAND_MAX 숫자는 0x7fffffff (2147483647), arc4random() 은 최대값이 0x100000000 (4294967296) 이다.

사용방법

기존 랜덤함수와 비슷하다.

int r = arc4random() % 10; //0-9 범위안의 숫자를 받는다.
참고 링크 : http://iphonedevelopment.blogspot.kr/2008/10/random-thoughts-rand-vs-arc4random.html

CGRectContainsPoint()

지금 현재 터치하고 있는 곳이 특정 뷰 안에 있는지 확인하고 싶을 때,
직접 계산을 해야하나 했는데 그전에 찾아보니 CGRectContainsPoint(CGRect rect, CGPoint point) 라는 함수가 있었다.

/* Return true if `point' is contained in `rect', false otherwise. */
CG_EXTERN bool CGRectContainsPoint(CGRect rect, CGPoint point)
  CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
예제
 CGPoint currPoint = [touch locationInView:self.view];
 UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
 if (CGRectContainsPoint(v.frame, currPoint))
     return YES;