최근 iOS 5로 업그레이드 후 많은 application에서 숫자 부분이 띄어쓰기 되는 현상이 있습니다.
예를 들어,

"1234"

인데

"1 2 3 4"

와 같이 나오는 경우죠.
자신이 개발한 앱에서도 이러한 현상이 발생 한다면 font를 apple gothic이 아닌 다른 종류로 설정 해 주시면 됩니다.
(스크린샷과 코드는 귀찮아서 생략 ~_~)
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2011/10/15 21:09 2011/10/15 21:09
Response
8 Trackbacks , No Comment
RSS :
http://b4you.net/blog/rss/response/263

예전에 Objective-C에서 Singleton 객체를 만드는 방법에 대해 써놓은 글(http://b4you.net/blog/210)이 있었는데 사용하다보니 몇 가지 제약이 있어 새로 만들어 보았습니다.

문제는 singleton 클래스를 하나 만들어 두고 그 클래스를 상속받으면 하위 클래스도 singleton 객체가 되게끔 하려고 하는데 여기서 여러 클래스가 상속을 받게 되면 static 객체를 공유한다는 것이었습니다.
각 객체마다 static 영역이 있어서 공유되는게 당연한데 상속 구조를 고려하지 않고 구현을 해놓은 바람에 귀찮은 문제가 발생하더군요. 이러한 것들은 C++이야 template를 사용하여 처리하면 되는데 Objective-C는 그렇게 되질 않아 다음과 같이 수정하였습니다.

+ (SingletonClass *)sharedSingletonClass
{
	static NSMutableDictionary *dictionary = nil;
	id sharedObject = nil;
	NSString *className;
	
	// for DCL
	if(dictionary == nil)
	{
		@synchronized(self)
		{
			if(dictionary == nil)
			{
				dictionary = [[NSMutableDictionary alloc] init];
			}
		}
	}
	
	className = NSStringFromClass([self class]);
	
	sharedObject = [dictionary objectForKey:className];

	// for DCL
	if(sharedObject == nil)
	{
		@synchronized(self)
		{
			sharedObject = [dictionary objectForKey:className];
			
			if(sharedObject == nil)
			{
				sharedObject = [[[self class] alloc] init];
				[dictionary setObject:sharedObject forKey:className];
			}
		}
	}
	
	return sharedObject;
}

달라진 부분은 NSDictionary를 사용한 점 입니다. 이렇게 처리하면 dictionary 내에서 search 할 때의 속도 때문에 overhead가 발생하긴 하겠지만, 상속 구조에서도 깔끔하게 잘 사용할 수 있습니다.

아직까진 다른 문제점은 없었으나 문제가 발생하면 3탄을 만들어야겠군요 ㅎㅎ
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2010/09/24 00:05 2010/09/24 00:05
Response
8 Trackbacks , No Comment
RSS :
http://b4you.net/blog/rss/response/257

Xcode 자동 완성 부분 disable 하기

오랜만의 포스팅 입니다.

Xcode에서 자동 완성이 귀찮을 경우 또는 수정이 필요한 경우 해당 keyword를 disable 할 수 있습니다.


우선 Xcode 설치 디렉토리안의

Applications/Xcode.app/Contents/PlugIns/TextMacros.xctxtmacro/Contents/Resources

디렉토리로 이동하신 뒤

(예: /Developer/Applications/Xcode.app/Contents/PlugIns/TextMacros.xctxtmacro/Contents/Resources)

C.xctxtmacro 파일을 편집 해 주시면 됩니다.


위 파일을 열면..

{
	Identifier = c.block.if;
	BasedOn = c.block;
	Name = "If Block";
	IsMenuItem = YES;
	OnlyAtBOL = YES;
	Command = "if";
	Expressions = "<#condition#>";
	CompletionPrefix = if;
	CycleList = (
		c.block.if,
		c.block.ifelse,
	);
},

와 같은 code block이 나오는데 이 부분을 적당히 검색 하셔서 삭제 또는 주석처리(/* ~ */) 하시면 됩니다.

수정한 뒤 Xcode를 재시작 하면 제대로 적용된 것을 보실 수 있습니다.

이 부분을 이용하여 자기가 원하는 자동완성을 등록해도 됩니다.
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2010/08/09 17:19 2010/08/09 17:19
, ,
Response
15 Trackbacks , No Comment
RSS :
http://b4you.net/blog/rss/response/255

iPhone 버전 판별하기

iPhone 개발을 하다 보면 컴파일 시 버전을 판단해야 되는 경우가 있습니다.

단순히 버전만을 체크할 경우

#define __IPHONE_2_0     20000  
#define __IPHONE_2_1     20100  
#define __IPHONE_2_2     20200  
#define __IPHONE_3_0     30000

와 같은 매크로를 사용하면 됩니다. (Availability.h에 선언되어 있습니다)
즉 다음과 같이..

#ifdef __IPHONE_3_0
// 3.0일 때 처리
#endif

하면 되죠.
그런데 "현재 버전"의 "이상", 즉 "2.2 이상에서만"이라는 조건은 여러개의 항목들을 전부 조합하여 사용할 수도 있지만, 다음과 같은 방법을 이용하여 판단할 수 있습니다

#if defined(__IPHONE_3_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_3_0)


__IPHONE_OS_VERSION_MIN_REQUIRED는 현재 버전에서 지원되는 최소 버전이며, __IPHONE_OS_VERSION_MAX_ALLOWED는 현재 버전에서 지원되는 최대 버전입니다.
따라서 __IPHONE_OS_VERSION_MAX_ALLOWED를 이용하면 "현재 버전에서 지원되는 최대 버전" 이하/이상 등의 조건을 사용할 수 있습니다.

이 때 주의할 점은, 2.0의 경우 __IPHONE_3_0이라는 매크로가 정의 되어 있지 않기 때문에 defined()를 이용하여 정의 되어 있는지 먼저 검사하여야 정확한 버전 비교가 됩니다.
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/09/30 11:23 2009/09/30 11:23
Response
No Trackback , No Comment
RSS :
http://b4you.net/blog/rss/response/246

iPhone Simulator에 사진 넣기

iPhone Simulator에서는 화면 캡쳐가 되질 않습니다.
덕분에 사진을 이용해서 무엇인가를 해야될 때 난감한데요, 이럴 땐 아래와 같은 과정을 거쳐 iPhone에 이미지를 넣을 수 있습니다.

1. 다음의 경로를 확인합니다. 만약 없을 경우 생성합니다.

~/Library/Application Support/iPhone Simulator/User/Media/DCIM/100APPLE

2. 이미지 파일을 IMG_0000.JPG와 같은 이름으로 복사합니다.

3. 이 때 photo library를 보면 이미지가 들어간걸 보실 수 있습니다.

4. 이렇게 하면 thumbnail 이미지가 안나오는데, 추가하시려면 임의로 96*96짜리 이미지를 만든 뒤 IMG_0000.THM과 같은 이름으로 같은 경로에 저장합니다.


참고: http://iphonedevelopment.blogspot.com/2008/11/adding-photos-to-iphone-library.html
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/08/24 15:39 2009/08/24 15:39
,
Response
No Trackback , No Comment
RSS :
http://b4you.net/blog/rss/response/243

iPhone 응용 프로그램을 배포하기 위해 distribution 으로 잘 컴파일을 하고

웹 페이지나 Application Loader를 통해 배포를 하려고 하면 자꾸 code sign verification이 실패하여 업로드를 할 수 없다고 나오는 경우가 있습니다.

Application Loader를 기준으로 보자면..
"Verifying iTunes Connect application..." 메시지가 나온 뒤 "Application failed codesign verification. Please see the console log for additional details" 이라는 메시지가 나오면서 업로드가 되지 않습니다.

원인은 응용 프로그램을 zip 형태로 압축할 때 zip 파일이 제대로 압축되지 않는다는 것 입니다만;
이러한 현상이 왜 발생하는지는 모르겠지만, 가끔 파일들이 몇 개가 빠져서 압축이 됩니다.

해결 방법은 간단합니다. 응용 프로그램 패키지에서 오른쪽 누르고 "정보 입수(get info)"를 선택하여 주시면 용량이 나옵니다. 이 상태에서 압축을 하면 정상적으로 압축이 되네요.
(정보 입수 할 때 한번 해당 패키지 내의 파일들을 다시 읽어서 무엇인가가 cache역할을 하는 정보가 갱신되는 것 같습니다)

이 현상을 테스트 해보려면.. 패키지를 압축하신 뒤 다시 압축을 풀어보시면 원래 패키지와 용량이 같지 않은 것을 발견하실 수 있습니다.

이런!@_#)!$
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/08/21 17:29 2009/08/21 17:29
, , ,
Response
No Trackback , No Comment
RSS :
http://b4you.net/blog/rss/response/242

iPhone에서 table view 목록에서 왼쪽->오른쪽 또는 오른쪽->왼쪽으로 swipe 하였을 때 삭제가 나오게 하는 UI가 있습니다. 다음과 같이 말이죠.
사용자 삽입 이미지
이 기능을 구현 하려면 UITableViewDelegate, UITableViewDataSource 두 가지 delegate를 구현한 뒤, 다음과 같은 코드를 작성하여 주시면 됩니다.

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
	return UITableViewCellEditingStyleDelete;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
	// 여기서 항목 삭제
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
	return YES;
}



