본문 바로가기
조회 수 5410 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print Files
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print Files
Chapter 3 Objective-C

** Creating and Using Instances

- 인스턴스 생성하기

[NSMutableArray alloc]; <----- 클래스 메소드 alloc 호출로 NSMutableArray 클래스의 인스턴스 생성

위 메소드는 객체에 할당된 메모리 공간의 포인터를 리턴하고 이 포인터 값은 아래와 같이 변수에 지정:

NSMutableArray *foo; <---- 포인터 변수 선언
foo = [NSMutableArray alloc]; <------ 인스턴스를 가리키는 포인터 위치를 foo에 지정

이 foo를 사용하기 전에 init 메소드로 초기화를 해야 한다.최종적으로 아래와 같이 코딩:

NSMutableArray *foo;
foo = [NSMutableArray alloc]; 
[foo init]; <-------- “foo is the receiver of the message init.” 새롭게 초기화된 object를 반환

위 코드는 아래와 같이 nest 가능

NSMutableArray *foo;
foo = [[NSMutableArray alloc] init];

- 인스턴스 사용하기

[foo addObject:bar]; <------- argument 하나
[foo insertObject:bar atIndex:5]; <------- argument 두개 (두번째부터 argu의 이름이 존재)

Note that insertObject:atIndex: is one selector, not two. It will trigger one method with two arguments.


** Using Existing Classes

- New -> New Project.... When the panel pops up, choose to create a Command Line Tool
01.png 02.png

- main.m을 선택하고 아래와 같이 수정

#import <Foundation/Foundation.h> <--- Foundation 프레임워크의 모든 클래스의 헤더를 포함하나 이 헤더들은 미리 컴파일되어 있으므로 부담이 적다

int main (int argc, const char * argv[])
{
	@autoreleasepool {

		NSMutableArray *array; <---- arrary 정의. NSMutableArray 타입의 인스턴스를 참조하는 포인터
		array = [[NSMutableArray alloc] init]; <---- NSMutableArray 타입의 인스턴스 생성 후 초기화. 그리고 포인터를 array에 대입
		int i;
		for(i=0; i<10; i++){
			NSNumber *newNumber = [[NSNumber alloc] initWithInt:(i * 3)];
			[array addObject:newNumber]; 
		}
		for(i=0; i<10; i++){
			NSNumber *numberToPrint = [array objectAtIndex:i];
			NSLog(@"The number at index %d is %@", i, numberToPrint); <---- printf와 동일. %@는 객체를 display. 객체로 description 메시지를 보내 반환값을 %@와 교체한다.
		}
	}
	return 0; <------ indiciating that no error occurred
}



- Possible Tokens in Objective-C Format Strings
03.png

<참고>
@ “The number at index %d is %@” 에서 " 앞에 @ 심볼이 조금 이상하게 보이지만 NSString 클래스의 인스턴스를 의미한다. In C, strings are just pointers to a buffer of characters that ends in the null character. Both C strings and instances of NSString can be used in the same file. To differentiate between constant C strings and constant NSStrings, you must put @ before the opening quote of a constant NSString.

// C string
char *foo;
// NSString
NSString *bar;
foo = "this is a C string"; 
bar = @"this is an NSString";

- Wherever a string is needed, the classes in the frameworks expect an NSString.
- However, if you already have a bunch of C functions that expect C strings, you will find yourself using char * frequently.

You can convert between C strings and NSStrings:

const char *foo = "Blah blah";
NSString *bar;
// Create an NSString from a C string
bar = [NSString stringWithUTF8String:foo];

// Create a C string from an NSString 
foo = [bar UTF8String];

Because NSString can hold Unicode strings, you will need to deal with the multibyte characters correctly in your C strings, and this can be quite difficult and time consuming.

- 실행결과
04.png


** Sending Messages to nil

- 대부분의 OOP 언어에서는 null에 메시지를 보내면 (메소드를 호출하면) crash된다. 이로인해 많은 프로그램에서 메시지를 보내기전 null 체크를 한다. 예를 들면,

if (foo != null) {
foo.doThatThingYouDo(); 
}

- OC에서는 nil에 메시지를 보내도 무방하다. 메시지는 그냥 무시된다. 따라서 null 체크를 특별히 해주지 않아도 상관없다.

id foo;
foo = nil;
int bar = [foo count];


