보관물

Posts Tagged ‘Objective-C’

Node.js + ObjC = NodObjC.

node.js를 이용해서 재미있는 프로젝트가 무엇이 있는지를 찾던 중에 발견한 것입니다. 간단히 설명되어 있는 것은 objective-c와 node.js의 다리(bridge)라고 하는 군요.

몇가지 링크와 간단한 예제를 통해 맛을 보도록 하겠습니다.
프로젝트 홈페이지 – https://github.com/TooTallNate/NodObjC
간단한 윈도우를 띄운 예제 (이 예제를 조금 변경해서 실행해 보겠습니다.) – https://gist.github.com/1204212

위의 프로젝트 홈페이지를 통해 프로젝트를 다운 받습니다.
다운 받은 후에 예제의 자바스크립트 파일을 만듭니다. 그리고 node 커맨드로 실행만 하면 맥 윈도우를 만들 수 있습니다.

위의 예에서 보시는 것 처럼 창 타이틀에 제 블로그 주소와 Welcome이 보입니다.
그럼 위 윈도우를 실행하는 소스 코드를 보겠습니다.


var $ = require('[NodObjc의 폴더 위치]')

$.import('Cocoa')

var pool = $.NSAutoreleasePool('alloc')('init')
  , app  = $.NSApplication('sharedApplication')

app('setActivationPolicy', $.NSApplicationActivationPolicyRegular)

var menuBar = $.NSMenu('alloc')('init')('autorelease')
  , appMenuItem = $.NSMenuItem('alloc')('init')('autorelease')

menuBar('addItem', appMenuItem)
app('setMainMenu', menuBar)

var appMenu = $.NSMenu('alloc')('init')('autorelease')
  , appName = $._('Jongryong.wordpress.com. Welcome...')
  , quitTitle = $._('Quit ')('stringByAppendingString', appName)
  , quitMenuItem = $.NSMenuItem('alloc')('initWithTitle', quitTitle
                                        ,'action', 'terminate:'
                                        ,'keyEquivalent', $._('q'))('autorelease')
appMenu('addItem', quitMenuItem)
appMenuItem('setSubmenu', appMenu)

var styleMask = $.NSTitledWindowMask
              | $.NSResizableWindowMask
              | $.NSClosableWindowMask
var window = $.NSWindow('alloc')('initWithContentRect', $.NSMakeRect(0,0,200,200)
                                ,'styleMask', styleMask
                                ,'backing', $.NSBackingStoreBuffered
                                ,'defer', false)('autorelease')
window('cascadeTopLeftFromPoint', $.NSMakePoint(20,20))
window('setTitle', appName)
window('makeKeyAndOrderFront', window)

// set up the app delegate
var AppDelegate = $.NSObject.extend('AppDelegate')
AppDelegate.addMethod('applicationDidFinishLaunching:', 'v@:@', function (self, _cmd, notif) {
  console.log('got applicationDidFinishLauching')
  console.log(notif)
})
AppDelegate.register()

var delegate = AppDelegate('alloc')('init')
app('setDelegate', delegate)

app('activateIgnoringOtherApps', true)
app('run')

위 소스코드를 자세히 소개하지는 않겠습니다. 사실, 저도 잘 모릅니다. ^^;
아무튼 역시나 node.js를 이용한 다양한 시도중에 하나네요. 이런 클라이언트 기반 코드와 node의 통신 환경을 이용하면 간단한 맥용 클라이언트용 툴을 쉽게 만들 수도 있을 것 같습니다.
물론, 아직은 기본적인 것만 지원하는 것으로 보입니다.

objective-c 메모리 관리 개념과 프로퍼티 관계.

처음에 Objective-C를 접하게 되면 조금 생소하게 느껴지는 부분이 메모리 관리 부분이다. (여기서 논하고 있는 메모리는 alloc으로 생성되는 동적메모리 부분이다.)

1. 기본 사용

{
    DataObject *localOne = [[DataObject alloc]init];
    localOne.No = i;
    localOne.Data = i * 99;
    
    [self.ListData addObject:localOne];
    
    NSLog(@"%@\tListItem RC: %d", [localOne description], [localOne retainCount]);
    
    [localOne release];
}

일반적인 개념으로는 alloc을 하면, 해당 메모리가 생성되면서 retain count가 1 증가한다.
그리고, release를 하면 해당 retain count가 1 감소한다.
이런 과정을 통해 retain count가 0이 되면 가베지 컬렉터가 해당 동적 메모리를 회수하는 구조를 갖는다.

그 외에도 우리가 일반적으로 메모리를 해제한다고 생각하기 쉬운 변수에 nil을 대입하는 방법도 있으나, 이것은 단순히 해당 변수에 저장된 실제 메모리 위치의 포인터를 지우는 작업이므로 동적 메모리를 해제하는 것에는 작용하지 않는다.
따라서, 특정 변수에 클래스 인스턴스에 nil을 대입하기 전에 동적 메모리를 release하지 않으면 메모리 릭을 만들어 낼 수 있을 것이다. (주의)

