Objective-C 훑어보기

Objective-C 2011. 3. 20. 23:40



iPhone 의 인기와 더불어 주목받고 있는 Objective-C 언어에 대해서 간략히 알아보자. 
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

와 같은 한쌍의 접근자를 생성할 것이다. 이렇게 생성된 접근자는 디폴트로 threadsafe 하다. @property만 선언했다면, 구현파일에
 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 객체에 메시지를 보낸다. 

 

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 메시는 객체를 초기화를 담당하며, 이메시지가  반환되면 깨체는 사용할 준비가 된 상태가 된다. 
new 도 NSObject의 클래스 메소드로 내부적으로 alloc과 init 를 호출한다

- (id)init...계열의 메소드를 오버라이드 하거나 재정의 해서 객체생성을 커스터마이징 할 수 있다. 
+ (id)alloc  또는 +(id)new 를 재정의 해서는 안된다. 



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를 위해 핵심이 되는 부분이다.
nil 객체 검사를 하는 이유는, 반드시 메모리 할당이 성공한다고 보장할 수 없기 때문이다. 메모리 고갈로 인한 실패가 있을 수 있기
때문에 방어적인 프로그램을 위한 것이다.  모든 잘 작성된 생성자는 위의 4가지 조건을 만족해야 한다 

Chaining Initializers
자바에서는 명시적인 생성자 호출 문법을 가지고 있어서, 특정한 수퍼클래스의 생성자나 자신의 생성자를 호출 할 수 있다.
Objective-C에서는 이러한 문법은 없지만, 동일한 원리로  수퍼클래스나 자신의 init...계열의 메시지로 초기화가 가능하다.

Designated Initializer
Objective-C 의 많은 클래스들이 "설계된" 생성자를 갖으며, 객체 생성시 이를 사용하여 초기화를 해야한다
그렇기 때문에 이러한 클래스들을 사용할 경우에는 문서를 참조해야 한다. 

Convenience Constructors
클래스 메소드의 일반적인 용례는 복잡한 객체 생성 및 초기화를 간소화시킷는 것이다. 
Cocoa framework의  NSDictrionary  클래스는 [NSDictionary dictionary]  클래스 메소드를 제공하며, 이것은
[[NSDictionary alloc] init]  와 동일하다 


 
10. Destructors
Objective-C 에서도 선택적으로 - (void)finalize 메소드를 오버라이드 할수 있다. 이 메시지는 가비지 컬렉터에 의해 객체가 파괴되기
전에 호출된다. 모든 finalize 메소드는  반환되기 직전에 수퍼클래스의 finalize  메시지를 호출해야한다
- (void)finalize {
if (file != nil) {
[file close];
file = nil;
}
[super finalize]
}   

 
   
11. etc...

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
  • sungsik81 2011.03.22 09:49 ADDR 수정/삭제 답글

    날 위한 포스트인가... 두둥...

  • 로그 @로그 2011.03.23 14:00 신고 ADDR 수정/삭제 답글

    예전에 자바 개발자를 위한 objective-c 보고 정리했던 거에요.. 정리라기 보단...
    책에서 그대로 가져온...^^;;

[Mac]launch daemon vs launch agent

운영체제로그/MacOS 2010. 12. 11. 16:37


운영체제 부팅과 함께 프로그램을 실행시키는 2가지 형태의 방법이 있다. 
launch daemon 으로 실행하는 방법과, launch agent 로 실해하는 방법이 그것인데, 
각각 윈도우에서 서비스 , 시작프로그램으로 실행하는 것과 같다. 

[Launch daemon]
사용자 로그인없이도 실행이 가능하지만,  GUI 상에서 정보를 보여줄 수는 없다. 
웹서버와 데이터베이스 서버 구동을 위해 적합한 방법이라 할수 있겠다.  프로그램들은 plist 설정파일에 
실행할 명령 및 옵션과 함께 기술된다.   /System/Library/LaunchDaemons 폴더에는 애플에서 제공되는 
daemon들을 위한 설정파일이 위치하고, /Library/LaunchDaemons 폴더에는 사용자 및 그외의
 daemon들을 위한 설정파일들이 저장된다. 

[Launch agent]
agent는 사용자를 대신하여 실행되는 프로그램이기 때문에 반드시 사용자가 로그인되어 있어야 한다. 
GUI를 통해 정보를 보여줄 수 있기 때문에,  SNS 애플리케이션과 같이 자주 사용하는 애플리케이션 등록에
적한한 방법이다. 역시 plist 포맷으로 기술되며, 모든 사용자가 공통으로 사용할 프로그램은  /System/Library/LaunchAgents 와 /Library/LaunchAgents 폴더에 설정파일이 저장된다. 사용자별 설정파일은 ~/Library/LaunchAgents 폴더에 저장된다. 

'운영체제로그 > MacOS' 카테고리의 다른 글

[Mac]launch daemon vs launch agent  (0) 2010.12.11
[Mac]시작프로그램/Script 등록하기  (0) 2010.12.11

[Mac]시작프로그램/Script 등록하기

운영체제로그/MacOS 2010. 12. 11. 15:43


Mac에서 시작 프로그램를 다음과 같이 등록할 수 있다.

시스템 환경설정(System Preferences) > 계정설정(Account) > "로그인 항목" 에

부팅완료 후 자동실행을 할 애플리케이션을 추가하거나 삭제할 수 있다.

MySQL을 설치하고, MySQL 서버를 시작과 동시에 구동하려 했는데... 위 항목에서는

스크립트를 추가할 수가 없었다.

launchd를 사용하여 데몬으로 시작시키는 방법을 알아보았다~

1 PropertyEditor 를 실행시켜서 아래와 같이 입력한다.


2. com.mysql.mysqld.plist 라는 이름으로 저장한다.

3. 이 파일을 /Library/LaunchDaemons 폴더로 복사한다.

4. 파일의 소유자와 그룹, 권한을 다음과 같이 변경한다.

$cd /Library/LauchDaemons$sudo chown root com.mysql.mysqld$sudo chgrp wheel com.mysql.mysqld$sudo chmod 644 com.mysql.mysqld

5. sudo launchctl load com.mysql.mysqld.plist 명령을 수행하여, launchd 에 작업을 등록한다.

* plist 파일에 지정합 키-값은 launchd 에 의해 미리 정해진 옵션으로 Program을 daemon으로 수행하기 위한 옵션으로 작용한다.

plist 파일을 변경하고, 다시 적용하기 위해서는 먼저 launchctl unload com.mysql.mysqld.plist 명령으로 언로드를 수행하고 다시 적용시켜야한다

디폴트로 mysqld 는 /etc/my.cnf 파일에 정해진 설정을 읽어서 구동되는데, 이 파일에 옵션을 줄 수도 있지만, plist 파일을 사용하면

모든 설정을 한곳으로 모을수 있는 장점이 있다. mysqld 에 줄수 있는 옵션들은 /etc/my.cnf 파일을 열어 확인을 하고,

plist 파일의 ProgramArguments 키의 array 값의 인자로 지정을 하면된다.

plist 파일의 추가할 수 있는 키옵션들은 man launchd.plist 명령을 통해 확인하자.

'운영체제로그 > MacOS' 카테고리의 다른 글

[Mac]launch daemon vs launch agent  (0) 2010.12.11
[Mac]시작프로그램/Script 등록하기  (0) 2010.12.11