** NSObject, NSArray, NSMutableArray, and NSString

- NSObject, NSArray, NSMutableArray, NSString 등과 같이 NS가 접두어로 들어간 클래스는 Foundation 프레임워크의 클래스들이다.
- 상속 다이어그램
05.png

<자주 사용되는 Foundation 클래스들>

* NSObject: 전체 OC 클래스의 루트로 자주 사용되는 메소드는 다음과 같다

- (id)init
메모리가 할당된 후 receiver를 초기화. 보통 alloc 메시지와 같이 사용
예: TheClass *newObject = [[TheClass alloc] init];
- (NSString *)description
receiver를 설명하는 NSString을 리턴. 디버깅에 많이 사용
%@ 포맷 스트링 사용시 대응하는 객체에 description 메시지가 보내진다
NSLog(@"The number at index %d is %@", i, numberToPrint);
is equivalent to
NSLog(@"The number at index %d is %@", i, [numberToPrint description]);
- (BOOL)isEqual:(id)anObject
receiver와 anObject가 동일하면 YES를 리턴하고 틀리면 NO를 리턴한다.
if ([myObject isEqual:anotherObject]) {
NSLog(@"They are equal."); 
}
x,y가 NSString일 때 x == y 와 [x isEqual:y]는 많은 차이가 있다.
The first way compares pointers, while the second way compares objects.
x == y는 포인터를 비교한다. 즉, 두 포인터가 동일한 메모리장소를 가리키는지를 비교
[x isEqual:y]는 객체를 비교한다. 여기서는 스트링의 문자들을 비교한다.

* NSArray: 객체들을 참조하는 포인터들의 리스트. NSArray에 nil은 요소가 될 수 없다.
  NSArray는 NSString, NSNumber 처럼 immutable 하다.
  즉, 변경이 불가능하다. (변경이 가능한 서브클래스로 NSMutableArray가 있다)
  요소로서 객체(포인터)를 가지지만 int, float 같은 C 원시타입은 가질 수 없다.
  
- (unsigned)count
현재 array가 가진 객체의 수를 리턴
- (id)objectAtIndex:(unsigned)i
i 번째 위치한 객체를 리턴
- (id)lastObject
마지막 객체를 리턴. array가 비어있으면 nil을 리턴
- (BOOL)containsObject:(id)anObject
요소중에 anObject 객체가 있으면 YES를 리턴. 이 메소드는 isEqual: 메시지를 각 array 객체들에게 anObject를 parameter로 해서 보낸다.

- (unsigned)indexOfObject:(id)anObject
anObject와 동일한 첫번째 객체의 위치를 리턴. 동일한 객체가 없으면 NSNotFound를 리턴

* NSMutableArray: NSArray를 상속. 객체를 추가 또는 삭제할 수 있다.
 immutable array에서 NSArray의 mutableCopy 메소드를 이용해 mutable array를 생성할 수 있다.
 
- (void)addObject:(id)anObject
receiver의 마지막에 anObject를 추가. nil은 추가하지 못한다.
필요시에 nil같이 아무것도 참조하지 않는 것을 추가해야 할 경우 NSNull을 사용한다.
예: [myArray addObject:[NSNull null]];
- (void)addObjectsFromArray:(NSArray *)otherArray
다른 array의 객체들을 이 array의 마지막에 추가한다
- (void)insertObject:(id)anObject atIndex:(unsigned)index
지정된 인덱스 위치에 객체를 삽입

- (void)removeAllObjects
모든 객체를 제거
- (void)removeObject:(id)anObject
anObject와 동일한 모든 객체를 제거

- (void)removeObjectAtIndex:(unsigned)index
인덱스에 위치한 객체를 제거하고 나머지 위의 객체들은 인덱스가 하나씩 내려온다.

* NSString: 유니코드 문자들의 버퍼. OC에서 모든 문자관련 작업은 이 클래스로 한다. 7-bit ASCII 문자 객체를 생성하기위해 @"..." 포맷을 사용

- (id)initWithFormat:(NSString *)format, ...
sprintf 처럼 동작한다. format에는 %d 처럼 토큰을 포함하는 문자열이 온다.
예)
int x = 5;
char *y = "abc";
id z = @"123";
NSString *aString = [[NSString alloc] initWithFormat:@"The int %d, the C String %s, and the NSString %@", x, y, z]; 
<---- [NSString alloc]으로 메모리할당 후 initWithFormat으로 객체초기화 (초기화시 문자열 지정도 같이 한다)

