BLOG main image
분류 전체보기 (92)
Cocoa Touch (11)
Cocoa (10)
Objective-C (13)
Swift (6)
Development (11)
Tools (11)
Books (7)
etc (21)
Application release (1)
Document Project (1)
105,874 Visitors up to today!
Today 0 hit, Yesterday 3 hit
daisy rss
tistory 티스토리 가입하기!
'Cocoa'에 해당되는 글 10건
2014. 4. 25. 13:35

프로젝트를 진행하면서 은근히 Class Cluster 객체를 상속받아 사용하는 경우가 많았는데 치명적인 문제점을 만났습니다.

다름이 아니라 NSKeyedArchiver를 통해 archiving한 객체를 NSKeyedUnarchiver를 통해 decode하면 상속받은 오브젝트로 만들어지지 않고 superclass의 오브젝트로 만들어지는군요.


즉, NSArray를 상속받아 MyArray를 만들었는데 그것을 인코딩/디코딩하면 결과물이 NSArray로 나옵니다. (헛)


일단 방법이 없나 찾아봤는데 아직은 뾰족한 방법을 찾지 못했습니다. (뭔가 있을것 같기는 한데 말이죠.)

시간을 두고 방법이 있는지 계속 확인은 해보겠지만... 현재로서는 조금 회의적입니다.

만일 정말 방법이 없다면... Class Cluster객체의 상속을 조금 자제해야 할 것 같습니다. T_T

Name
Password
Homepage
Secret
2014. 2. 18. 12:10

Localize작업을 하다보면 언어에 따라 formatting이 바뀌는 경우가 있습니다.

예를 들면 영어 문장이 아래와 같다면


“You ate 2 apples during 30 minutes.”


한국어 문장은 


“당신은 30 분 동안 2 개의 사과를 먹었다.”


이렇게 되겠지요.


이것을 리소스 파일로 만들게 되면 아래와 같을 것입니다.


“You ate %d apples during %d minutes.” = “당신은 %d 분 동안 %d 개의 사과를 먹었다.”


문제는 영문에서의 아규먼트의 순서는 갯수-시간인데 비해 한국어는 시간-갯수가 됩니다.


이런 경우 문장을 수정해서 순서를 맞추는 방법도 있겠지만 결과물의 문장이 영 깔끔하지 않습니다.

이에, 해당 이슈를 처리할 방법이 있는지 구글링 해보았는데 아래와 같은 방법으로 처리가 가능하다는 글을 보았습니다. 저 역시 바로 떠오른 생각은 그랬고요.


“You ate ${count} apples during ${time} minutes.” = “당신은 ${time} 분 동안 ${count} 개의 사과를 먹었다.”


localized string을 만들때 ${}로 둘러싼 키 값에 해당 스트링으로 교체해주는 방법인데요, 이 방법은 NSLocalizedString을 바로 사용할 수 없을 뿐더러 해당 처리를 해주는 별도의 코드를 작성할 필요가 있습니다.


이 이야기를 자바 개발자에게 했더니…


“You ate %1$s apples during %2$s minutes.”같이 아규먼트에 인덱스를 줄 수 있다고 하네요.


아… 이런 Objective-C를 쓰면서 자바가 부럽긴 처음이었습니다.


그래서 시간 여유가 있어서 생각했던 모듈을 만들려고 애플 문서를 뒤적거리는 중에 아래와 같은 부분을 발견했습니다.


“One problem that often occurs during translation is that the translator may need to reorder parameters inside translated strings to account for differences in the source and target languages. If a string contains multiple arguments, the translator can insert special tags of the form n$ (where n specifies the position of the original argument) in between the formatting characters. These tags let the translator reorder the arguments that appear in the original string. The following example shows a string whose two arguments are reversed in the translated string:”


/* Message in alert dialog when something fails */


"%@ Error! %@ failed!" = "%2$@ blah blah, %1$@ blah!";


아아… 이런… 제가 공부를 너무 안했던 것이지요. Cocoa Framework에서도 이런 방법을 제공하고 있었던 것입니다.

상당히 민망해지는군요. :$



[..’] | 2014.02.27 06:15 | PERMALINK | EDIT/DEL | REPLY
OS X 10.9 / iOS 7에선 더 좋아졌죠. 혹시 아직 안보셨으면 Foundation 10.9 Release Notes의 맨 마지막 색션 보시면 재미있을 겁니다. 이런데다 슬적 끼워놓은게 맘에안들긴 하지만요.
https://developer.apple.com/librarY/mac/releasenotes/Foundation/RN-Foundation/index.html
maccrazy | 2014.03.03 11:05 신고 | PERMALINK | EDIT/DEL
앗. 안녕하세요~ 요즘 블로그 방문자가 별로 없어서 자주 안 들어와보게 되는데 그새 왔다가셨네요. :) 알려주신 링크 보니까 재미있네요. 이런걸 왜 이제야 넣었을까요? T_T 그나저나 잘 지내시죠? 블로그는 왜 닫으셨어요?
han9kin | 2015.03.02 00:33 신고 | PERMALINK | EDIT/DEL | REPLY
헛... "%1$s" 이거 printf에서부터 지원하는 건데...
man fprintf 하시면 자세한 설명이...
maccrazy | 2015.05.06 10:25 신고 | PERMALINK | EDIT/DEL
잇히히~ 어이야디야~ 나날이 바보되는 느낌.
Name
Password
Homepage
Secret
2013. 10. 31. 12:36

오래된 기억이라 정확 할지는 모르겠지만, 예전의 Cocoa Framework에서는 collection class들의 subclass들은 만들지 말라고 했던것 같은데 Class Cluster에 대한 문서를 보다보니 이제는 collection class들의 subclass를 만드는 방법을 설명하고 있군요.


두가지 방법의 서브클래싱이 가능한데 그것은 아래와 같습니다.


1. True Subclass


True subclass는 클래스 내부의 데이터 모델을 직접 설계할 때 사용하는 방법을 지칭합니다. 즉, NSArray라면 NSArray를 상속 받지만 실제 데이터가 저장되는 모양은 모두 직접 만든다는것인데요, abstract superclass를 상속 받은 후 initializer method와 primitive methods들만 구현해주면 됩니다.

primitive method가 구현되면 나머지 메소드들은(derived methods) 모두 제대로 동작합니다. 예를 들면 NSArray의 경우 primitive method로 count와 objectAtIndex만 있습니다.



2. Compsite 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을 한다던지, 데이터 처리 자체를 변경하지 않는 범위에서 무엇인가 추가작업을 간결하게 하고자 하면 유용할듯 합니다.


부연설명들.


1. Class Cluster


Class Cluster는 abstract factory pattern의 확장입니다. 동일한 하나의 인터페이스 하에 다양한 구현들이 존재하는데 initializer의 선택에 맞게 가장 알맞은 형태의 구현 객체를 사용하게 되는 패턴입니다. 가장 대표적인 예는 NSNumber같은 것이 될 수 있는데 int를 처리하는 클래스와 float을 처리하는 클래스 등등 데이터 형에 맞는 여러개의 클래스가 NSNumber라는 동일한 클래스를 인터페이스로 사용하고 있습니다.


2. primitive method, derived method


이름에서 알 수 있듯이, primitive method를 그 cluster에서 반드시 구현되어야 하는 메소드를 말합니다. derived method는 내부적으로 primitive method를 사용하기 때문에 primitive method만 구현되면 해당 class cluster로 제대로 동작해주게 됩니다.


Name
Password
Homepage
Secret
2010. 9. 19. 22:47
Mac OS X와 iOS의 outlet을 assign으로 할지 retain으로 할지 달라지는 이유는 Nib loading 매카니즘의 차이 때문이다. 이거 두번이나 확인한 건데 분명 몇달 지나면 또 까먹을지도 몰라서 블로깅 해둠.
상세한 설명은... 기억 안나면 그때 다시 문서보면 되지 뭐...
Name
Password
Homepage
Secret
2010. 5. 10. 18:24

직접 세터를 구현해서 사용할 때, 실제로 값이 바뀌지 않아도 노티피케이션이 날아가기 때문에 비효율적일 수도 있으므로 수동으로 노티피케이션을 보낼 필요가 있음. 그때 사용.


요런 설명... This can be useful to help minimize triggering notifications that are unnecessary, or to group a number of changes into a single notification.



+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)aKey

{

    BOOL sAutomatic = NO;

    

    if ([aKey isEqualToString:@"key"])

    {

        sAutomatic = NO;

    }

    else

    {

        sAutomatic = [super automaticallyNotifiesObserversForKey:aKey];

    }

    

    return sAutomatic;

}


Name
Password
Homepage
Secret
2009. 12. 1. 17:54

아무래도 한글을 처리 할 일이 많다.

그 중 소팅은 단연 중요하고 많이 처리되는 일인데, 코코아에서 아래와 같은 코드는 어떤 결과를 보여주게 될까?



NSArray *sTemp        = [NSArray arrayWithObjects:@"하루", @"허씨", @"한국인", @"호빵", @"하늘", nil];