tableView:commitEditingStyle:forRowAtIndexPath: 에서 [indexPath row]를 이용하여 table view에 있는 셀의 index (0-based) 값을 얻을 수 있는데, DB에서 삭제한다거나 메모리/파일에서 삭제 하면 됩니다.
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/08/17 11:45 2009/08/17 11:45
, , ,
Response
No Trackback , a comment
RSS :
http://b4you.net/blog/rss/response/241

Xcode에서 객체를 새로 생성하면 다음과 같이 자동으로 code가 입력되어 있는 것을 보실 수 있습니다.

#import "TestClass.h"

@implementation TestClass

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Initialization code
    }
    return self;
}


- (void)drawRect:(CGRect)rect {
    // Drawing code
}


- (void)dealloc {
    [super dealloc];
}

@end


개인적으로 괄호 여는 스타일, 들여쓰기가 default로 공백이라는 점 등등 마음에 안드는 점이 한두개가 아닌데요, 아래의 경로에서 이러한 자동 생성되는 코드를 수정할 수 있습니다.

/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/File Templates


안에 보시면..

사용자 삽입 이미지

위의 그림에서와 같이 iPhone OS의 Cocoa Touch Class, Code Signing등의 디렉토리를 보실 수 있습니다.
여기서는 Cocoa Touch Class의 Objective-C class에 있는 UIView 클래스의 기본 코드를 수정 하도록 하겠습니다.