- (NSUInteger)length
- (NSString *)stringByAppendingString:(NSString *)aString
receiver에 aString을 추가하여 문자열 객체를 리턴
예)
NSString *errorTag = @"Error: ";
NSString *errorString = @"unable to read file.";
NSString *errorMessage;
errorMessage = [errorTag stringByAppendingString:errorString];

- (NSComparisonResult)compare:(NSString *)otherString
receiver와 otherString를 비교하여 receiver가 알파벳순에서 우선하면 NSOrderedAscending을, 그 반대인 경우 NSOrderedDescending을 리턴
- (NSComparisonResult)caseInsensitiveCompare:(NSString *)otherString
위 compare와 동일하나 대소문자를 무시한다.


** “Inherits from” versus “Uses” or “Knows About”
- 초보자들은 종종 NSString와 NSMutableArray의 서브클래스를 생성하는 것을 좋아한다. Don't.
- 숙련된 개발자들은 위 클래스를 composition으로 사용한다.
- You will find it much easier to use a class than to subclass one. Subclassing involves more code and requires a deeper understanding of the superclass. By using composition instead of inheritance, Cocoa developers can take advantage of very powerful classes without really understanding how they work.


** Creating Your Own Classes

- 10주 동안의 1 ~ 100 범위의 램덤번호를 출력하는 툴을 생성
- LotteryEntry 객체는 date와 두개의 램덤 integer를 가지도록 생성
- 완성된 툴을 가지고 아래와 같이 출력되도록 만든다.
06.png

1. Creating the LotteryEntry Class
- new -> file -> Objective-c class
- NSObject의 서브클래스로 LotteryEntry
- LotteryEntry.h, LotteryEntry.m 생성 확인

07.png 08.png 09.png 10.png

2. LotteryEntry.h 파일을 아래와 같이 수정

#import <Foundation/Foundation.h>
@interface LotteryEntry : NSObject {
	NSDate *entryDate;  // 인스턴스 변수(객체)
	int firstNumber;    // 인스턴스 변수
	int secondNumber;	// 인스턴스 변수
}
- (void)prepareRandomNumbers; // firstName, secondNumber를 1-100 사이의 수로 설정
- (void)setEntryDate:(NSDate *)date; // NSDate타입 객체를 받아서 entryDate에 대입
- (NSDate *)entryDate; // entryDate를 반환
- (int)firstNumber; // accessor 메소드 (인스턴수 변수값을 반환)
- (int)secondNumber; // accessor 메소드 (인스턴수 변수값을 반환)
@end



3. LotteryEntry.m 파일을 아래와 같이 수정

#import "LotteryEntry.h" 
@implementation LotteryEntry
- (void)prepareRandomNumbers {
	firstNumber = ((int)random() % 100) + 1; // random()출력값을 int로 캐스팅한 후 100으로 나눈 후 나머지 값(0-100)에 1을 더함
	secondNumber = ((int)random() % 100) + 1; 
}
- (void)setEntryDate:(NSDate *)date { // 파라미터 NSDate 타입의 객체(포인터)를 받은 후 entryDate에 대입
	entryDate = date;
}
- (NSDate *)entryDate { // entryDate를 반환
	return entryDate; 
}
- (int)firstNumber {
	return firstNumber; 
}
- (int)secondNumber {
	return secondNumber; 
}
@end



4. main.m 파일을 아래와 같이 수정

#import <Foundation/Foundation.h>
#import "LotteryEntry.h"

int main (int argc, const char *argv[]) { 
	@autoreleasepool {
		// Create the date object
		NSDate *now = [[NSDate alloc] init];
		NSCalendar *cal = [NSCalendar currentCalendar]; 
		NSDateComponents *weekComponents = [[NSDateComponents alloc] init];
		
		// Seed the random number generator 
		srandom((unsigned)time(NULL)); 
		NSMutableArray *array;
		array = [[NSMutableArray alloc] init];
		
		int i;
		for (i = 0; i < 10; i++) {
			[weekComponents setWeek:i];
			
			// Create a date/time object that is 'i' weeks from now
			NSDate *iWeeksFromNow;
			iWeeksFromNow = [cal dateByAddingComponents:weekComponents toDate:now options:0];
			
			// Create a new instance of LotteryEntry 
			LotteryEntry *newEntry = [[LotteryEntry alloc] init]; 
			[newEntry prepareRandomNumbers];
			[newEntry setEntryDate:iWeeksFromNow];
			
			// Add the LotteryEntry object to the array 
			[array addObject:newEntry];
		}
		for (LotteryEntry *entryToPrint in array) { 
			// Display its contents 
			NSLog(@"%@", entryToPrint);
		} 
	}
	return 0; 
}



