검색결과 리스트
Objective-C에 해당되는 글 6건
- 2011.04.29 Objective-C 문자열 조작 메서드
- 2011.03.23 다중인자를 갖는 PerformSelector 메시지
- 2011.03.22 Protocol 과 Category
- 2011.03.20 Objective-C 훑어보기 (2)
- 2011.03.20 [Cocoa] Cocoa Design Pattern
- 2011.03.03 HMAC-SHA1 구현
글
Objective-C 문자열 조작 메서드
Objective-C
2011. 4. 29. 12:22
Objective-C 문자열 조작 메서드 중 몇가지에 대해서 알아보자.
문자열 비교시 결과값을 위해 다음과 같은 enum 상수가 선언되어 있다.
enum {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
};
typedef NSInteger NSComparisonResult;
NSOrderedAscening은 좌측의 피연산자가 우측의 피연자보다 작다는 것을
NSOrderedDescending은 좌측의 피연자가 우측의 피연자보다 크다는 것을
NSOrderedSame은 좌우측의 피연산자가 같다는 것을 나타낸다.
다음은 문자열에 포함된 특정 문자열이나 NSArray 안에 특정 Object와 같이 범위를 지정하기 위해 사용되는 구조체이다.
NSOrderedDescending은 좌측의 피연자가 우측의 피연자보다 크다는 것을
NSOrderedSame은 좌우측의 피연산자가 같다는 것을 나타낸다.
다음은 문자열에 포함된 특정 문자열이나 NSArray 안에 특정 Object와 같이 범위를 지정하기 위해 사용되는 구조체이다.
typedef struct _NSRange {
NSUInteger location; // start index
NSUInteger length; // location 위치부터의 길이
} NSRange;
다음은 초 단위로 시간간격을 지정하기 위한 타입정의이다.
typedef double NSTimeInterval;
이름만을 보고도 충분히 그 의미를 알수 있기 때문에 메서드에 대한 설명은 생략하겠다. (-_-;;)
문자열 비교
- (NSComparisonResult)compare:(NSString *)aString - (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString - (BOOL)isEqualToString:(NSString *)aString - (BOOL)hasPrefix:(NSString *)aString
문자열 접합
- (NSString *)stringByAppendingString:(NSString *)aString - (NSString *)stringByAppendingFormat:(NSString *)format ...
문자열 분할
- (NSString *)substringToIndex:(NSUInteger)anIndex - (NSString *)substringFromIndex:(NSUInteger)anIndex - (NSString *)substringWithRange:(NSRange)aRange
문자열 검색
- (NSRange)rangeOfString:(NSString *)aString - (NSRange)lineRangeForRange:(NSRange)aRange
문자열 치환
- (NSString *)stringByReplacingCharactersInRange:(NSRange)range withString:(NSString *)replacement - (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement
문자열 변환
- (NSString *)capitalizedString - (NSString *)lowercaseString - (NSString *)uppercaseString - (id)initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding - (const char *)cStringUsingEncoding:(NSStringEncoding)encoding
문자열 토큰 분리
- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator - (NSArray *)componentsSeparatedByString:(NSString *)separator
'Objective-C' 카테고리의 다른 글
| Objective-C 문자열 조작 메서드 (0) | 2011.04.29 |
|---|---|
| 다중인자를 갖는 PerformSelector 메시지 (0) | 2011.03.23 |
| Protocol 과 Category (0) | 2011.03.22 |
| Objective-C 훑어보기 (2) | 2011.03.20 |
| [Cocoa] Cocoa Design Pattern (0) | 2011.03.20 |
| HMAC-SHA1 구현 (0) | 2011.03.03 |
설정
트랙백
댓글
글
다중인자를 갖는 PerformSelector 메시지
Objective-C
2011. 3. 23. 15:31
이번 포스팅에서는 다중 파라미터를 갖는 Selector를 인자로 받아 별도의 쓰레드에서 처리를 해주는 비동기 메서드
구현에 대해서 알아볼 것이다.
아이폰 앱 프로젝트 진행 중 Delegate 패턴을 구현하면서 PerformSelector 류의 메서드를 사용 할 필요가 생겼다.
Cocoa Touch 프레임웍에서는 최대 2개까지의 인자를 받는 메서드(performSelector:withObject:withObject:) 만을 제공하고,
더 많은 파라미터를 전달해야 할 경우, 클래스 또는 Dictionary를 사용하여 전달해야 했다. 매번마다 파라미터를 담기위해 Dictionary를 생성하고, 데이터를 꺼내쓰는 것은 상당히 번거로운 작업이었다.
외국 블로그에서 우연히 이 문제를 깔끔하게 해결해주는 코드를 발견했다. C언어의 가변인자 리스트와 Objective-C 의
NSInvocation 메커니즘을 사용하는 방법이었다. 이 포스팅에서는 가변인자 리스트와 NSInvocation 메커니즘에 대해서는
설명하지 않겠다. 추후 Objective-C 런타임 메커니즘을 알아보면서 NSInvocation에 대해서 자세히 알아볼 것이다.
Cocoa Touch 프레임웍에서는 최대 2개까지의 인자를 받는 메서드(performSelector:withObject:withObject:) 만을 제공하고,
더 많은 파라미터를 전달해야 할 경우, 클래스 또는 Dictionary를 사용하여 전달해야 했다. 매번마다 파라미터를 담기위해 Dictionary를 생성하고, 데이터를 꺼내쓰는 것은 상당히 번거로운 작업이었다.
외국 블로그에서 우연히 이 문제를 깔끔하게 해결해주는 코드를 발견했다. C언어의 가변인자 리스트와 Objective-C 의
NSInvocation 메커니즘을 사용하는 방법이었다. 이 포스팅에서는 가변인자 리스트와 NSInvocation 메커니즘에 대해서는
설명하지 않겠다. 추후 Objective-C 런타임 메커니즘을 알아보면서 NSInvocation에 대해서 자세히 알아볼 것이다.
다음은 가변인자 리스트와 NSInvocation을 사용하여 다중 파라미터를 갖는 Selector를 호출하는 예제코드이다.
- (void)performSelector:(SEL)aSelector withContext:(void*)context,... {
if (context) {
NSMethodSignature *signature = [self methodSignatureForSelector:aSelector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation retainArguments];
NSUInteger argumentCount = [signature numberOfArguments] - 2;
[invocation setTarget:self]; // index 0
[invocation setSelector:aSelector]; // index 1
va_list arguments;
va_start(arguments, context);
// 인자의 개수는 +2가 된 상태
NSUInteger i, count = argumentCount;
void *currentValue = context;
for (i = 0; i < count; i++) {
[invocation setArgument:¤tValue atIndex:(i + 2)];
currentValue = va_arg(arguments, void*); // 다음 인자 읽기
}
va_end(arguments);
NSThread *customWorkerThread = [NSThread currentThread];
[invocation performSelector:@selector(invoke) onThread:customWorkerThread withObject:nil waitUntilDone:NO];
} else {
[self performSelectorInBackground:aSelector withObject:nil];
}
}
위 메서드를 사용하여 아래와 같이 세 개의 인자를 갖는 printArgument:andOther:andAnother: 메시지를 호출하면...
// 호출할 메서드
- (void)printArgument:(NSString*)arg1 andOther:(NSString*)arg2 andAnother:(NSString*)arg3 {
NSLog(@"%@", [NSThread currentThread]);
NSLog(@"arg1: %@", arg1);
NSLog(@"arg2: %@", arg2);
NSLog(@"arg3: %@", arg3);
}
// 요렇게 호출할 수 있다. 깔끔하지 않는가? [self performSelector:@selector(printArgument:andOther:andAnother:) withContext:@"t1", @"t2", @"t3", nil];
위 메소드를 카테고리로 정의해놓으면 아주 유용하게 사용할 수 있을 것이다.
[소스 출처]
'Objective-C' 카테고리의 다른 글
| Objective-C 문자열 조작 메서드 (0) | 2011.04.29 |
|---|---|
| 다중인자를 갖는 PerformSelector 메시지 (0) | 2011.03.23 |
| Protocol 과 Category (0) | 2011.03.22 |
| Objective-C 훑어보기 (2) | 2011.03.20 |
| [Cocoa] Cocoa Design Pattern (0) | 2011.03.20 |
| HMAC-SHA1 구현 (0) | 2011.03.03 |
설정
트랙백
댓글
글
Protocol 과 Category
Objective-C
2011. 3. 22. 23:53
이번 포스팅에서는 Protocol과 Category에 대해서 알아보자. Protocol은 자바의 인터페이스에 유사한 개념이다.
Protocol은 공식 프로토콜과 비공식 프로토콜이 있으며, 그 중 공식 프로토콜이 자바의 인터페이스에 해당한다.
Category는 상속의 대안으로 클래스를 변경하지 않고도, 새로운 기능(메서드)을 추가할 수 있는 메커니즘이다.
프로토콜과 카테고리에 대해서 좀 더 자세히 알아보자.
Protocol은 공식 프로토콜과 비공식 프로토콜이 있으며, 그 중 공식 프로토콜이 자바의 인터페이스에 해당한다.
Category는 상속의 대안으로 클래스를 변경하지 않고도, 새로운 기능(메서드)을 추가할 수 있는 메커니즘이다.
프로토콜과 카테고리에 대해서 좀 더 자세히 알아보자.
1. Protocol 이란?
자바언어의 Interface에 해당하는 개념으로 @protocol 지시어를 사용하여 정의한다. @protocol 을 구현하는 모듈은
프로토콜이 규약하는 모든 메소드를 반드시 구현해야하는 프로토콜을 공식 프로토콜(Formal Protocol)이라고 하며,
구현해도 되고 구현하지 않아도 되는 프로토콜을 비공식 프로토콜 (Informal Protocol)이라고 한다. 공식 프로토콜은
@required 지시어를, 비공식 프로토콜은 @optional 지시어를 사용한다.
(비공식 프로토콜은 런타임시에 비공식 프로토콜을 구현하는 메소드가 존재하는 경우에만 호출된다.)
프로토콜이 규약하는 모든 메소드를 반드시 구현해야하는 프로토콜을 공식 프로토콜(Formal Protocol)이라고 하며,
구현해도 되고 구현하지 않아도 되는 프로토콜을 비공식 프로토콜 (Informal Protocol)이라고 한다. 공식 프로토콜은
@required 지시어를, 비공식 프로토콜은 @optional 지시어를 사용한다.
(비공식 프로토콜은 런타임시에 비공식 프로토콜을 구현하는 메소드가 존재하는 경우에만 호출된다.)
공식프로토콜의 모든 메소드들이 구현되지 않으면 컴파일 시에 에러가 발생할 것이다. 2개 이상의 프로토콜을 구현할
경우 ,(콤마)를 구분자로 구현할 프로토콜을 <> 안에 나열한다.
경우 ,(콤마)를 구분자로 구현할 프로토콜을 <> 안에 나열한다.
Objective-C 에서는 Java 와는 다르게 컴파일 타임에 프로토콜 할당에 대해 타입검사를 수행하지 않는다.
런타임시 메시지가 호출될 때, 해당하는 메소드가 구현되지 않았다면 selector exception 예외가 발생한다.
@interface VenusAttacks : Game ... @end @class Thing; @protocol Living - (float)age; - (float)health; (NSDictionary*)healthInfo; @end @protocol Communicating - (NSArray*)recipientsInRange; - (void)sendMessage:(NSString*)message to:(id)recipient; @end @interface Thing : NSObject ... @end @interface Character : Thing ... @end
1.1 비공식 프로토콜(Informal Protocol)
비공식 프로토콜은 모듈클래스가 반드시 구현하지 않아도 되는 프로토콜이다.
비공식 프로토콜은 (반드시 구현하지 않아도 되기 때문에) 유연하고 동적이지만, 추가적인 문서화와 프로그래머들 간에
(통일된 사용을 위해) 협조가 요구된다. 비공식 프로토콜에서는 메서드가 구현되었는지 검사하는 코드가 들어가며
그 형태는 아래 코드와 같다. 자바에서는 윈도우 종료시 이벤트를 인터셉트 하기위해서, 해당하는 이벤트에 대한 리스너를
등록하고, 이벤트가 발생하면 리스너를 통해 통보받는다. Objetive-C 에서는 delegate 가 윈도우 종료시 Notification 을
(통일된 사용을 위해) 협조가 요구된다. 비공식 프로토콜에서는 메서드가 구현되었는지 검사하는 코드가 들어가며
그 형태는 아래 코드와 같다. 자바에서는 윈도우 종료시 이벤트를 인터셉트 하기위해서, 해당하는 이벤트에 대한 리스너를
등록하고, 이벤트가 발생하면 리스너를 통해 통보받는다. Objetive-C 에서는 delegate 가 윈도우 종료시 Notification 을
통보받는 메소드를 비공식 프로토콜로 선언하고 있다.
BOOL shouldClose = YES; if ([delegate respondsToSelector:@selector(windowShouldClose:)]) shouldClose = [delegate windowShouldClose:self]; if (!shouldClose) return;
1.2 공식프로토콜과 비공식 프로토콜의 조합(Combining Formal and Informal Protocols)
프로토콜은 비공식 프로토콜과 공식 프로토콜이 혼합되어 사용되어지는 경우가 많다.
프로토콜에 선언한 메소드는 디폴트로 공식 프로토콜이며, @required 이라는 지시어를 명시적으로 사용할 수 있다.
비공식 프로토콜은 @optional 지시어를 사용한다.
다음은 TableDataSource 프로토콜이며, 테이블 행의 개수를 반환하는 메소드와 해당하는 열과 행의 셀객체를 반환하는
메소드는 @required 로 , 테이블 특정 행과 열의 셀객체를 변경하는 메소드는 @optional 로 선언되어 있어서, 비공식 프로토콜이
구현되지 않았을 경우, read-only 로 동작하게 된다. (구현 유무에 따라 동작용도를 변경할 수 있다. )
@protocol TableDataSource
@required
- (int)numberOfRowsInTable:(Table*)table;
- (id)table:(Table*)table objectForColumn:(int)col row:(int)ro
@optional
- (void)table:(Table*) setObject:(id)object forColumn:(int)col row:(int)row;
@end
클래스 정의 일부에 이름을 붙힌 조각이라 할 수 있다.. 자바에서는 단일블럭에서 하나의 클래스 정의가 모두 이루어지지만,
Objective-C에서는 한 클래스 정의를 카테고리를 사용하여 여러 파일에 분리하여 정의할 수 있다.
카테고리를 사용함으로써, 복잡한 클래스를 관련이 되어 있는 인스턴스 변수와 메소드들의 그룹으로 분리하여
복잡성을 줄이고, 프로그래머들이 독립적으로 개발할 수 있도록 해준다.
이외에도 카테고리는 클래스 정의(@interface) 와 독립적으로 클래스 메소드를 추가할 수 있게하며,
클래스 구현의 일부를 은닉할 수 있는 메커니즘을 제공한다. 클래스와 카테고리는 별도의 헤더파일과 모듈파일에
저장될 수 있으며, 해당 클래스를 사용하는 클라이언트 클래스는 관련있는 헤더파일만을 import 하여 사용한다.
// 카테고리를 사용하지 않고 단일 클래스에 정의한 경우
@interface RecipeBoxController : NSObject {
NSMutableArray*recipes;
NSMutableDictionary* recipeIndex;
}
- (id)init;
- (Document*)newRecipe;
- (Document*)newShoppingList;
- (Document*)newShoppingListFromRecipes:(NSIndexSet*)recipeIndexes;
@end
@implementation RecipeBoxController
...
@end
다음 카테고리는 리스트 설정하고 획득하는 역할만을 수행한다.
// Category 를 사용하여 클래스를 분리 @interface RecipeBoxController (ShoppingLists) - (Document*)newShoppingList; - (Document*)newShoppingListFromRecipes:(NSIndexSet*)recipeIndexes; @end @implementation RecipeBoxController (ShoppingLists) ... @end
2.1 카테고리 사용하여 조직하기(Using Categories for Organization)
거대한 클래스를 다룰수 있는 기능적인 단위로 나누는 것이 카테고리의 주요한 용도이다. 이 개념은 한 클래스를
모듈화 할 수 있게하며, 각 모듈간에 캡슐화와 의존성을 줄여준다. 빌터패턴이 카테고리를 사용하여 얻을 수 있는 응용의 한
예이다. 자바에서 빌드에서 복잡한 객체 생성의 과정이 별도 클래스로 분리되는데,
예이다. 자바에서 빌드에서 복잡한 객체 생성의 과정이 별도 클래스로 분리되는데,
Objective-C에서는 별도의 객체생성과정이 메인 클래스 정으로부터 카테고리를 사용하여 분리될 수 있다.
2.2 메서드 은닉 (Hiding Methods)
카테고리의 또 다른 사용용도는 클래스의 일부를 은닉하는 것이다. 자바에서는 private, protect 키워드를 사용하여
내부 데이터를 은닉한다. 아래는 카테고리를 사용하여 메소드 일부를 은닉하는 예이다. Private 이름으로 선언된 카테고리는
컴파일러에게 무시되며, 해당 클래스를 사용하는 클라이언트 클래스는 카테고리의 메소드들을 볼 수 없다.
내부 데이터를 은닉한다. 아래는 카테고리를 사용하여 메소드 일부를 은닉하는 예이다. Private 이름으로 선언된 카테고리는
컴파일러에게 무시되며, 해당 클래스를 사용하는 클라이언트 클래스는 카테고리의 메소드들을 볼 수 없다.
두개의 클래스 선언을 별도의 헤더 파일로 분리할 수도 있다. 이때, 클라이언트 클래스는 ToasterController.h 헤더파일만을
import 하여 사용하면 된다. 카테고리의 헤더파일은 관례적으로 (클래스이름+카테고리이름.h) 이라는 형태를 갖는다.
아래에서는 ToasterController+Private.h 라는 이름을 갖을 것이다.
이런한 개념을 확장하여 Objectiv-C 에서는 extension 이라는 개념을 제공한다.
@interface ToasterController : NSObject {
@private
float darkness;
}
- (void)setDarkness:(float)level;
- (void)startToasting
- (void)stopToasting
@end
@interface ToasterController (Private)
- (float)darkness
- (CarrierState)carrierPosition;
- (NSTimeInterval)cycleTime;
- (void)setCycleTime:(NSTimeInterval)cycleTime;
- (void)finishedToasting:(NSTimer*)timer;
카테고리를 사용하여 원 클래스에 어떠한 변경을 하지 않고도, 새로운 메소드를 정의할 수 있다.
아래 코드는 Foundation Framework 의 NSArray 클래스에 카테고리를 사용하여, 배열의 첫번째 요소를 얻는
(id)firstObject 메소드를 추가하고 있다.
* 만일 카테고리와 클래스가 동일한 메소드를 구현한다면, 카테고리 메소드가 클래스의 메소드를 대체하게 되어, 본 클래스의
메소드를 호출하지 못하게 된다. 동일한 메소드를 구현하는 카테고리가 2개 이상 있게되면 런타임에 무엇이 호출될지는 예측할 수 없다.
@interface NSArray (MyCollectionAdditions)
- (id)firstObject;
@end
@implementation NSArray (MyCollectionAdditions)
- (id)firstObject {
return ([self objectAtIndex:0]);
}
@end
2.3 Extesions
Extension 은 익명 카테고리이다. 다만 Extension은 클래스의 @implementaion 구현부아 아닌 클래스의 @interface 정의부를
분리하기 위해 사용한다. extension 의 @interface 지시어는 비어있는 카테고리 이름을 사용한다. extensions 내에 선언된 메소드들은 동일하게 @implentation 에서 모두 구현되어져야 한다. 카테고리와 extension은 컴파일 타임에만 프로그래머와 컴파일러로부터 메소드 선언을 은닉할 수 있으며, 런타임시에는 introspection(리플렉션)을 사용하면 노출될 수 있다.
분리하기 위해 사용한다. extension 의 @interface 지시어는 비어있는 카테고리 이름을 사용한다. extensions 내에 선언된 메소드들은 동일하게 @implentation 에서 모두 구현되어져야 한다. 카테고리와 extension은 컴파일 타임에만 프로그래머와 컴파일러로부터 메소드 선언을 은닉할 수 있으며, 런타임시에는 introspection(리플렉션)을 사용하면 노출될 수 있다.
@interface CaseDocument : NSObject {
@private
CaseNumber caseNumber;
}
- (CaseNumber)caseNumber;
@end
@interface CaseDocument()
- (void)setCaseNumber:(CaseNumber)number;
@end
@implementation CaseDocument
- (CaseNumber)caseNumber { return (caseNumber); }
- (void)setCaseNumber:(CaseNumber)number { caseNumber = number; }
'Objective-C' 카테고리의 다른 글
| Objective-C 문자열 조작 메서드 (0) | 2011.04.29 |
|---|---|
| 다중인자를 갖는 PerformSelector 메시지 (0) | 2011.03.23 |
| Protocol 과 Category (0) | 2011.03.22 |
| Objective-C 훑어보기 (2) | 2011.03.20 |
| [Cocoa] Cocoa Design Pattern (0) | 2011.03.20 |
| HMAC-SHA1 구현 (0) | 2011.03.03 |
Category,
extension,
formal protocol,
informal protocol,
objective-c,
protocol,
공식 프로토콜,
비공식 프로토콜,
카테고리,
프로토콜
설정
트랙백
댓글
글
Objective-C 훑어보기
Objective-C
2011. 3. 20. 23:40
iPhone 의 인기와 더불어 주목받고 있는 Objective-C 언어에 대해서 간략히 알아보자.
Objective-C 언어는 C 언어 기반위에 객체지향적인 요소를 가미한 언어로서, 객체지향 언어의 원류인 Smalltalk 에서
그 개념을 많이 차용했다고 한다. 이 포스팅에서는 언어의 구체적인 설명은 하지않고, 간략히 어떤 언어 요소들이
있는지만 알아보겠다.
Objective-C 언어는 C 언어 기반위에 객체지향적인 요소를 가미한 언어로서, 객체지향 언어의 원류인 Smalltalk 에서
그 개념을 많이 차용했다고 한다. 이 포스팅에서는 언어의 구체적인 설명은 하지않고, 간략히 어떤 언어 요소들이
있는지만 알아보겠다.
1. Objective-C 에서 클래스 정의
#import "SuperClass.h"
@interface NewClass : SuperClass {
int instanceVariable;
}
- method;
- methodWithParameter:param;
@end
@implementation NewClass
- method {
return (nil);
}
- methodWithParameter:param {
return (nil);
}
2. Object Pointers
SpecificClass * specificObject; id anyObject;id 타입은 void * 형 포인터로 어떤 객체 포인터도 할당하거나 할당받을 수 있다.
3. Sending Messages
[object method]; [object methodWithParam:param];
objective-c에서는 메시지를 호출한다고 하기 보단, 객체에게 메세지를 보낸다고 한다.
3. Naming Method
Objective-C에서는 메시지의 이름을 부여할 때, 메소드가 취하는 행위를 기술하도록 이름짓는다. 메시지의 이름은
다음과 같은 형식을 따른다.
다음과 같은 형식을 따른다.
반환타입+메시지행위+첫번째 인자이름: 첫번째 인자 이름: 두번째 인자이름...
반환타입이나 인자가 존재하지 않는 경우 생략될 수 있다.
- valuePrepositionParameter:parameter - objectForKey:key - stringByAppendingString:string; - numberFromString:string;
4. Parameter and Return Types
인자와 반환값은 괄호사이에 기술한다- (id)objectForKey:(id)aKey; - (NSMenuItem)itemWithTag:(NSInteger)aTag; - (unichar)characterAtIndex:(NSUInteger)index; - (NSString*)stringByAddingPercentEscapeUsingEncoding:(NSStringEncoding)encoding; - (void)runInNewThread; - (void)addAttribute:(NSString*)name value:(id)value range:(NSRange)aRange;
5. Method Selectors
메서드의 이름, 인자변수의 이름, 인자의 타입이 유일한 식별자를 구성하며, Java 의 메소드 시그니처와 동일한 의미를 갖는다.
(NSfont*)fontWithFamily:(NSString*)family traits:(NSFontTraitMask)fontTraitMask weight:(NSInteger)weight size:(CGFloat)size
의 메소드 식별자는 fontWithFamily:family:traits:weight:size 가 된다. 이 식별자는 실제로 selector 라 불리는 숫자 상수와
맵핑이 되며, 그 숫자 상수는 SEL 타입을 갖는다. @selector() 지시어는 특정 메소드의 selector 상수를 반환한다
SEL selector = @selector(fontWithFamily:traits:weight:size)
6. Instance Variable
isa 인스턴스 변수
모든 Objective-C 객체가 상속받는 인스턴스 변수로, 클래스 자체를 정의하는 Class 타입의 객체이다.
- (Class)class 메소드 호출을 통해 얻을 수 있으며, - (NSString *)className 통해 클래스의 이름을 문자열로 얻을 수 있다.
Properties
객체의 프로퍼티를 정의하는 키워드로 @property 와 @synthesize 가 있다. @property 는 클래스가 계약을 지킬 것이라고 컴파일러에게 알려주는 역할을 한다. @synthesize 는 컴파일러에게 해당 인스턴스 변수에 대한 getter와 setter 를 생성하라고 지시한다
int tag;
라는 인스턴스 변수에 대해 @property int tag; @synthesize tag;를 선언되면 컴파일러는
- (void)setTag:(int)newTag
- (int)tag
- (int)tag
와 같은 한쌍의 접근자를 생성할 것이다. 이렇게 생성된 접근자는 디폴트로 threadsafe 하다. @property만 선언했다면, 구현파일에
getter 와 setter를 기술하는 것은 프로그래머의 몫이다. 즉 @synthesize를 통해 자동생성하거나, 프로그래머가 직접 구현해줘야 한다. 그렇지 않으면 컴파일 에러가 발생할 것이다.
getter 와 setter를 기술하는 것은 프로그래머의 몫이다. 즉 @synthesize를 통해 자동생성하거나, 프로그래머가 직접 구현해줘야 한다. 그렇지 않으면 컴파일 에러가 발생할 것이다.
@property 지시어와 함께 사용할 수 있는 속성들이 있는데, getter와 setter울 생서을 위한 속성이 된다.
Property Attributes
| Attribute | Description |
| readonly | getter 만을 생성한다. readwrite 속성과 상반된다. |
| readwrite | 디폴트 값이며, getter 와 setter 를 모두 생성한다. |
| copy | setter 에서 인자를 인수변수에 저장할 때, 인자의 복사본을 저장한다. 객체 포인터 타입에만 유효한 속성이다. (primitive 타입은 항상 복사되기 때문) 리시버가 센더의 인자값을 변경하지 못하게 할 때 사용한다. |
| assign | 인스턴스 변수에 레퍼런스 카운팅 없이 단순 할당한다. 가비지 컬렉션이 존재하는 환경에서 참조를 유지하고 싶거나, 인자값이 변경불가능할 때 사용한다. |
| retain | assign과 유사하며, 가비지 컬렉션이 없는 Managed memory 환경에서 객체의 참조 카운터를 증가 시킨다. |
| getter=name | 지정한 name 이름으로 getter 를 생성한다. getter와 setter의 표준 패턴을 위반해서 Key-Value Coding 과 같은 기술들이 인식할 수 없게 될수도 있기 때문에 사용에 주의해야한다. |
| setter=name | 지정한 name 이름으로 setter 를 생성한다. |
| nonatomic | 디폴트로 생성된 setter 는 atomic 속성을 갖는다. 락을 사용하여 thread-safe 하지만, 상당한 오버헤드를 수반한다. 쓰레드의 개입이 없을 경우, 명시적으로 nonatomic 으로 선언하여 performance 를 높이는게 좋다. |
7. Class Methods
클래스 메소드는 메소드 이름 앞에 + 기호를 갖는다. 모든 클래스는 런타임에 그 클래스 인스턴스의 identity와 behavior를 정의하는
하나의 Class 객체를 생성한다. 클래스는 이 Class 객체가 응답하는 메시지를 정의한다. Objective-C의 클래스 메소드는 자바와 비슷한 역할을 하지만 기술적으로는 다르다.
@interface RandomSequece : NSObject {
long long int seed;
}
+ (NSNumber*)number;
+ (NSNumber*)string;
- (NSNumber*)nextNumber;
- (NSString*)string;
@end
...
NSNumber *n = [RandomSequence number];
NSString *s = [RandomSequence string];
관례적으로 클래스 메소드를 먼저 정의하고, 인스턴스 메소드를 정의한다. 자바에서 클래스메소드는 this 키워드를 사용할 수 없지만, Objective-C 의 클래스메소드 에서는 self 키워드를 사용할 수 있다. 클래스 메소드에 self 는 Class 객체를 가리키며, 인스턴스 메소드 처럼 서브클래스에 상속할 수 있으며 오버라이딩 또한 가능하다.
@interface Classy : NSObject {
+ (void)greeting;
+ (NSString*)salutation;
}
@end
@implementation
+ (void)greeting {
NSLog(@"%@, world!", [self salutation]);
}
+ (NSString*)salutation {
NSLog(@"Greetings");
}
@end
@interface Classic : Classy
+ (NSString*)salutation;
@end
+ (NSString*)salutation {
return (@"Hello");
}
@end
...
[Classy greeting]; // Logs "Greetings, world"
[Classic greeting]; // Logs "Hello, world!"
[Classic greeting] 은 Classy Class 객체에 메시지를 보내고, [self salutation]은 해당 Cass 클래스 객체에 메시지를 보낸다.
[Classic greeting] 은 greeting 메소드가 없지만, 수퍼클래스로부터 상속받은 greeting 메시지를 호출하며, [self salutation] 은 Classic
Class 객체에 메시지를 보낸다.
Class 객체에 메시지를 보낸다.
8. Constructing Objects
java 에서는 객체를 생성하는 문법을 존재하여, 객체를 생성하는 방법을 명시적으로 제약한다. 반면 Objective-C 는 객체를
생성하는 방법을 클래스 설계자가 결정하도록 한다.
생성하는 방법을 클래스 설계자가 결정하도록 한다.
객체를 생성하는 과정은 2가지 과정을 거친다.
1) 메모리 구조 할당
2) 인스턴스 초기화
@interface RandomSequence : NSObject {
long long seed;
}
- (id)init;
- (id)initWithSeed:(long long)startingSeed;
@end
@implementation RandomSequence
- (id)init {
self = [super init];
if (self != nil) {
seed = 1;
}
return (self);
}
- (id)initWithSeed:(long long)startingSeed {
self = [super init];
if (self != nil) {
seed = startingSeed;
}
return (self);
}
@end
...
RandomSequence *r1 = [[RandomSequence alloc] init];
RandomSequence *r2 = [[RandomSequence alloc] initWithSeed:-43 ];
RandomSequence * r3 = [RandomSequence new];
alloc 은 NSObject 에 정의된 클래스 메소드 +(id)alloc 이다. 객체를 생성하기 위해 클래스 참조를 사용하여 메모리를 할당하고,
그것을 isa 변수에 할당한다. 그리고 인스턴스를 모두 0으로 채운뒤, 참조를 반환한다. 이 시점에서 요청된 객체가 존재하지만
아직 초기화는 되지않았다. init 메시는 객체를 초기화를 담당하며, 이메시지가 반환되면 깨체는 사용할 준비가 된 상태가 된다.
그것을 isa 변수에 할당한다. 그리고 인스턴스를 모두 0으로 채운뒤, 참조를 반환한다. 이 시점에서 요청된 객체가 존재하지만
아직 초기화는 되지않았다. init 메시는 객체를 초기화를 담당하며, 이메시지가 반환되면 깨체는 사용할 준비가 된 상태가 된다.
new 도 NSObject의 클래스 메소드로 내부적으로 alloc과 init 를 호출한다
- (id)init...계열의 메소드를 오버라이드 하거나 재정의 해서 객체생성을 커스터마이징 할 수 있다.
+ (id)alloc 또는 +(id)new 를 재정의 해서는 안된다.
9. Writing an init Method
9. Writing an init Method
Objective-C에서 생성자를 작성하기 위해서 4가지 계약을 충족해야 한다
1) 수퍼 클래스의 생성자를 호출한다 : [super init]
2) 자신의 self 변수를 업데이트 한다 : self = [super init]
3) nil 객체 검사를 한다 : if (self != nil ) { ... }
4) 자신의 포인터를 반환한다 : return self
모든 생성자는 수퍼클래스의 생성자를 호출해야한다. 자바는 언어 차원에서 이를 지원하지만, Objective-C 는 프로그래머에게
책임이 있다. self 를 변경하는 것은 자바 프로그래머에게는 이상하지만, Class Cluster를 위해 핵심이 되는 부분이다.
책임이 있다. self 를 변경하는 것은 자바 프로그래머에게는 이상하지만, Class Cluster를 위해 핵심이 되는 부분이다.
nil 객체 검사를 하는 이유는, 반드시 메모리 할당이 성공한다고 보장할 수 없기 때문이다. 메모리 고갈로 인한 실패가 있을 수 있기
때문에 방어적인 프로그램을 위한 것이다. 모든 잘 작성된 생성자는 위의 4가지 조건을 만족해야 한다
때문에 방어적인 프로그램을 위한 것이다. 모든 잘 작성된 생성자는 위의 4가지 조건을 만족해야 한다
Chaining Initializers
자바에서는 명시적인 생성자 호출 문법을 가지고 있어서, 특정한 수퍼클래스의 생성자나 자신의 생성자를 호출 할 수 있다.
Objective-C에서는 이러한 문법은 없지만, 동일한 원리로 수퍼클래스나 자신의 init...계열의 메시지로 초기화가 가능하다.
Designated Initializer
Objective-C 의 많은 클래스들이 "설계된" 생성자를 갖으며, 객체 생성시 이를 사용하여 초기화를 해야한다
그렇기 때문에 이러한 클래스들을 사용할 경우에는 문서를 참조해야 한다.
Convenience Constructors
클래스 메소드의 일반적인 용례는 복잡한 객체 생성 및 초기화를 간소화시킷는 것이다.
Cocoa framework의 NSDictrionary 클래스는 [NSDictionary dictionary] 클래스 메소드를 제공하며, 이것은
[[NSDictionary alloc] init] 와 동일하다
Objective-C 에서도 선택적으로 - (void)finalize 메소드를 오버라이드 할수 있다. 이 메시지는 가비지 컬렉터에 의해 객체가 파괴되기
전에 호출된다. 모든 finalize 메소드는 반환되기 직전에 수퍼클래스의 finalize 메시지를 호출해야한다
- (void)finalize {
if (file != nil) {
[file close];
file = nil;
}
[super finalize]
}
11. etc...
Inner / Anonymous Classes (내부 클래스와 익명클래스)
Inner / Anonymous Classes (내부 클래스와 익명클래스)
내부 클래스와 익명클래스는 코드 캡슐화나 어댑터로 사용되는데, Objective-C 에서는 비공식 프로토콜과 코드 블록을
사용하여 구현된다. (코드 블록은 변수에 실행가능한 코드 블록 할당을 허용하는 Objective-C 언어에 최근 추가된 개념이다)
Object Arrays
Objecitve-C에서는 C object 포인터 배열이나 NSArray 컬렉션 클래스를 사용하여 구현한다
final
final 키워드를 지원하지 않으며, 클래스 상속이나 메소드 오버라이딩을 막을 수 없다. 변수에 적용 할 경우, const가 유사하다.
abstract
Objective-C 의 모든 클래스와 메소드는 구체 클래스이다
package
Objective-C에는 패키지가 없으며, 패키지 범위 또한 없다.
'Objective-C' 카테고리의 다른 글
| Objective-C 문자열 조작 메서드 (0) | 2011.04.29 |
|---|---|
| 다중인자를 갖는 PerformSelector 메시지 (0) | 2011.03.23 |
| Protocol 과 Category (0) | 2011.03.22 |
| Objective-C 훑어보기 (2) | 2011.03.20 |
| [Cocoa] Cocoa Design Pattern (0) | 2011.03.20 |
| HMAC-SHA1 구현 (0) | 2011.03.03 |
설정
트랙백
댓글
글
[Cocoa] Cocoa Design Pattern
Objective-C
2011. 3. 20. 01:44
'Objective-C' 카테고리의 다른 글
| Objective-C 문자열 조작 메서드 (0) | 2011.04.29 |
|---|---|
| 다중인자를 갖는 PerformSelector 메시지 (0) | 2011.03.23 |
| Protocol 과 Category (0) | 2011.03.22 |
| Objective-C 훑어보기 (2) | 2011.03.20 |
| [Cocoa] Cocoa Design Pattern (0) | 2011.03.20 |
| HMAC-SHA1 구현 (0) | 2011.03.03 |
설정
트랙백
댓글
글
HMAC-SHA1 구현
Objective-C
2011. 3. 3. 23:37
@interface NSData (ATOAuth) - (NSData*)dataByHmacSHA1EncryptingWithKey:(NSData*)key; @end
#import "NSData+EOUtil.h"
#include <commoncrypto/commonhmac.h>
@implementation NSData (ATOAuth)
- (NSData*)dataByHmacSHA1EncryptingWithKey:(NSData*)key
{
void* buffer = malloc(CC_SHA1_DIGEST_LENGTH);
CCHmac(kCCHmacAlgSHA1, [key bytes], [key length], [self bytes], [self length], buffer);
return [NSData dataWithBytesNoCopy:buffer length:CC_SHA1_DIGEST_LENGTH freeWhenDone:YES];
}
@end
'Objective-C' 카테고리의 다른 글
| Objective-C 문자열 조작 메서드 (0) | 2011.04.29 |
|---|---|
| 다중인자를 갖는 PerformSelector 메시지 (0) | 2011.03.23 |
| Protocol 과 Category (0) | 2011.03.22 |
| Objective-C 훑어보기 (2) | 2011.03.20 |
| [Cocoa] Cocoa Design Pattern (0) | 2011.03.20 |
| HMAC-SHA1 구현 (0) | 2011.03.03 |