2. 프로퍼티 사용 –

DataObject *currentObject;
@property (retain, nonatomic) DataObject *CurrentObject;

{
    i = i + 1;
    
    if (!self.CurrentObject) {
        self.CurrentObject = [[DataObject alloc]init];
    }
    
    self.CurrentObject.No = i;
    self.CurrentObject.Data = i * 99;
    
    [self.ListData addObject:self.CurrentObject];
    
    NSLog(@"%@\tListItem RC: %d", [self.CurrentObject description], [self.CurrentObject retainCount]);
    
    [self.CurrentObject release]; 
    self.CurrentObject = nil;
}

위와 같이 프로퍼티를 사용하는 환경에서는 retain count가 프로퍼티의 속성에 영향을 받는다. 지금은 프로퍼티의 속성이 retain으로 되어 있다는 것에 주목하고, 모든 소스는 프로퍼티로 사용한 것도 확인할 수 있다. 이런 환경에서 retain count의 변동을 확인해 보자.
역시 동적 메모리가 생성되는 alloc에서 retain count는 1 증가하게 된다.(retain count = 1)
그리고 self.CurrentObject에 대입하는 과정에서 프로퍼티 속성이 retain이므로 다시 retain count가 1 증가한다. (총 retain count = 2)
다음으로 self.ListData에 넣으면서 다시 retain count가 1 증가한다. (이제 retain count = 3)
이제 이 데이터를 배열에 넣어서 다른 메소드 등에서 사용할 것이니 retain count를 진정시킬 필요가 있다. (다른 메소드에서 배열에서 삭제하면 메모리가 정리되기를 원한다.)

그러기 위해 self.CurrentObject를 release하면서 retain count가 1 감소한다. (retain count = 2)
다음으로 self.CurrentObejct에 nil을 대입하면서 다시 retain count가 감소한다. (최종 배열에 남은 메모리는 retain count = 1)

1번에서 본 일반적인 상황과 다른 점 중에 하나가 nil을 대입하는 부분이다. 1에서는 단순히 변수에 nil을 대입하므로 retain count에 영향을 미치지 않지만, self.CurrentObejct는 프로퍼티 속성이 retain 이므로 nil을 대입하는 과정에서 retain count가 감소하는 것이다.

그럼, 프로퍼티의 속성을 assign으로 주면 어떻게 될까? 아직 속성에 대한 정확한 이해가 없다면, 한번 테스트해 보기를 권장한다.
이상과 같이 프로퍼티와 클래스 변수를 혼용해서 사용하고, 부주의하게 release와 nil대입을 사용하면 메모리를 낭비하게 될 수 있다.

이상 동적 메모리 관리에 대한 간단한 내용을 정리해 보았다.

인스턴스의 클래스 타입 확인…

인스턴스의 클래스 타입을 찾는 방법은 아래와 같이 두가지 함수를 사용할 수 있다.

  • isMemberOfClass
  • isKindOfClass

– isMemberOfClass의 경우는 해당 인스턴스가 특정한 클래스의 타입인지를 확인한다.

if([myobject isMemberOfClass:[NSString class]]) {
    .... //myobject가 NSString일 경우 실행
}

– isKindOfClass의 경우 해당 인스턴스가 특정 클래스의 상속 관계에 있어도 확인 가능하다.

if([myobject isKindOfClass:[UIView class]]) {
    .... //myobject가 UIView의 subClass여도 실행. 물론 myobject가 UIView여도 실행
}

인스턴스의 클래스를 확인해야 할 경우가 발생할 때 (팩토리 패턴 등)에 유용하게 사용 가능.

카테고리:Objective-C, Programming 태그:

전달 인자의 갯수가 미정일 때 코딩 방법… (Objective-C)

전달인자가 미정이고 이를 사용해서 특정 작업을 해야 하는 경우 …

-(void) methodname:(object)argCount, ...;  <- 이런 상황

몇개인지 모를 숫자를 더해주는 메소드를 작성해 본다.

-(void) sumNumber:(int)argCount, ...{
    va_list pList; //argument의 list를 저장
    
    va_start(pList, argCount); //va_list를 va_start를 이용해서 초기화

    int sum=0;

    for(int i =0;i<argCount;i++) {
        int arg = va_arg(pList, int);
        printf("The %dth arg is %d\n", i, arg);
        sum += arg;
    }
    
    va_end(pList); //va_end()를 이용해서 마친다.
    print("The total sum is %d\n", sum);
}


연속적인 문자의 출력이나 기타 등등.. 정해지지 않은 아규먼트를 이용할 때 사용해 볼 수 있다.

%d 블로거가 이것을 좋아합니다: