<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>han9kin.doesntexist.com</title>
		<link>http://han9kin.doesntexist.com/</link>
		<description>하늘을 날게될 그 날을 꿈꾸며...</description>
		<language>ko</language>
		<pubDate>Fri, 05 Mar 2010 01:34:25 +0900</pubDate>
		<generator>Tistory 1.1 (http://www.tistory.com/)</generator>
		<image>
		<title>han9kin.doesntexist.com</title>
		<url><![CDATA[http://cfs7.tistory.com/upload_control/download.blog?fhandle=YmxvZzE5MzAyMEBmczcudGlzdG9yeS5jb206L2F0dGFjaC8wLzEuZ2lm]]></url>
		<link>http://han9kin.doesntexist.com/</link>
		<description>하늘을 날게될 그 날을 꿈꾸며...</description>
		</image>
		<item>
			<title>GNU GLOBAL 5.7.6 + Objective-C</title>
			<link>http://han9kin.doesntexist.com/45</link>
			<description>&lt;div class=&quot;xhtmlEditorBody&quot;&gt;
&lt;p&gt;Xcode에는 Code Sense라는 멋진 소스 인덱싱 툴이 내장되어 있다. 하지만, 소스 편집기로 Emacs 등의 External Editor를 사용한다면 Code Sense는 별로 도움이 되지 않는다. Code Sense 데이터베이스에 접근할 수 있는 툴을 Apple이 만들어 주지 않는한 외부 편집기에서 Code Sense를 활용할 수 있는 방법은 없는 듯 하다.&lt;/p&gt;
&lt;p&gt;그래서, 이번에는 &lt;a href=&quot;http://www.gnu.org/software/global/&quot; title=&quot;http://www.gnu.org/software/global/&quot; class=&quot;external&quot;&gt;GNU GLOBAL&lt;/a&gt;이 Objective-C를 대충 해석할 수 있도록 패치를 해 보았다.&lt;/p&gt;
&lt;p&gt;원래 GNU GLOBAL은 소스파일을 해석해서 tag를 출력해주는 툴을 아무거나 붙일 수 있도록 되어 있다. 즉, Exuberant Ctags를 사용하여 tagging하고 global을 이용하여 query할 수도 있다는 말이다. 그래서, 처음에는 Objective-C 소스파일에서 tag를 출력해주는 툴을 만들어 GNU GLOBAL에 붙일까 생각했었는데, 귀차니즘이 발동하여 GNU GLOBAL의 C++ 파서를 대충 수정하여 Objective-C tag를 출력하도록 하였다.&lt;/p&gt;
&lt;p&gt;한가지 아쉬운 것은 Objective-C 메소드에 대한&amp;nbsp;reference tag 검색이 안된다는 것. 이건 작업할려다가 포기했다!&lt;/p&gt;
&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://han9kin.tistory.com/attachment/cfile24.uf@12477F134AFD26A40A1CFE.bz2&quot;&gt;&lt;img src=&quot;http://cfs.tistory.com/blog/image/extension/unknown.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; global-5.7.6-objc.tar.bz2&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;아! 실력이 미천하여 버그가 엄청 많이 있을 수 있다!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;
&lt;/div&gt;</description>
			<category>컴퓨팅환경</category>
			<category>emacs</category>
			<category>GNU GLOBAL</category>
			<category>Objective-C</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/45</guid>
			<comments>http://han9kin.doesntexist.com/45#entry45comment</comments>
			<pubDate>Fri, 13 Nov 2009 18:21:18 +0900</pubDate>
		</item>
		<item>
			<title>Change title &amp; button label color of UINavigationBar</title>
			<link>http://han9kin.doesntexist.com/44</link>
			<description>&lt;div class=&quot;xhtmlEditorBody&quot;&gt;
&lt;p&gt;UINavigationBar는 tintColor를 이용해서 색상을 바꿀 수 있다. 하지만, 제목이나 버튼의 글자 색깔을 바꾸는 기능은 제공하지 않고 있다. 이건 참 곤란하다. tintColor를 밝은 색으로 주면 제목과 버튼 글자가 잘 보이지 않는다.&lt;/p&gt;
&lt;p&gt;비록 정상적인 방법은 아니지만, 글자 색깔을 바꾸어 보았다.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;#include &amp;lt;objc/runtime.h&amp;gt;
#include &amp;lt;objc/message.h&amp;gt;


@implementation UIKitHack (UINavigationTextColor)

/*
 * -[UINavigationItemView drawText:inRect:]
 *
 * 이 메소드를 갈아치워서 UINavigationBar의 Title Text Color를 바꿀 수 있다.
 */
static void UINavigationItemView_drawTextInRect(id self, SEL _cmd, NSString *string, CGRect rect)
{
    CGPoint  point = rect.origin;
    UIFont  *font  = [self performSelector:@selector(_defaultFont)];

    /*
     * Draw shadow of string
     */
    point.y += 2;
    [[UIColor whiteColor] set];
    [string drawAtPoint:point forWidth:rect.size.width withFont:font lineBreakMode:UILineBreakModeTailTruncation];

    /*
     * Draw string
     */
    point.y -= 1;
    [[UIColor blackColor] set];
    [string drawAtPoint:point forWidth:rect.size.width withFont:font lineBreakMode:UILineBreakModeTailTruncation];
}


/*
 * -[UIButtonLabel textColor]
 *
 * 이 메소드를 추가하여 Button Text Color를 바꿀 수 있다.
 */
static UIColor *UIButtonLabel_textColor(id self, SEL _cmd)
{
    if ([[self superview] isKindOfClass:NSClassFromString(@&quot;UINavigationButton&quot;)])
    {
        return [UIColor blackColor];
    }
    else
    {
        struct objc_super super = { self, [UILabel class] };

        return objc_msgSendSuper(&amp;amp;super, _cmd);
    }
}


/*
 * -[UIButtonLabel shadowColor]
 *
 * 이 메소드를 추가하여 Button Text Shadow Color를 바꿀 수 있다.
 */
static UIColor *UIButtonLabel_shadowColor(id self, SEL _cmd)
{
    if ([[self superview] isKindOfClass:NSClassFromString(@&quot;UINavigationButton&quot;)])
    {
        return [UIColor whiteColor];
    }
    else
    {
        struct objc_super super = { self, [UILabel class] };

        return objc_msgSendSuper(&amp;amp;super, _cmd);
    }
}


/*
 * -[UIButtonLabel setShadowOffset:]
 *
 * 이 메소드를 갈아치워서 Button Text Shadow Offset을 바꿀 수 있다.
 */
static IMP UIButtonLabel_original_setShadowOffset;
static void UIButtonLabel_setShadowOffset(id self, SEL _cmd, CGSize offset)
{
    if ([[self superview] isKindOfClass:NSClassFromString(@&quot;UINavigationButton&quot;)])
    {
        struct objc_super super = { self, [UILabel class] };

        objc_msgSendSuper(&amp;amp;super, _cmd, CGSizeMake(0, 1));
    }
    else
    {
        UIButtonLabel_original_setShadowOffset(self, _cmd, offset);
    }
}


/*
 * 추가하고 갈아치우는 삽질의 마무리
 */
+ (void)load
{
    Class  class;
    Method method;


    class = NSClassFromString(@&quot;UINavigationItemView&quot;);

    if (class)
    {
        method = class_getInstanceMethod(class, @selector(drawText:inRect:));

        if (method)
        {
            method_setImplementation(method, (IMP)UINavigationItemView_drawTextInRect);
        }
        else
        {
            NSLog(@&quot;-[UINavigationItemView drawText:inRect:] method not found&quot;);
        }
    }
    else
    {
        NSLog(@&quot;UINavigationItemView class not found&quot;);
    }


    class = NSClassFromString(@&quot;UIButtonLabel&quot;);

    if (class)
    {
        class_addMethod(class, @selector(textColor), (IMP)UIButtonLabel_textColor, &quot;@@:&quot;);
        class_addMethod(class, @selector(shadowColor), (IMP)UIButtonLabel_shadowColor, &quot;@@:&quot;);

        method = class_getInstanceMethod(class, @selector(setShadowOffset:));

        if (method)
        {
            UIButtonLabel_original_setShadowOffset = method_setImplementation(method, (IMP)UIButtonLabel_setShadowOffset);
        }
        else
        {
            NSLog(@&quot;-[UIButtonLabel setShadowOffset:] method not found&quot;);
        }
    }
    else
    {
        NSLog(@&quot;UIButtonLabel class not found&quot;);
    }
}

@end
&lt;/pre&gt;
&lt;p&gt;정상적인 방법이 아니므로, 사용 및 응용은 알아서 하시기를...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;
&lt;/div&gt;</description>
			<category>프로그래밍</category>
			<category>cocoa</category>
			<category>UIKit</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/44</guid>
			<comments>http://han9kin.doesntexist.com/44#entry44comment</comments>
			<pubDate>Tue, 20 Oct 2009 12:05:16 +0900</pubDate>
		</item>
		<item>
			<title>Tokyo Cabinet 1.4.33 Universal Package for Mac OS X</title>
			<link>http://han9kin.doesntexist.com/43</link>
			<description>&lt;div class=&quot;xhtmlEditorBody&quot;&gt;
&lt;p&gt;Key-Value pair Database Library 중 하나인 Tokyo Cabinet을 한번 써보기 위해 설치해보았다. 설치한 김에 설치 패키지로 만들어 보았다.&lt;/p&gt;
&lt;p&gt;참고로 Tokyo Cabinet은 hash table, B+ tree, fixed length array 방식을 지원하는 DBM 스타일의 데이터베이스 라이브러리이다. 자세한 내용은 &lt;a href=&quot;http://1978th.net/tokyocabinet/&quot; title=&quot;http://1978th.net/tokyocabinet/&quot; class=&quot;external&quot;&gt;여기&lt;/a&gt;로...&lt;/p&gt;
&lt;p&gt;Universal Binary로 빌드하였고, 사용한 컴파일러, 최소 운영체제 버전은 다음과 같이 맞추었다.&lt;/p&gt;
&lt;table class=&quot;datatable&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;i386&lt;/td&gt;
&lt;td&gt;gcc-4.0&lt;/td&gt;
&lt;td&gt;Mac OS X 10.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;x86_64&lt;/td&gt;
&lt;td&gt;llvm-gcc-4.2&lt;/td&gt;
&lt;td&gt;Mac OS X 10.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ppc&lt;/td&gt;
&lt;td&gt;gcc-4.0&lt;/td&gt;
&lt;td&gt;Mac OS X 10.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ppc64&lt;/td&gt;
&lt;td&gt;gcc-4.2&lt;/td&gt;
&lt;td&gt;Mac OS X 10.5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://han9kin.tistory.com/attachment/cfile1.uf@135071194AB0FD21077E93.zip&quot;&gt;&lt;img src=&quot;http://cfs.tistory.com/blog/image/extension/zip.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; TokyoCabinet-1.4.33.pkg.zip&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;
&lt;/div&gt;</description>
			<category>컴퓨팅환경</category>
			<category>Package</category>
			<category>TokyoCabinet</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/43</guid>
			<comments>http://han9kin.doesntexist.com/43#entry43comment</comments>
			<pubDate>Wed, 16 Sep 2009 23:51:47 +0900</pubDate>
		</item>
		<item>
			<title>Emacs-23.1의 ns-open-file-select-line</title>
			<link>http://han9kin.doesntexist.com/42</link>
			<description>&lt;div class=&quot;xhtmlEditorBody&quot;&gt;
&lt;p&gt;Mac OS X 10.6 Snow Leopard를 설치한 후, 기존의 Emacs.app bundle이 실행되지 않아서 원인을 찾아봤다. 사용하고 있던 Emacs.app은 껍데기 번들로 실제로는 시스템에 기본으로 설치되어 있는 /usr/bin/emacs를 사용하고 있었다.&lt;/p&gt;
&lt;p&gt;그런데, 흐미... 이것은 무엇일까... Snow Leopard에 기본 설치되어 있는 /usr/bin/emacs 바이너리는 universal binary로 x86_64를 포함하고 있었다. 아직 Mac OS X 64비트로 포팅이 되지도 않은 카본 Emacs를 애플이 했을리는 없을 것이고. 이것은 터미널 전용 emacs? 너무 하잖아.. 10.5에서 되던 것을 고작 64비트 때문에 기능을 빼버려? 젠장...&lt;/p&gt;
&lt;p&gt;별 수 없이 emacs 소스 받아다가 컴파일하기로 했다. 그 사이 emacs 23버전은 카본이 아니라 코코아로 바뀌어 있었다. 그런데, 심각한 문제는 Xcode에서 파일을 열 때 해당 라인이나 범위를 highlight해주는 기능이 안되고 있었다. 허걱.. 이거 분명 이전 버전에서는 잘 되던 것인데... 소스 확인 시작...&lt;/p&gt;
&lt;p&gt;소스를 확인해 보니, 기존의 카본 코드들을&amp;nbsp;아주 깨끗이 지우고&amp;nbsp;코코아 포트를 추가해 놨다. 그리고, 코코아 코드에는 이 기능이 구현되어 있지 않았다...&lt;/p&gt;
&lt;p&gt;별 수 있나... 또 해야지뭐...&lt;/p&gt;
&lt;p&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;a href=&quot;http://han9kin.tistory.com/attachment/cfile3.uf@1219660B4A9CEAFD6B3A0A.gz&quot;&gt;&lt;img src=&quot;http://cfs.tistory.com/blog/image/extension/gz.gif&quot; alt=&quot;&quot; style=&quot;vertical-align: middle;&quot; /&gt; ns-open-file-line.diff.gz&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;
&lt;/div&gt;</description>
			<category>컴퓨팅환경</category>
			<category>emacs</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/42</guid>
			<comments>http://han9kin.doesntexist.com/42#entry42comment</comments>
			<pubDate>Tue, 01 Sep 2009 18:22:55 +0900</pubDate>
		</item>
		<item>
			<title>UIActionSheet 또는 UIAlertView의 Delegate 구현</title>
			<link>http://han9kin.doesntexist.com/41</link>
			<description>&lt;div class=&quot;xhtmlEditorBody&quot;&gt;
&lt;p&gt;이 포스팅 제목 뽑기 참 힘들었다... 지금도 마음에 안 들지만, 그냥 할련다. 내가 원래 그렇지...&lt;/p&gt;
&lt;p&gt;iPhone Application 개발을 하다보면 가끔 참 황당하기 짝이없는 API들을 보는 경우가 있는데, 오늘 소개할 것은 UIActionSheet와 UIAlertView다. 사실, 이 둘은 생긴 모양은 다르지만, API생김새는 거의 똑같다. 그러므로 예는 모두 UIActionSheet를 사용하겠다.&lt;/p&gt;
&lt;p&gt;먼저, UIActionSheet를 띄워보자.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;UIActionSheet *actionSheet;

actionSheet = [[UIActionSheet alloc] initWithTitle:@&quot;뭐하실래요?&quot;
                                          delegate:self
                                 cancelButtonTitle:@&quot;됐어요&quot;
                            destructiveButtonTitle:@&quot;약주세요&quot;
                                 otherButtonTitles:@&quot;밥사주세요&quot;, @&quot;술사주세요&quot;, nil];

[actionSheet showInView:[self view]];
[actionSheet release];
&lt;/pre&gt;
&lt;p&gt;이제는 UIActionSheetDelegate 메소드 중 마음에 드는 것을 하나 골라 어떤 버튼이 눌렸는지 확인하여 실행에 옮길 차례다.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == [actionSheet destructiveButtonIndex])
    {
        [self drug];
    }
    else if (buttonIndex == [actionSheet firstOtherButtonIndex])
    {
        [self dinner];
    }
    else if (buttonIndex == ([actionSheet firstOtherButtonIndex] + 1))
    {
        [self drink];
    }
}
&lt;/pre&gt;
&lt;p&gt;만약, 버튼이 더 추가되거나 순서가 바뀌거나 하면... 여러 종류의 ActionSheet를 띄워야하는 ViewController라면... 생각만 해도 악몽이다. UIActionSheet의 designated initializer가 아니라 -addButtonWithTitle: 메소드를 사용하여 버튼을 추가하면서 각각의 button index를 가지고 있게 하면 그나마 낫겠지만, 그것도 그리 마음에 드는 방법은 아니다.&lt;/p&gt;
&lt;p&gt;그래서, 별 수 없이 button title을 key로, 메소드 셀렉터를 value로 하는 dictionary를 만들어 사용해봤다.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;static NSDictionary *actionSheetActions = nil;

+ (void)initialize
{
    if (!actionSheetActions)
    {
        actionSheetActions = [[NSDictionary alloc] initWithObjectsAndKeys:
                                                       @&quot;drug&quot;,   @&quot;약주세요&quot;,
                                                       @&quot;dinner&quot;, @&quot;밥사주세요&quot;,
                                                       @&quot;drink&quot;,  @&quot;술사주세요&quot;,
                                                       nil];
    }
}

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (buttonIndex != [actionSheet cancelButtonIndex])
    {
        SEL selector = NSSelectorFromString([actionSheetActions objectForKey:[actionSheet buttonTitleAtIndex:buttonIndex]]);

        if (selector)
        {
            [self performSelector:selector];
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;낡고 느린 방법이긴 하지만, 나는 이게 더 좋아보인다. 아... 이렇게까지 해야하는지...&lt;/p&gt;
&lt;p&gt;PS) 이 예제에서 사용한 코드는 보기 쉽게 하기 위해 일부러 NSLocalizedString()을 사용하지 않고 한국어 타이틀을 코드에 집어넣었다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;
&lt;/div&gt;</description>
			<category>프로그래밍</category>
			<category>cocoa</category>
			<category>UIKit</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/41</guid>
			<comments>http://han9kin.doesntexist.com/41#entry41comment</comments>
			<pubDate>Sat, 18 Jul 2009 00:20:00 +0900</pubDate>
		</item>
		<item>
			<title>Objective-C Method Hooking</title>
			<link>http://han9kin.doesntexist.com/40</link>
			<description>&lt;p&gt;이런 거를 Hooking이라고 표현해도 되는지 잘 모르겠다만...&lt;/p&gt;
&lt;p&gt;가끔씩 카테고리를 사용해서 기존의 메소드를 덮어쓰는게 아니라 기존의 메소드를 그냥 놔두고 나의 코드를 삽입하고 싶은 경우가 있을 수 있다. LD_PRELOAD를 이용해서 원래 함수의 실행을 가로막고 뭔가 할 수 있는 것처럼...&lt;/p&gt;
&lt;p&gt;Objective-C Runtime API를 이용하면 가능하다. 원리는 기존 메소드를 다른 이름으로 복사하고 새로운 메소드를 같은 이름으로 추가하는 것이다. 그러면 새로운 메소드에서 필요시 기존 메소드를 호출할 수 있다.&lt;/p&gt;
&lt;p&gt;다음 예제는 NSView의 -addSubview: 메소드앞단에 로그찍는 코드를 끼워넣은 것이다.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;#import &amp;lt;objc/runtime.h&amp;gt;

@implementation NSView (Logging)

static void addSubviewLogging(id self, SEL _cmd, NSView *aView)
{
    NSLog(@&quot;-[%@ addSubview:%@]&quot;, self, aView);

    [self addSubviewReal:aView];
}

+ (void)load
{
    class_addMethod(self, @selector(addSubviewReal:), [self instanceMethodForSelector:@selector(addSubview:), &quot;v@:@&quot;);
    class_replaceMethod(self, @selector(addSubview:), (IMP)addSubviewLogging, &quot;v@:@&quot;);
}

@end
&lt;/pre&gt;
&lt;p&gt;이 코드는 단지 예제일 뿐... 응용은 알아서...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;
</description>
			<category>프로그래밍</category>
			<category>Objective-C</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/40</guid>
			<comments>http://han9kin.doesntexist.com/40#entry40comment</comments>
			<pubDate>Fri, 22 May 2009 12:08:10 +0900</pubDate>
		</item>
		<item>
			<title>Tracing All Objective-C Messages</title>
			<link>http://han9kin.doesntexist.com/39</link>
			<description>&lt;p&gt;환경변수 NSObjCMessageLoggingEnabled를 YES로 세팅하고 코코아 응용프로그램을 실행하면 응용프로그램에서 발생하는 모든 Objective-C 메세징을 로그파일에 써준다. 로그파일은 /tmp/msgSends-PID.&lt;/p&gt;
&lt;p&gt;하지만, 이거는 도움이 될 수가 없다. 워낙 많은 메세징이 발생하기 때문... 원하는 것은 특정 부분에서 어떤 메세징이 발생하는지가 될 것이다.&lt;/p&gt;
&lt;p&gt;소스코드상에서 다음과 같이 관심있는 부분 앞뒤로 메세지 로깅을 켜고 끌 수 있다.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;instrumentObjcMessageSends(YES);

/* 메세징 로깅을 원하는 코드 */

instrumentObjcMessageSends(NO);
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;
</description>
			<category>컴퓨팅환경</category>
			<category>logging</category>
			<category>Objective-C</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/39</guid>
			<comments>http://han9kin.doesntexist.com/39#entry39comment</comments>
			<pubDate>Wed, 20 May 2009 17:26:58 +0900</pubDate>
		</item>
		<item>
			<title>OBJC_HELP 환경변수</title>
			<link>http://han9kin.doesntexist.com/38</link>
			<description>&lt;p&gt;환경변수 OBJC_HELP를 1로 세팅하고 파운데이션 프로그램을 실행시키니 이런 것이 나오네...&lt;/p&gt;
&lt;p&gt;도움이 될 만한 것이 있을지도...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc:nogutter:nocontrols&quot;&gt;objc[31709]: OBJC_HELP: describe Objective-C runtime environment variables
objc[31709]: OBJC_PRINT_OPTIONS: list which options are set
objc[31709]: OBJC_PRINT_IMAGES: log image and library names as they are loaded
objc[31709]: OBJC_PRINT_LOAD_METHODS: log calls to class and category +load methods
objc[31709]: OBJC_PRINT_INITIALIZE_METHODS: log calls to class +initialize methods
objc[31709]: OBJC_PRINT_RESOLVED_METHODS: log methods created by +resolveClassMethod: and +resolveInstanceMethod:
objc[31709]: OBJC_PRINT_CLASS_SETUP: log progress of class and category setup
objc[31709]: OBJC_PRINT_PROTOCOL_SETUP: log progresso of protocol setup
objc[31709]: OBJC_PRINT_IVAR_SETUP: log processing of non-fragile ivars
objc[31709]: OBJC_PRINT_FUTURE_CLASSES: log use of future classes for toll-free bridging
objc[31709]: OBJC_PRINT_RTP: log initialization of the Objective-C runtime pages
objc[31709]: OBJC_PRINT_GC: log some GC operations
objc[31709]: OBJC_PRINT_SHARING: log cross-process memory sharing
objc[31709]: OBJC_PRINT_CXX_CTORS: log calls to C++ ctors and dtors for instance variables
objc[31709]: OBJC_PRINT_EXCEPTIONS: log exception handling
objc[31709]: OBJC_PRINT_ALT_HANDLERS: log processing of exception alt handlers
objc[31709]: OBJC_PRINT_REPLACED_METHODS: log methods replaced by category implementations
objc[31709]: OBJC_PRINT_DEPRECATION_WARNINGS: warn about calls to deprecated runtime functions
objc[31709]: OBJC_PRINT_CACHE_COLLECTION: log cleanup of stale method caches
objc[31709]: OBJC_DEBUG_UNLOAD: warn about poorly-behaving bundles when unloaded
objc[31709]: OBJC_DEBUG_FRAGILE_SUPERCLASSES: warn about subclasses that may have been broken by subsequent changes to superclasses
objc[31709]: OBJC_DEBUG_FINALIZERS: warn about classes that implement -dealloc but not -finalize
objc[31709]: OBJC_DEBUG_NIL_SYNC: warn about @synchronized(nil), which does no synchronization
objc[31709]: OBJC_USE_INTERNAL_ZONE: allocate runtime data in a dedicated malloc zone
objc[31709]: OBJC_ALLOW_INTERPOSING: allow function interposing of objc_msgSend()
objc[31709]: OBJC_DISABLE_GC: force GC OFF, even if the executable wants it on
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;
</description>
			<category>프로그래밍</category>
			<category>Objective-C</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/38</guid>
			<comments>http://han9kin.doesntexist.com/38#entry38comment</comments>
			<pubDate>Wed, 20 May 2009 16:10:01 +0900</pubDate>
		</item>
		<item>
			<title>NSOperationQueue를 이용한 Asynchronous NSURLConnection 구현</title>
			<link>http://han9kin.doesntexist.com/37</link>
			<description>&lt;p&gt;NSFileHandle이나 NSURLConnection은 Async I/O를 위해 내부적으로는 쓰레드를 사용하지만, I/O 이벤트가 발생했을 때 delegate를 호출해주는 편리한 인터페이스를 제공하고 있다. 다만, delegate 객체는 진행중인 I/O에 대한 상태관리(?)를 해야한다. 상태관리라니 뭔가 거창하게 해야하는 건 아니고, 현재까지 수행해야할 또는 완료된 I/O 데이터를 가지고 있어야 한다든지, 오류가 발생했을 때 대처해야 한다던지... 뭐, 그런 것들...&lt;/p&gt;
&lt;p&gt;문제는 이러한 I/O가 동시 다발적 또는 산발적으로 마구 발생하는 경우는 일일이 다루기가 귀찮아질 수 있다. 그래서, NSOperationQueue를 이용해 보기로 했다. 다음 예제는 NSOperation의 서브클래스로, NSURLConnnection을 이용하여 서버에서 데이터를 다운받아 넘기는 간단한 것이다.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;@interface URLDownload : NSOperation
{
    NSURLConnection *connection;
    NSMutableData   *data;

    BOOL             executing;
    BOOL             finished;

    id               delegate;
    SEL              selector;
}

/*
 * delegate method의 signature는 다음과 같다.
 *  - 리턴타입:    void
 *  - 첫번째 인자: download operation 객체 (URLDownload *)
 *  - 두번째 인자: 다운받은 데이터 객체 (NSData *)
 *  - 세번째 인자: 에러 객체 (NSError *)
 */
- (id)initWithRequest:(NSURLRequest *)aRequest delegate:(id)aDelegate selector:(SEL)aSelector;

@end


@implementation URLDownload

- (id)initWithRequest:(NSURLRequest *)aRequest delegate:(id)aDelegate selector:(SEL)aSelector
{
    self = [super init];

    if (self)
    {
        connection = [[NSURLConnection alloc] initWithRequest:aRequest delegate:self startImmediately:NO];
        delegate   = aDelegate;
        selector   = aSelector;
    }

    return self;
}

- (void)dealloc
{
    [connection release];
    [data release];
    [super dealloc];
}


#pragma mark overrides for concurrent operation

/*
 * concurrent operation을 위해서는 다음의 메소드를 오버라이드해야 한다.
 *  - isConcurrent
 *  - isExecuting
 *  - isFinished
 *  - start
 */

- (BOOL)isConcurrent
{
    return YES;
}

- (BOOL)isExecuting
{
    return executing;
}

- (BOOL)isFinished
{
    return finished;
}

- (void)start
{
    if ([self isCancelled])
    {
        [self willChangeValueForKey:@&quot;isFinished&quot;];
        finished = YES;
        [self didChangeValueForKey:@&quot;isFinished&quot;];
    }
    else
    {
        [self willChangeValueForKey:@&quot;isExecuting&quot;];
        executing = YES;
        [self didChangeValueForKey:@&quot;isExecuting&quot;];

        [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [connection start];
    }
}


#pragma mark others

/*
 * cancel 메소드를 오버라이드하여 NSURLConnection의 수행을 cancel시키고 operation을 종료한다.
 */
- (void)cancel
{
    [super cancel];
    [connection cancel];

    if ([self isExecuting])
    {
        /*
         * NSOperationQueue의 cancelAllOperations에 의해 cancel될 때
         * [self stop] 을 하면 아직 cancel되지 않은 operation들이 수행을 시작할 수 있기 때문에
         * performSelector:withObject:afterDelay: 메소드를 이용하여 stop시킨다.
         */
        [self performSelector:@selector(stop) withObject:nil afterDelay:0];
    }
}

/*
 * executing과 finished property를 종료 상태로 바꿔주기 위한 편의성 메소드
 */
- (void)stop
{
    [self willChangeValueForKey:@&quot;isFinished&quot;];
    [self willChangeValueForKey:@&quot;isExecuting&quot;];
    executing = NO;
    finished  = YES;
    [self didChangeValueForKey:@&quot;isExecuting&quot;];
    [self didChangeValueForKey:@&quot;isFinished&quot;];
}


#pragma mark NSURLConnectionDelegate

/*
 * 응답이 들어오면 데이터를 저장하기 위한 공간을 생성한다.
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    long long length = [response expectedContentLength];

    if (length == NSURLResponseUnknownLength)
    {
        length = 0;
    }

    data = [[NSMutableData alloc] initWithCapacity:length];
}

/*
 * 데이터가 들어오면 저장해 놓는다.
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)receivedData
{
    [data appendData:receivedData];
}

/*
 * 오류가 발생하면 nil data와 함께 오류를 delegate에 전달하고 operation을 종료한다.
 */
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSData       *nilData;
    NSInvocation *invocation;

    if (![self isCancelled])
    {
        nilData    = nil;
        invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:&quot;v@:@@@&quot;]];

        [invocation setTarget:delegate];
        [invocation setSelector:selector];
        [invocation setArgument:&amp;amp;self atIndex:2];
        [invocation setArgument:&amp;amp;nilData atIndex:3];
        [invocation setArgument:&amp;amp;error atIndex:4];

        [invocation invoke];
    }

    [self stop];
}

/*
 * 데이터 로딩이 끝나면 데이터를 delegate에 전달하고 operation을 종료한다.
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSError      *nilError;
    NSInvocation *invocation;

    if (![self isCancelled])
    {
        nilError   = nil;
        invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:&quot;v@:@@@&quot;]];

        [invocation setTarget:delegate];
        [invocation setSelector:selector];
        [invocation setArgument:&amp;amp;self atIndex:2];
        [invocation setArgument:&amp;amp;data atIndex:3];
        [invocation setArgument:&amp;amp;nilError atIndex:4];

        [invocation invoke];
    }

    [self stop];
}

@end
&lt;/pre&gt;
사용은 다음과 같이 한다.
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;- (NSOperationQueue *)operationQueue
{
    return operationQueue; // NSOperationQueue를 적절하게 미리 만들어 두어야 한다.
}

- (void)downloadDataWithURL:(NSURL *)aURL
{
    URLDownload *download;

    download = [[URLDownload alloc] initWithRequest:[NSURLRequent requestWithURL:aURL] delegate:self selector:@selector(urlDownload:data:error:)];
    [[self operationQueue] addOperation:download];
    [download release];
}

/*
 * 다운로드가 끝나면 이 메소드가 호출된다.
 * 오류가 발생했을 때 data는 nil이 들어온다.
 */
- (void)urlDownload:(URLDownload *)aDownload data:(NSData *)data error:(NSError *)error
{
    if (data)
    {
        // 다운로드 완료
    }
    else
    {
        NSLog(@&quot;download error: %@&quot;, error);
    }
}
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;</description>
			<category>프로그래밍</category>
			<category>cocoa</category>
			<category>Foundation</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/37</guid>
			<comments>http://han9kin.doesntexist.com/37#entry37comment</comments>
			<pubDate>Fri, 13 Mar 2009 17:24:54 +0900</pubDate>
		</item>
		<item>
			<title>nil과 NSNull</title>
			<link>http://han9kin.doesntexist.com/36</link>
			<description>&lt;p&gt;NULL이라함은 보통 &quot;값이 없음&quot;을 말한다.&lt;/p&gt;
&lt;p&gt;C언어에서 NULL은 사실 그냥 0으로 정의되어 있는데, 포인터변수에 NULL을 사용하여 레퍼런스하는 대상이 없다는 의미로 사용한다. Objective-C에서는 객체 포인터 타입인 id에서 사용하기 위해 따로 nil을 정의하고 있다. nil도 사실 0으로 정의되어 있기 때문에 이넘이나 그넘이나 같은 넘이다.&lt;/p&gt;
&lt;p&gt;Objective-C가 C나 C++과 다른 점 중에 하나는 이 nil이 단순히 레퍼런스하는 객체가 없다는 의미 외에도 &quot;nil object&quot;라고까지 표현할만큼 특별한 기능(?)을 발휘하고 있다는 점이다. 바로 어떠한 메세지도 받아들이고(respond) 결과로 자기 자신을 리턴한다는 것이다.(자세한 내용은 &lt;a href=&quot;http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW7&quot; title=&quot;http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW7&quot; class=&quot;external&quot;&gt;여기&lt;/a&gt;참조) 즉, 다음과 같은 코드도 런타임에서 어떠한 에러도 발생하지 않고 잘 실행된다. 물론 아무것도 하지 않지만.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc:nocontrols:nogutter&quot;&gt;[nil killYourself];
&lt;/pre&gt;
&lt;p&gt;Java나 Smalltalk도 예외를 발생시키지만, Objective-C는 그렇지 않다. 이런 특별한 기능(?)이 복잡한 예외처리를 필요로 하는 경우나 디버깅할 때 귀찮을 경우도 있지만, 코드를 단순화시키기 쉽고 잘 죽지 않는(허허.. 이거 좋은 건지...) 프로그램을 만들 수 있다... (응?)&lt;/p&gt;
&lt;p&gt;그런데....&lt;/p&gt;
&lt;p&gt;NSNull 이라는 것도 있다. 코코아의 컬렉션 객체들이 nil 즉, NULL 포인터를 저장할 수 없기 때문에 존재하는, nil은 아닌 Null 객체다. (헉.. 이건, 뭐...) 문제는 NSNull 객체는 nil이 가지고 있는 특별한 기능(?)이 없다는 것이다. 즉, 다음과 같은 코드는 시키는 대로 아주 잘 죽는다... 쩝.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc:nocontrols:nogutter&quot;&gt;[[NSNull null] killYourself];
&lt;/pre&gt;
&lt;p&gt;그래서, nil과 NSNull 객체가 둘 다 들어올 수 있는 코드에서는 객체 포인터를 미리 잘 확인해봐야 한다. 다음과 같이...&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc:nocontrols:nogutter&quot;&gt;if (anObj &amp;amp;&amp;amp; ![anObj isKindOfClass:[NSNull class]])
{
    // 이제 anObj를 마음껏 사용한다.
}
&lt;/pre&gt;
&lt;p&gt;매번 if문을 저렇게 쓰는 것이 싫다면 nil이나 NSNull 객체가 아닌지 확인하는 메소드를 다음과 같이 구현할 수 있겠다.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;@interface NSObject (NullTesting)

- (BOOL)isNotNull;

@end

@implementation NSObject (NullTesting)

- (BOOL)isNotNull
{
    return [self isKindOfClass:[NSNull class]] ? NO : YES;
}

@end
&lt;/pre&gt;
또는, 이렇게.
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;@interface NSObject (NullTesting)

- (BOOL)isNotNull;

@end

@implementation NSObject (NullTesting)

- (BOOL)isNotNull
{
    return YES;
}

@end

@implementation NSNull (NullTesting)

- (BOOL)isNotNull
{
    return NO;
}

@end
&lt;/pre&gt;
&lt;p&gt;그러면, 다음과 같이 if 문의 조건을 쉽게 쓸 수 있다.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc:nocontrols:nogutter&quot;&gt;if ([anObj isNotNull])
{
    // 이제 anObj를 마음껏 사용한다.
}
&lt;/pre&gt;
&lt;p&gt;주의할 점은 isNull 메소드는 불가능하다. 왜냐하면 nil은 항상 nil(0)만 리턴하기 때문이다.&lt;/p&gt;
&lt;p&gt;if문조차 싫다면 Objective-C의 message forwarding을 이용해서 NSNull이 nil 처럼 모든 메세지를 무시하도록 만들 수 있겠다.&lt;/p&gt;
&lt;pre name=&quot;code&quot; class=&quot;objc&quot;&gt;@implementation NSNull (NilObject)

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    return [NSMethodSignature signatureWithObjCTypes:&quot;@@:&quot;];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    id ret = nil;
    [anInvocation setReturnValue:&amp;amp;ret];
}

@end
&lt;/pre&gt;
&lt;p&gt;이제는 좀 마음이 편해질려나...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align:right&quot;&gt;이 글은 &lt;a href=&quot;http://han9kin.springnote.com/&quot;&gt;스프링노트&lt;/a&gt;에서 작성되었습니다.&lt;/p&gt;</description>
			<category>프로그래밍</category>
			<category>cocoa</category>
			<category>Objective-C</category>
			<author>han9kin</author>
			<guid>http://han9kin.doesntexist.com/36</guid>
			<comments>http://han9kin.doesntexist.com/36#entry36comment</comments>
			<pubDate>Fri, 13 Mar 2009 15:55:59 +0900</pubDate>
		</item>
	</channel>
</rss>