<Object 다이어그램>
11.png

5. Building 및 실행
12.png

출력값을 보면 <LotteryEntry: 0x10030c8a0> 과 같이 LotteryEntry 객체의 기본 description 메소드 (즉, NSObject에서 정의된 description 메소드) 출력값이 나온다. 이 출력값을 읽기 편한 값으로 변경하려면 LotteryEntry.m에서 description 메소드를 작성하여 오버라이드한다.

6. LotteryEntry.m 에서 description 메소드 추가

- (NSString *)description {
	NSDateFormatter *df = [[NSDateFormatter alloc] init]; 
	[df setTimeStyle:NSDateFormatterNoStyle];
	[df setDateStyle:NSDateFormatterMediumStyle]; 
	NSString *result;
	result = [[NSString alloc] initWithFormat:@"% @ = % d and % d", [df stringFromDate:entryDate], firstNumber, secondNumber]; 
	return result;
}



재실행하면 아래와 같이 출력된다
13.png

** NSDate

- immutable 이며 생성 후 날짜나 시간 변경이 가능하다
- 자주 사용되는 메소드는 아래와 같다

+ (id)date
클래스 메소드. 객체 생성 및 현재 날짜와 시간을 리턴
예)
NSDate *now;
now = [NSDate date];
- (id)dateByAddingTimeInterval:(NSTimeInterval)interval
객체를 생성하고 주어진 interval을 plus하여 date를 리턴한다
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate
reciever와 andanotherDate간의 시간차를 초단위로 계산해 리턴한다. 린턴 값은 원시타입의 double과 동일하다.
+ (NSTimeInterval)timeIntervalSinceReferenceDate
January 1, 2001 GMT 부터 receiver의 시간차를 초단위로 계산해 리턴
- (NSComparisonResult)compare:(NSDate *)otherDate
receiver가 otherDate보다 이전이면 NSOrderedAscending를 리턴하고, 반대면 NSOrderedDescending를, 동일하면 NSOrderedSame을 리턴


** Writing Initializers

위의 main.m에서 아래와 같은 코드가 있다

newEntry = [[LotteryEntry alloc] init];
[newEntry prepareRandomNumbers];

새로운 인스턴스를 생성 후 바로 prepareRandomNumbers 메소드를 호출하여 firstNumber와 secondNumber을 초기화한다. 이 경우 init 메소드를 오버라이드하여 따로 prepareRandomNumbers메소드를 호출하지 않도록 할 수 있다.

LotteryEntry.m에 아래와 같이 init 메소드를 추가한다. (init 메소드 오버라이드시에 아래와 같은 포맷으로 작성한다)

- (id)init {
	self = [super init]; 
	if (self) // 또는 (self != nil) 즉, self가 nil이 아닌지를 체크
	{
		firstNumber = ((int)random() % 100) + 1;
		secondNumber = ((int)random() % 100) + 1; 
	}
	return self; // 수퍼클래스의 init 호출 후 nil이 리턴되면 그냥 그 nil을 리턴
}



위 코드는 먼저 수퍼클래스의 initializer를 호출하고 변수를 초기화 한 후 객체 자신의 포인터인 self를 리턴한다. self는 Java의 this와 동일.
이제 main.m에서 아래의 코드를 삭제한다.
[newEntry prepareRandomNumbers];

LotteryEntry.h에서 해당 메소드 선언도 삭제한다. 
- (void)prepareRandomNumbers;

실행하고 동일한 결과가 나오는지 확인한다.

<참고>
Q1. init 메소드에서 수퍼클래스의 init를 왜 호출하는가?
: Because you are overriding the init message. If you don't override it then [[NewsItem alloc] init] would just call the superclass' init message. 초기화 메소드는 반드시 슈퍼클래스의 초기화 메소드를 호출해야 한다

Q2. init 메소드에서 수퍼클래스의 init만 호출 [super init] 하지 않고 왜 수퍼클래스의 initializer의 리턴값을 self에 지정하고 존재유무 테스트를 하는가? 
: 이유는 어떤 Cocoa 클래스의 경우 초기화가 불가능할 때 nil을 리턴하기 때문이다. (Objective-C 클래스는 어떤 문제라도 발생하면 객체를 생성하지 못하고 nil 을 반환할 수 있다.) 이런 경우를 대비해 [super init]의 리턴값을 테스트해야 한다. 또한 수퍼클래스가 self 대신 다른 객체를 리턴할 수도 있기 때문이다.

에를 들어 self 대신 nil을 리턴하도록(return nil;) 만든 후 실행하면 아래와 같은 에러가 나온다.
14.png


** Initializers with Arguments

main.m에서 아래와 같은 코드가 있다. 객체를 생성하고 인자를 가진 메소드를 호출
LotteryEntry *newEntry = [[LotteryEntry alloc] init]; 
[newEntry setEntryDate:iWeeksFromNow];

위 코드 대신 아래와 같이 생성자에 인자를 주어 원하는 객체로 바로 생성하는 것이 보다 나이스하다.
LotteryEntry *newEntry = [[LotteryEntry alloc] initWithEntryDate:iWeeksFromNow];

1. main.m에서 위와 같이 코드를 변경한다.

2. LotteryEntry.h에서 아래와 같은 메소드를 선언한다
- (id)initWithEntryDate:(NSDate *)theDate;

3. LotteryEntry.m에서 init 메소드의 이름 및 내용을 변경한다.
- (id)initWithEntryDate:(NSDate *)theDate // 이름변경으로 init 대신 특정 생성자로
{
	self = [super init]; 
	if (self)
	{
		entryDate = theDate;  // 인자로 받은 객체를 인스턴스 변수에 대입
		firstNumber = ((int)random() % 100) + 1;
		secondNumber = ((int)random() % 100) + 1; 
	}
	return self; 
}



4. 실행 후 동작하는 것을 확인

5. 부가적으로 만약 다른 사람이 LotteryEntry 클래스를 사용시 initWithEntryDate 메소드가 생성자로 사용되는 것을 모를 수 있다. 따라서 사용자는 아래와 같은 코드를 작성할 것이다.

NSDate *today = [NSDate date];
LotteryEntry *bigWin = [[LotteryEntry alloc] init]; 
[bigWin setEntryDate:today];

이 코드가 에러를 유발하지는 않지만 상속 트리에 의해 NSObject 클래스의 init를 호출할 것이고, 이 경우 firstNumber, secondNumber가 따로 설정되지 않고 0으로 나올 것이다. 이런 경우를 대비해 아래와 같이 init를 오버라이드하여 initWithEntryDate를 호출하도록 만든다.

- (id)init {
	return [self initWithEntryDate:[NSDate date]]; 
}



결국 사용자는 init 또는 인수를 가진 initWithEntryDate 메소드를 호출하여 객체를 생성하고 초기화 시킬 수 있다.

<참고1: 생성자 생성시 지침사항>
- 수퍼클래스의 생성자를 사용하는 것으로 충분하다면 따로 생성자를 만들지 않는다.
- 생성자를 만들 경우 스퍼클래스의 지정(designated) 생성자(핵심생성자 즉, 모든 작업을 하는 생성자)를 오버라이드 한다.
- 여러 생성자를 만들 경우 위의 initWithEntryDate와 같이 한 메소드(지정 생성자)가 모든 일을 하도록 만든다. 위에서 init가 initWithEntryDate 메소드를 호출한 것 처럼 다른 생성자들이 지정 생성자를 호출하도록 코딩한다.
- 작성하는 클래스의 지정 생성자가 수퍼클래스의 지정 생성자를 호출한다.

<참고2: 수퍼클래스의 지정생성자를 오버라이드하여 예외를 발생>
- 아래와 같이 수퍼클래스의 지정생성자를 오버라이드하여 예외를 발생해야 하는 경우가 있다. 후에 더 자세히 다룸
- (id)init
{
	@throw [NSException exceptionWithName:@"BNRBadInitCall" reason:@"Initialize Lawsuit with initWithDefendant:" userInfo:nil];
	return nil; 
}




** The Debugger: BreakPoint 지정
: 여기서는 브레이크 포인트 설정, 디버거 실행 및 변수값 보기 등등을 다룬다.

- 브레이킹 포인트를 지정하고 enable시킨 후 프로그램을 실행시키면 xcode는 프로그램을 debugger에서 실행시킨다.
- 브레이킹 포인트 추가 및 실행하기
15.png


<참고 32bit/64bit OS>
* 32bit app의 경우 포인터의 값이 0x00000000 처럼 나온다.
0x00000000 <----- 16진수 8자리 = 8x4 = 32 bit memory mapping
2^32
4294967296 <----- byte
4294967296/1024/1024/1024 = 4 <----- GB (즉, 32bit 환경에서 메모리는 4GB까지만 인식가능)

* 64bit app의 경우 포인터의 값이 0x0000000000000000 처럼 16자리를 가진다.
이는 2^64이며, 이론적으로 18446744073709551616 byte (16 exabytes)까지 메모리 어드레싱이 가능하다.
하지만 OS에 따라 메모리 제한이 있다. 예를 들면 WinXP x64의 경우 메모리는 128GB까지 가능하다.

** The Debugger: 디버거영역 다루기
- 디버거영역을 보면 상위에 Continue, Step-Over, .. 버튼 등등이 있다. Continue 버튼을 클릭하면 계속 진행되어 한번의 루프가 돌고 다시 breakpoint에서 정지된다. Step-Over버튼으로 한줄씩 실행이 가능
- 디버그 콘솔에서 명령을 실행가능. 예를 들면, po "print-object"를 실행하여 객체에 description 메시지를 보낼 수 있다.

16.png

** The Debugger: Exception Breakpoint 설정
- 실행 중 무언가가 잘못된 경우 Exception이 발생한다. 예외 브레이크 포인트를 추가하여 디버거가 예외 발생시 프로그램을 정지시키도록 설정할 수 있다. 아래와 같이 기존 breakpoint를 disable하고 Exception Breakpoint를 추가한 후 예외타입을 Objective-C로 지정한다.

17.png 18.png

- 테스트를 위해 아래 코드와 같이 array에 없는 index를 요청하는 코드를 main.m에 추가하여 예외가 발생되도록 한다.

array = [[NSMutableArray alloc] init];
NSLog(@"first item = % @", [array objectAtIndex:0]); // 추가

19.png

** The Debugger: macro NSAssert() 사용
- 의도하지 않은 동작이 있으나 예외로 잡히지 않은 경우 macro NSAssert를 사용할 수 있다.

Assert is to make sure a value is what its suppose to be. If assertion fails that means something went wrong and so the app quits. One reason to use assert would be if you have some function that will not behave or will create very bad side effects if one of the parameters passed to it is not exactly some value (or a range of values) you can put an assert to make sure that value is what you expect it to be, and if its not then something is really wrong, and so the app quits. Assert can be very useful for debugging/unit testing, and also when you provide frameworks to stop the users from doing "evil" things

- 예를 들어, 아래와 같이 지정메소드에 인수값을 체크하여 인수가 nil이면 예외를 발생하는 NSAssert를 추가한다.

- (id)initWithEntryDate:(NSDate *)theDate
{
	self = [super init]; if (self) {
		NSAssert(theDate != nil, @"Argument must be non-nil"); // theDate가 nil이어야 하고, 아니면 예외발생
		entryDate = theDate;
		firstNumber = ((int)random() % 100) + 1; secondNumber = ((int)random() % 100) + 1;
	}
	return self; 
}



위 코드를 추가하고 실행하면 코드에 문제가 없으므로 아무런 변화가 없다. 아래와 같이 변경하여 일부러 예외를 발생시켜본다.
NSAssert(theDate == nil, @"Argument must be non-nil");

20.png

- 이 NSAssert 코드는 product 버전에 포함시키지 않으려면 아래와 같이 한다. 
21.png

You can change your current build configuration to Release by opening the scheme editor (in the Product menu, click Edit Scheme...). Select the Run action; on the Info panel, change Build Configuration to Release.

22.png 23.png

Now when you build and run your application, it will be built using the Release configuration. Note that the default build configuration for the Archive action is Release.
(이부분은 테스트시 잘 되지 않았음....)


** Static Analyzer