우선

/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/File Templates/Cocoa Touch Class/Objective-C class/UIView subclass.pbfiletemplate


로 이동한 뒤, class.h와 class.m 파일을 수정합니다. (만일의 사태에 대비하여 수정 전 백업 해두세요)
기본적으로 아래와 같이 되어 있는 코드를..

//
//  «FILENAME»
//  «PROJECTNAME»
//
//  Created by «FULLUSERNAME» on «DATE».
//  Copyright «YEAR» «ORGANIZATIONNAME». All rights reserved.
//
«OPTIONALHEADERIMPORTLINE»
@implementation «FILEBASENAMEASIDENTIFIER»

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Initialization code
    }
    return self;
}


- (void)drawRect:(CGRect)rect {
    // Drawing code
}


- (void)dealloc {
    [super dealloc];
}

@end


다음과 같이 변경하였습니다

//
//  «FILENAME»
//  «PROJECTNAME»
//
//  Created by «FULLUSERNAME» on «DATE».
//  Copyright «YEAR» «ORGANIZATIONNAME». All rights reserved.
//
«OPTIONALHEADERIMPORTLINE»
@implementation «FILEBASENAMEASIDENTIFIER»

- (id)initWithFrame:(CGRect)frame
{
        if (self = [super initWithFrame:frame])
        {
                // Initialization code
        }
        return self;
}

- (void)drawRect:(CGRect)rect
{
        // Drawing code
}

- (void)dealloc
{
        [super dealloc];
}

@end


변경하고 나서 UIView 클래스를 생성하면 깔끔한 코드가 나옵니다.
나머지 클래스들도 동일한 방법으로 수정하시면 됩니다.

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/08/10 13:46 2009/08/10 13:46
,
Response
No Trackback , No Comment
RSS :
http://b4you.net/blog/rss/response/240

Xcode에서 파일이나 객체를 추가하였을 경우에 자동으로 생성되는 주석이 있습니다.

다음과 같이 말이죠.

//
//  TestProject.h
//  TestProject
//
//  Created by Hyun Jun Jang on 09. 08. 10.
//  Copyright 2009 CompanyName. All rights reserved.
//


여기서 다음과 같은 명령을 통해 CompanyName 부분을 다른 문자열로 변경할 수 있습니다.

defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{ORGANIZATIONNAME="CompanyName";}'
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/08/10 13:29 2009/08/10 13:29
,
Response
No Trackback , No Comment
RSS :
http://b4you.net/blog/rss/response/239

Objective-C vs C

Objective-C를 처음 접했을 때 클래스 메서드를 호출하였을 때 C의 함수 호출과 다른점이 무엇일까? 라는 생각이 들었는데.. 그냥 wrapping 한건지 아니면 뭐 또 다른게 있을지 말이죠.

그 동안 귀찮아서 미루다가 오늘 disassemble 해 보았습니다.
테스트 환경은 iPhone Simulator입니다. 따라서 레지스터 이름들이 익숙한(?) eax, ebx가 나오는데요..
실제 iPhone은 arm이라 어떻게 disassemble 될 지는 잘 모르겠습니다;;
(제가 disasm 초보라 양해 부탁드립니다~)

* 테스트에 사용 될 클래스 및 함수

@interface MyClass : NSObject
{
	int _member;
}

- (void)printTest;
- (int)get;
- (void)setMember:(int)member;

@end

@implementation MyClass

- (void)printTest
{
	printf("- printTest\n");
}

- (int)get
{
	return 30;
}

- (void)setMember:(int)member
{
	_member = member;
}

- (int)member
{
	return _member;
}

@end

void PrintTest()
{
	printf("PrintTest()\n");
}

int Get()
{
	return 30;
}


* "-[MyClass printTest]" vs "PrintTest()" (void 테스트)

Dump of assembler code for function -[MyClass printTest]:
0x00001d7a <-[MyClass printTest]+0>: nop    
0x00001d7b <-[MyClass printTest]+1>: nop    
0x00001d7c <-[MyClass printTest]+2>: nop    
0x00001d7d <-[MyClass printTest]+3>: nop    
0x00001d7e <-[MyClass printTest]+4>: nop    
0x00001d7f <-[MyClass printTest]+5>: nop    
0x00001d80 <-[MyClass printTest]+6>: push   ebp
0x00001d81 <-[MyClass printTest]+7>: mov    ebp,esp
0x00001d83 <-[MyClass printTest]+9>: push   ebx
0x00001d84 <-[MyClass printTest]+10>: sub    esp,0x14
0x00001d87 <-[MyClass printTest]+13>: call   0x1d8c <-[MyClass printTest]+18>
0x00001d8c <-[MyClass printTest]+18>: pop    ebx
0x00001d8d <-[MyClass printTest]+19>: lea    eax,[ebx+0x1dc]
0x00001d93 <-[MyClass printTest]+25>: mov    DWORD PTR [esp],eax
0x00001d96 <-[MyClass printTest]+28>: call   0x400a 
0x00001d9b <-[MyClass printTest]+33>: add    esp,0x14
0x00001d9e <-[MyClass printTest]+36>: pop    ebx
0x00001d9f <-[MyClass printTest]+37>: leave  
0x00001da0 <-[MyClass printTest]+38>: ret


