보관물

Posts Tagged ‘Property’

[cocos2d] schedule사용시 일부 parameter의 out of scope현상

7월 21, 2011 댓글 남기기

Problem

schedule을 사용하여 일정간격으로 특정 fuction(testMethod)를 실행시키려는 도중
testMethod에서 일부 parameter를 정상적으로 참조하지 못하는 문제가 발생.

breakpoint를 찍어 보면 out of scope라고 알려줌.

관련 Source

Foo.h

@interface Foo : CCLayer {

 NSString *pBirdName;
XActionManager *pActionManager;

}
@end

Foo.m

#import “Foo.h”

@implementation Foo {

@synthesize pActionManager;

-(id) init {

…전략…
pBirdName = [NSString stringWithString:@”Peacock”];
pActionManager = [[XActionManager alloc] init];
…후략…

}

-(void) someFunction {

[self schedule:@selector(testMethod) interval:2.0f];

}

-(void) testMethod {

[self unschedule:_cmd];

…중략…
//pBirdName : out of scope
//pActionManager : 정상
[self anotherMethod:pBirdName actionManager:pActionManager];
…중략…

[self schedule:@selector(testMethod) interval:2.0f];

}

}

Cause

anotherMethod에서 pActionManager는 정상적으로 사용이 가능한데 pBirdName은 out of scope가 발생되고 있다.
그래서 의도한 결과가 나오질 않고 있는 상황.
이것은 autorelease와 관련이 있다.
-(id) init 의 실행이 끝나는 순간 pBirdName은 autorelease처리가 되기 때문에 out of scope가 발생된다.
이를 해결하기 위해서는 pBirdName의 retainCount를 증가(eg. [pBirdName retain])시키거나 property를 사용하는 방법이 필요하다.

Solution

pBirdName을 property를 선언하고 self.pBirdName으로 접근하니 정상적으로 동작한다.

Foo.h 에 추가

@property (nonatomic, retain) NSString *pBirdName;

Foo.m에 추가

@synthesize pBirdName;

-(id) init의 pBirdName부분을 수정

self.pBirdName = [NSString stringWithString:@”Peacock”];

-(void) testMethod에서 anotherMethod호출 부분을 수정

[self anotherMethod:self.pBirdName actionManager:pActionManager];

-(void) dealloc에 pBirdName추가

self.pBirdName = nil;

카테고리:cocos2d 태그:, ,

Custom classes, Properties

2월 20, 2011 댓글 남기기

Object Classes

Public Header (.h)

#import <Foundation/Foundation.h>

@interface Animal : NSObject
{

//instance variables
NSString *name;

}
//method declarations
-(NSString *)name;
-(void)setName:(NSString *)m_name;
@end

Private Implementation (.m)

#import “Animal.h”

@implementation Animal
-(NSString *)name {

return name;

}
-(void)setName:(NSString *)m_name {

name = m_name;

}
@end

Class내에서 선언된 method를 사용하고자 하는 경우 다음과 같은 형태로 사용한다.

[self setName:@”Andy”];

if ([self isDog]) {
//…
}

Properties

위의 sample code는 NSString 형태의 name이라는 변수에 대해서 getter/setter를 구현하였음.
이를 Properties와 Synthesize를 써서 같은 기능을 하도록 변경을 하면 다음과 같다.

Public Header (.h)

#import <Foundation/Foundation.h>

@interface Animal : NSObject
{

//instance variables
NSString *name;

}

@property (copy) NSString *name;

@end

Private Implementation (.m)

#import “Animal.h”

@implementation Animal

@synthesize name;

@end

ivars에서 정의한 이름과 property로 사용할 이름을 다르게 정의할 수도 있다.
아래의 sample code는 ivar는 _name으로 정의하였지만
property를 다음과 같이 정의함으로써 name으로 사용할 수있다.

Public Header (.h)

#import <Foundation/Foundation.h>

@interface Animal : NSObject
{

//instance variables
NSString *_name;

}

@property (copy) NSString *name;

@end

Private Implementation (.m)

#import “Animal.h”

@implementation Animal

@synthesize name = _name;

@end

property로 선언한 것을 self와 dot syntax를 활용할 수도 있다.

//self와 dot syntax를 사용한 경우
self.name = @”Lucy”;

//self와 dot syntax를 사용한 경우와 동일한 내용
[self setName:@”Lucy”];

//ivar에 직접 접근하는 경우 (accessor method를 사용안함)
name = @”Lucy”;

그러므로 self와 dot syntax를사용하고 setter를 별도로 구현하는 경우 다음의 경우를 주의해야한다.

-(void) setName:(NSString *)m_name {

//self.name은 [self setName:…]을 호출하므로 재귀적으로 무한루프에 빠지게됨
self.name = m_name;

}

참고자료

iPhone Application Development (CS193P) – Winter 2010 : iTunes U
3. Custom Classes, Object lifecycle, Autorelease, Objective-C Properties