- Static Analyzer는 코드를 분석하고 버그를 찾는 툴이다.
- 일반적으로 개발자는 컴파일러의 경고등의 메시지에 의존했으나 Static Analyzer는 코드의 위험한 패턴을 체크하는 등 좀더 자세하게 체크한다.
- 테스트는 아래와 같이 한다.

24.png 25.png 26.png

In this case, the static analyzer has found a number of memory-related problems in our program because we disabled a feature called automatic reference counting, which we will discuss in the next chapter


** How Does Messaging Work?

- 모든 클래스의 루트인 NSObject에는 isa라는 메소드를 선언되어 있다.
- 따라서 모든 클래스 (루트 클래스의 서버클래스)들은 객체생성시 상속관계에 의해 클래스 구조를 참조하는 isa 포인터를 가진다.
- The class structure includes the names and types of the instance variables for the class. 
- It also has the implementation of the class’s methods. The class structure has a pointer to the class structure for its superclass.

<각 객체는 그 자신에 대한 클래스를 참조하는 포인터를 가진다>
27.png

- 위 그램에서 method들은 selector에 의해 인덱스된 것이다.
- Although SEL is defined to be char *, it is most useful to think of it as an int. 
- Each method name is mapped to a unique int. For example, the method name addObject: might map to the number 12. 
- When you look up methods, you will use the selector, not the string @"addObject:".

<The Selector Table>
28.png

At compile time, the compiler looks up the selectors wherever it sees a message send. Thus,

[myObject addObject:yourObject];

becomes (assuming that the selector for addObject: is 12) 

objc_msgSend(myObject, 12, yourObject);

Here,objc_msgSend() looks atmyObject’sisa pointer to get to its class structure and looks for the method associated with 12. If it does not find the method, it follows the pointer to the superclass. If the superclass does not have a method for 12, it continues searching up the tree. If it reaches the top of the tree without finding a method, the function throws an exception.

Clearly, this is a very dynamic way of handling messages. These class structures can be changed at runtime. In particular, using the NSBundle class makes it relatively easy to add classes and methods to your program while it is running. This very powerful technique has been used to create applications that can be extended by other developers.


List of Articles
번호 제목 글쓴이 날짜 조회 수
21 Cocoa Programming 정리 08 - NSArrayController file Hojung 2013.02.25 5334
20 Cocoa Programming 정리 07 - Key-Value Coding 과 Key-Value Observing file Hojung 2013.02.20 4468
19 Cocoa Programming 정리 06 - 헬퍼 객체 file Hojung 2013.02.19 6803
18 Cocoa Programming 정리 05 - 타겟(Target)과 액션(Action) file Hojung 2013.02.14 5772
17 Cocoa Programming 정리 04 - 메모리 관리 file Hojung 2013.02.13 5623
» Cocoa Programming 정리 03 - Objective-C file Hojung 2013.02.08 5410
15 Cocoa Programming 정리 02 - 시작하기 file Hojung 2013.02.05 7996
14 Cocoa Programming 정리 01 - Cocoa란? Hojung 2013.02.05 4285
13 객체 변수 선언시 @private 사용 Hojung 2012.09.18 3716
12 테스트 코드 작성 Hojung 2012.08.22 3443
11 NSString 객체의 생성과 변환 Hojung 2012.08.22 4469
10 클래스 프로퍼티 설정 Hojung 2012.08.22 3493
9 클래스와 객체 - 1 Hojung 2012.08.22 3567
8 Interface and Implementation Hojung 2012.08.22 3321
7 Extends vs Implements의 개념과 차이점 - 2 Hojung 2012.08.22 3670
6 Extends vs Implements의 개념과 차이점 - 1 Hojung 2012.08.22 4260
5 포인터 Hojung 2012.08.22 3593
4 조건문 및 순환문 Hojung 2012.08.22 3732
3 변수형 및 객체형 Hojung 2012.08.22 3705
2 hello world Hojung 2012.08.22 3524
Board Pagination ‹ Prev 1 2 Next ›
/ 2

Designed by sketchbooks.co.kr / sketchbook5 board skin

나눔글꼴 설치 안내


이 PC에는 나눔글꼴이 설치되어 있지 않습니다.

이 사이트를 나눔글꼴로 보기 위해서는
나눔글꼴을 설치해야 합니다.

설치 취소

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5