Dump of assembler code for function PrintTest:
0x00001ebd : nop    
0x00001ebe : nop    
0x00001ebf : nop    
0x00001ec0 : nop    
0x00001ec1 : nop    
0x00001ec2 : nop    
0x00001ec3 : push   ebp
0x00001ec4 : mov    ebp,esp
0x00001ec6 : push   ebx
0x00001ec7 : sub    esp,0x14
0x00001eca : call   0x1ecf 
0x00001ecf : pop    ebx
0x00001ed0 : lea    eax,[ebx+0xa5]
0x00001ed6 : mov    DWORD PTR [esp],eax
0x00001ed9 : call   0x400a 
0x00001ede : add    esp,0x14
0x00001ee1 : pop    ebx
0x00001ee2 : leave  
0x00001ee3 : ret

무슨말인지 잘 모르겠지만(-_-;;) 보시다시피 다른 부분이 없습니다.  둘 다 그냥 printf()를 호출하고 종료합니다.

* "-[MyClass get]" vs "Get()" (int 테스트)

Dump of assembler code for function -[MyClass get]:
0x00001da1 <-[MyClass get]+0>: nop    
0x00001da2 <-[MyClass get]+1>: nop    
0x00001da3 <-[MyClass get]+2>: nop    
0x00001da4 <-[MyClass get]+3>: nop    
0x00001da5 <-[MyClass get]+4>: nop    
0x00001da6 <-[MyClass get]+5>: nop    
0x00001da7 <-[MyClass get]+6>: push   ebp
0x00001da8 <-[MyClass get]+7>: mov    ebp,esp
0x00001daa <-[MyClass get]+9>: sub    esp,0x8
0x00001dad <-[MyClass get]+12>: mov    eax,0x1e
0x00001db2 <-[MyClass get]+17>: leave  
0x00001db3 <-[MyClass get]+18>: ret


Dump of assembler code for function Get:
0x00001ee4 : nop    
0x00001ee5 : nop    
0x00001ee6 : nop    
0x00001ee7 : nop    
0x00001ee8 : nop    
0x00001ee9 : nop    
0x00001eea : push   ebp
0x00001eeb : mov    ebp,esp
0x00001eed : sub    esp,0x8
0x00001ef0 : mov    eax,0x1e
0x00001ef5 : leave  
0x00001ef6 : ret

이것 역시 완전히 동일합니다. mac 개발에서도 eax로 리턴값을 주는군요.



이번에는 메서드를 호출하였을 경우 어떻게 코드가 실행되는지 분석 해 보겠습니다.

1. [myClass setMember:10] 호출

0x00001e67 : mov    edx,DWORD PTR [ebp-0xc] // myClass 주소 ($ebp-0x0c)를 edx에 저장
0x00001e6a : lea    eax,[ebx+0x121b] // selector(setMember:)주소를 가리키고 있는 변수
0x00001e70 : mov    eax,DWORD PTR [eax] // eax가 가리키는 곳의 값을 eax에 넣음
0x00001e72 : mov    DWORD PTR [esp+0x8],0xa // 10을 esp+0x08에 넣음 (3번째 인자)
0x00001e7a : mov    DWORD PTR [esp+0x4],eax // selector 값을 넣음 (2번째 인자)
0x00001e7e : mov    DWORD PTR [esp],edx // 스택에 myClass 주소를 넣음 (1번째 인자)
0x00001e81 : call   0x4005  // dyld_stub_objc_msgSend 호출