NSArray *sSortedArray = [sTemp sortedArrayUsingSelector:@selector(compare:)];


for (NSString *str in sSortedArray)

{

    NSLog(str);

}



결과

2009-12-01 17:47:58.369 Test[1859:10b] 하늘

2009-12-01 17:47:58.371 Test[1859:10b] 호빵

2009-12-01 17:47:58.372 Test[1859:10b] 한국인

2009-12-01 17:47:58.372 Test[1859:10b] 허씨

2009-12-01 17:47:58.372 Test[1859:10b] 하루


이건 뭐... T_T;;;

(Mac OS X 10.5, 10.6, iPhone 모두에서 발생)


애플에 이야기 하긴 했는데 언제나 고쳐질지는 의문.

difro | 2009.12.01 23:28 | PERMALINK | EDIT/DEL | REPLY
@selector(compare:) 대신 @selector(localizedCompare:) 를 쓰니까 잘 되네요. (Mac 10.6 에서 테스트)
2009-12-01 23:26:36.602 Untitled[4808:a0f] 하늘
2009-12-01 23:26:36.603 Untitled[4808:a0f] 하루
2009-12-01 23:26:36.603 Untitled[4808:a0f] 한국인
2009-12-01 23:26:36.604 Untitled[4808:a0f] 허씨
2009-12-01 23:26:36.608 Untitled[4808:a0f] 호빵
maccrazy | 2009.12.02 09:59 신고 | PERMALINK | EDIT/DEL
흐잇.. 감사합니다. localizedCompare에서는 문제가 없군요. 다른 방법으로 해결했는데 localizedCompare를 쓰는게 더 편하군요. 그래도 compare:쪽 버그도 해결되어야 할 것 같기는 해요.
Name
Password
Homepage
Secret
2009. 2. 13. 14:51
각 "월"과 "주"의 영문 명칭을 꼭 프로그램에 상수로 박아놔야 할까?
그럴 필요가 없다.
NSUserDefaults에는 생각보다 많은 정보들이 저장되어있다.
한번쯤 들여다보면 도움이 될듯하다.