objc_msgSend는 많이 들어 보셨을 껍니다. 잘못된 receiver에 메시지를 날릴려고 하면 항상 나오는 EXC_BAD_ACCESS와 같은 오류 상황에서 backtrace (call stack) 해보면 objc_msgSend()가 찍히죠.
여기서 보시면 receiver가 edx에 저장이 되고 eax에는 selector가 저장됩니다.[2] 이러한 값들을 c 코드로 보면 다음과 같이 되겠죠.

dyld_stub_objc_msgSend(myClass, selectorOfSetMember, 10);


이렇게 하면 "4. 멤버 변수 접근 (setter 이용)"에서 보시는 것과 같이 _member 변수에 값이 설정됩니다.

2. objc_msgSend로..

위의 0x00001e81 <TestMe+162> 부분의 코드에서 call 0x4005를 통해 dyld_stub_objc_msgSend를 호출하는 것을 보실 수 있습니다.
따라가보면..

0x00004005 <dyld_stub_objc_msgSend+0>: jmp    0x95da0670 <objc_msgSend>


와 같이 나오는데, 또 다시 objc_msgSend를 거치는 것을 보실 수 있습니다. (dyld_stub_objc_msgSend는 말그대로 stub 코드라서)

3. objc_msgSend 에서는 무슨 일이?

1번에서 넣어준 인자 덕분에 objc_msgSend()는 myClass, selector, 10 이라는 3개의 인자를 받았습니다. 이 인자들을 이용해서 무엇인가를 하겠죠.

objc_msgSend()는 아래와 같이 생겼습니다. 정신건강을 위해 more/less로 처리 했습니다 :)

objc_msgSend() 보기

뭐가 뭔지 잘 모르겠지만 한번 보도록 하죠.
청므에 ecx에 esp+0x08, eax에 esp+0x04를 넣습니다. 각각 selector와 myClass가 되겠죠.
이렇게 넣고 0xfffeb010과 비교를 하는데 이걸 찾아보니 ignore selector라는 군요.[4] 참고 자료를 보시면

-#if WITH_OBJC
-static inline bool
-is_ignored_selector(SEL sel)
-{
-#if defined(__ppc__)
-    return sel == (SEL)0xfffef000;
-#elif defined(__i386__)
-    return sel == (SEL)0xfffeb010;
-#else
-# error Unsupported arch
-#endif
-}
-#endif
-


와 같이 되어 있습니다. i386일때 selector가 0xfffeb010이면 is_ignored_selector가 true가 됩니다. 위의 어셈 코드를 보시면 아시겠지만.. 이 값을 갖게 되면 무시되서 그냥 return 하네요. (왜 이렇게 하는지 용도는 먼지 모르겠습니다??) 참고로 inline으로 선언되어 있어서 is_ignored_selector(selector)와 같이 호출하여도 어셈 코드 상에는 하드 코딩 됩니다.

receiver에게 데이터를 전달하기 위해 계속 진행하다 보면 <objc_msgSend+44>지점에서 eax가 0인지 확인 합니다. 여기서 eax는 selector인데, 만약 0이라면 <objc_msgSend+58>로 이동하겠지만 0이 아니므로 계속 진행합니다. 이렇게 쭉 가다가 "_class_lookupMethodAndLoadCache"라는 곳으로 이동하는데요, 이렇게 이동을 해서 보면 정신 없는 코드로 빠져 버립니다. 이것 역시 정신건강을 위해 less/more로..

_class_lookupMethodAndLoadCache 보기