PS. 아놔.. 10.5 이상에서 deprecated...
"월", "주"의 명칭을 받아올려면 NSDateFormatter를 써라네요.
littlehj | 2009.03.04 12:11 신고 | PERMALINK | EDIT/DEL | REPLY
많이 바쁜가 보네? 통 블로그 업데이트가 안되는 걸 보면....ㅎㅎ
Name
Password
Homepage
Secret
2008. 8. 26. 19:18
다음은 NSString에서 지원하는 인코딩들이다.
Western (Mac OS Roman) 0x1e 30 30
Japanese (Mac OS) 0x80000001 2147483649 -2147483647
Traditional Chinese (Mac OS) 0x80000002 2147483650 -2147483646
Korean (Mac OS) 0x80000003 2147483651 -2147483645
Arabic (Mac OS) 0x80000004 2147483652 -2147483644
Hebrew (Mac OS) 0x80000005 2147483653 -2147483643
Greek (Mac OS) 0x80000006 2147483654 -2147483642
Cyrillic (Mac OS) 0x80000007 2147483655 -2147483641
Devanagari (Mac OS) 0x80000009 2147483657 -2147483639
Gurmukhi (Mac OS) 0x8000000a 2147483658 -2147483638
Gujarati (Mac OS) 0x8000000b 2147483659 -2147483637
Thai (Mac OS) 0x80000015 2147483669 -2147483627
Simplified Chinese (Mac OS) 0x80000019 2147483673 -2147483623
Tibetan (Mac OS) 0x8000001a 2147483674 -2147483622
Central European (Mac OS) 0x8000001d 2147483677 -2147483619
Symbol (Mac OS) 0x6 6 6
Dingbats (Mac OS) 0x80000022 2147483682 -2147483614
Turkish (Mac OS) 0x80000023 2147483683 -2147483613
Croatian (Mac OS) 0x80000024 2147483684 -2147483612
Icelandic (Mac OS) 0x80000025 2147483685 -2147483611
Romanian (Mac OS) 0x80000026 2147483686 -2147483610
Keyboard Symbols (Mac OS) 0x80000029 2147483689 -2147483607
Farsi (Mac OS) 0x8000008c 2147483788 -2147483508
Cyrillic (Mac OS Ukrainian) 0x80000098 2147483800 -2147483496
Western (Mac VT100) 0x800000fc 2147483900 -2147483396
Unicode™ (UTF-16) 0xa 10 10
Unicode™ (UTF-8) 0x4 4 4
Western (ISO Latin 1) 0x5 5 5
Central European (ISO Latin 2) 0x9 9 9
Western (ISO Latin 3) 0x80000203 2147484163 -2147483133
Central European (ISO Latin 4) 0x80000204 2147484164 -2147483132
Cyrillic (ISO 8859-5) 0x80000205 2147484165 -2147483131
Arabic (ISO 8859-6) 0x80000206 2147484166 -2147483130
Greek (ISO 8859-7) 0x80000207 2147484167 -2147483129
Hebrew (ISO 8859-8) 0x80000208 2147484168 -2147483128
Turkish (ISO Latin 5) 0x80000209 2147484169 -2147483127
Nordic (ISO Latin 6) 0x8000020a 2147484170 -2147483126
Thai (ISO 8859-11) 0x8000020b 2147484171 -2147483125
Baltic Rim (ISO Latin 7) 0x8000020d 2147484173 -2147483123
Celtic (ISO Latin 8) 0x8000020e 2147484174 -2147483122
Western (ISO Latin 9) 0x8000020f 2147484175 -2147483121
Latin-US (DOS) 0x80000400 2147484672 -2147482624
Greek (DOS) 0x80000405 2147484677 -2147482619
Baltic Rim (DOS) 0x80000406 2147484678 -2147482618
Western (DOS Latin 1) 0x80000410 2147484688 -2147482608
Central European (DOS Latin 2) 0x80000412 2147484690 -2147482606
Turkish (DOS) 0x80000414 2147484692 -2147482604
Icelandic (DOS) 0x80000416 2147484694 -2147482602
Arabic (DOS) 0x80000419 2147484697 -2147482599
Cyrillic (DOS) 0x8000041b 2147484699 -2147482597
Thai (Windows, DOS) 0x8000041d 2147484701 -2147482595
Japanese (Windows, DOS) 0x8 8 8
Simplified Chinese (Windows, DOS) 0x80000421 2147484705 -2147482591
Korean (Windows, DOS) 0x80000422 2147484706 -2147482590
Traditional Chinese (Windows, DOS) 0x80000423 2147484707 -2147482589
Western (Windows Latin 1) 0xc 12 12
Central European (Windows Latin 2) 0xf 15 15
Cyrillic (Windows) 0xb 11 11
Greek (Windows) 0xd 13 13
Turkish (Windows Latin 5) 0xe 14 14
Hebrew (Windows) 0x80000505 2147484933 -2147482363
Arabic (Windows) 0x80000506 2147484934 -2147482362
Baltic Rim (Windows) 0x80000507 2147484935 -2147482361
Vietnamese (Windows) 0x80000508 2147484936 -2147482360
Western (ASCII) 0x1 1 1
Japanese (Shift JIS X0213) 0x80000628 2147485224 -2147482072
Chinese (GBK) 0x80000631 2147485233 -2147482063
Chinese (GB 18030) 0x80000632 2147485234 -2147482062
Japanese (ISO 2022-JP) 0x15 21 21
Korean (ISO 2022-KR) 0x80000840 2147485760 -2147481536
Japanese (EUC) 0x3 3 3
Simplified Chinese (EUC) 0x80000930 2147486000 -2147481296
Traditional Chinese (EUC) 0x80000931 2147486001 -2147481295
Korean (EUC) 0x80000940 2147486016 -2147481280
Japanese (Shift JIS) 0x80000a01 2147486209 -2147481087
Cyrillic (KOI8-R) 0x80000a02 2147486210 -2147481086
Traditional Chinese (Big 5) 0x80000a03 2147486211 -2147481085
Western (Mac Mail) 0x80000a04 2147486212 -2147481084
Traditional Chinese (Big 5 HKSCS) 0x80000a06 2147486214 -2147481082
Western (NextStep) 0x2 2 2
Non-lossy ASCII 0x7 7 7
Western (EBCDIC US) 0x80000c02 2147486722 -2147480574
Name
Password
Homepage
Secret
2008. 7. 29. 16:32
이글루에서 옮겨온 글입니다. 2008/07/28 17:56


예전 소스코드를 정리하다가 갑자기 튀어나온 소스코드가 있어서 정리해두고자 한다.
얼핏 기억에 윈도우용으로 나와있는 모 프로그램을 맥용으로 포팅할 때 BMP파일 처리에서 문제가 있어서 그것을 처리하기 위해서 만든 테스트 코드였던것 같다.