일반 C++ 메서드 호출과는 비교할 수 없을 정도로 징하게 많이 호출하는군요;
보시면 _class_lookupMethodAndLoadCache, _class_getFreedObjectClass, _class_getNonexistentObjectClass, _class_isInitialized, class_initialize과 같은 메서드 들을 호출합니다. 정확히 분석해 보진 않았지만 receiver가 nil 일 경우 여기서 걸러지겠죠?? 여기서 상위 클래스의 메서드 호출 등을 수행하고 메서드를 cache 하는 동작을 한다고 합니다.[3] 머.. 여기선 특별한게 없는 듯 합니다.

다시 objc_msgSend()로 가서 보면 <objc_msgSend+110>에서 jmp eax 합니다. 여기서 eax는 selector 주소가 계산되어 실제 코드 영역으로 진입하게 됩니다. 이 부분을 통해 setMember:가 호출 되는 것이죠.

4. setMember 안에서..

Dump of assembler code for function -[MyClass setMember:]:
0x00001db4 <-[MyClass setMember:]+0>: nop    
0x00001db5 <-[MyClass setMember:]+1>: nop    
0x00001db6 <-[MyClass setMember:]+2>: nop    
0x00001db7 <-[MyClass setMember:]+3>: nop    
0x00001db8 <-[MyClass setMember:]+4>: nop    
0x00001db9 <-[MyClass setMember:]+5>: nop    
0x00001dba <-[MyClass setMember:]+6>: push   ebp
0x00001dbb <-[MyClass setMember:]+7>: mov    ebp,esp
0x00001dbd <-[MyClass setMember:]+9>: sub    esp,0x8
0x00001dc0 <-[MyClass setMember:]+12>: mov    edx,DWORD PTR [ebp+0x8] // edx에 self주소(ebp + 0x08) 저장
0x00001dc3 <-[MyClass setMember:]+15>: mov    eax,DWORD PTR [ebp+0x10] // eax에 첫번째 인자 값(ebp + 0x10) 저장
0x00001dc6 <-[MyClass setMember:]+18>: mov    DWORD PTR [edx+0x4],eax // _member(edx + 0x04)에 eax값 저장
0x00001dc9 <-[MyClass setMember:]+21>: leave  
0x00001dca <-[MyClass setMember:]+22>: ret

아까부터 느끼는거지만... mac에서는 앞에 nop이 꼭 붙는군요; 저 영역이 어딘가에 사용되서 이겠죠?
특별한건 없습니다. 값 들을 보면 objc_msgSend에서 esp에 myClass 포인터를 넣어주는 것 같고, 2번째 인자로 10을 넣어주는 것 같네요.


전체적으로 보자면..... 한개의 메시지가 전달되기 위해 엄청 많은 명령어를 실행하고 있는데 좀 비효율 적인게 아닌가 생각이 듭니다.
나중에 selector 호출 속도와 일반 함수, C++ 클래스 메서드 호출 속도를 profiling 해봐야 겠네요.

어셈을 잘 몰라 하면서 분석하느라 부족한게 많은 글이네요. 나중에 한번 다시 도전 해봐야겠습니다-_-;

* 참고

[1] So you crashed in objc_msgSend()
http://www.sealiesoftware.com/blog/archive/2008/09/22/objc_explain_So_you_crashed_in_objc_msgSend.html

[2] obj_msgSend()
http://ridiculousfish.com/blog/archives/2005/08/01/objc_msgsend/

[3] The faster objc_msgSend
http://www.mulle-kybernetik.com/artikel/Optimization/opti-9.html

[4] [macruby-changes] [391] MacRuby/branches/lrz_unstable
http://lists.macosforge.org/pipermail/macruby-changes/2008-August/000280.html

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2009/07/06 17:35 2009/07/06 17:35
,
Response
No Trackback , No Comment
RSS :
http://b4you.net/blog/rss/response/235


블로그 이미지

빗소리를 먹는 사람.

- 장현준

Notices

Archives

Authors

  1. 장현준

Recent Trackbacks

Calendar

«   2017/12   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            

Site Stats

Total hits:
2084436
Today:
4280
Yesterday:
5115