먼저 bmp 파일을 NSData로 읽어들인다.
다음, CreateCGImageFromData함수를 이용해서 CGImageRef로 만들어 준다. CreateCGImageFromData함수는 아래와 같다.
그 과정이 끝나면 CreateMaskedImage 함수를 이용해서 마스크드 이미지를 만든다. CreateMaskedImage함수는 아래와 같다.
마지막으로 CGImageRef로 부터 NSImage를 생성해주는 NSImageFromCGImageRef함수를 이용한다. 역시 아래에...
다 합치면 아래와 같다.
뭐... 또 쓸일이 있을지는 모르겠다. :)
Name
Password
Homepage
Secret
2008. 7. 29. 15:58
이글루에서 옮겨온 글입니다. 2007/02/10 00:48


테이블뷰 안에다 컨트롤셀을 넣었을 때 많은 사람들이 이 셀의 컨트롤에 값을 세팅하는데 어려움을 격고 있는것 같다. 코코아빌더같은 사이트에서도 질문은 많지만 적절한 답을 구하기는 쉽지 않은 것 같다. 이것은 테이블뷰의 구조에 대해서 제대로 이해하지 못해서 발생하는 현상인듯한데 얼마전 코코아의 테이블뷰와 같은 스팩으로 윈도우에서 작동 가능한 컨트롤을 만들면서 여러가지로 테이블뷰를 테스트하고 실제 코딩을 해보면서 어떻게 돌아가는지 어느정도 파악 할 수 있었다.
먼저 테이블에 들어있는 NSActionCell들(?)이 어떻게 저장되어 있는지 알 필요가 있다. 어떻게 들어있는지 알기 위해서 데이타소스의 아래 메시지에서 셀을 꺼내서 출력을 해보았다.
아뿔사... 모두 같은 어드레스를 가지고 있다. 그랬다. 테이블 뷰는 실제로는 단 하나만의 컨트롤을 가지고 있었던 것이다. 그렇다면 이것을 매 row를 표현하거나 값을 넣거나 뺄 때 위치만 바꾸면서 사용했다는 말이된다. 일단 이렇게 되면 값이 이상하게 세팅되는 것에 대한 일부분의 비밀은 풀었다.

그렇다면, 테이블뷰의 데이터는 실제로 데이터 소스에 들어있다는 대전제를 생각하면 모든 컨트롤 셀들의 값들 역시 데이터소스에 있어야 한다는 말이다.
일단 필요한 갯수만큼의 슬라이더 값을 저장할 어레이를 만들었다.
자 그러면 언제 셀에 값을 넣고 뺄 것인가?

일단 먼저 테이블뷰의 기본 사용법에 따라 앞서 열거한 두 메시지에서 셀에 값을 넣고 빼는 작업을 했다.
안된다.. 이것 좀 난감하군...
셀로 부터 변화된 값을 받을 수 없었다. 셀의 값이 바뀌었다고 - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex 메시지에서 셀의 값을 읽어봤자 원래 값만 나온다.

그렇다. 셀 역시 컨트롤이다. 타켓/액션 구조로 작동시켜 보기로 했다. 데이터소스에 액션을 추가하고 셀에 데이터소스가 타겟이라고 세팅했다. 셀의 값이 바뀔 때 적절하게 액션 메시지를 날려준다.
조금 지저분하지만 위와 같은 메시지 핸들러를 작성했다.
그러나 데이터는 정확하게 화면에 나와주지 않았다.

그렇다면 디스플레이 할때 뭔가를 해줄 수 있는 부분은 한군데 밖에 안남았다.
테이블의 딜리게이트를 역시 데이터소스라고 지정해주고 willDisplay를 이용해봤다.
아.. 이제 제대로 나온다...
더 단순한 방법이 있는지 모르겠다. 윈도우에서 보다야 엄청나게 짧은 라인으로 훨씬 많은 기능을 구현하긴 했지만 어쩐지 좀 지저분해보인다.

그래... 자라리 이렇게 할 바에는 커스텀뷰를 테이블뷰에 넣으리... 역시 액션셀은 코코아 바인딩만을 위한 장치란 말인가? 어렴풋한 기억에 의존하면 코코아 바인딩을 이용하면 이 모든 작업이 불필요해진다. 소위 glue code를 제거해준다.(그래도 나는 코코아 바인딩을 쓰고 싶지는 않다. 코드가 쓰기 편하다는 이야기는 그만큼 손댈 수 있는 여지가 적다는 말이기도 하고 코코아 바인딩은 꽤나 느린듯 하다.)

혹시 누가 더 심플한 방법을 알고 있다면 제발 좀 알려줬으면 좋겠다.
Name
Password
Homepage
Secret
prev"" #1 next