2009-06-14 6 views
1

방금이 오류를 알아 내려고 지난 3 시간을 보냈습니다. 나는 누군가에게 그것을 설명해주기를 바란다. 그래서 나는 그것을 다시하지 않는다.인스턴스 변수를 할당하는 아이폰

"self"를 사용하지 않고 NSString 인스턴스 변수를 할당했습니다. 클래스 ("self")가 릴리스되면 "잘못된 액세스"오류가 발생했습니다. 동일한 변수 선언을 사용하여 다른 클래스에서 똑같은 일을 수행했으며이 오류가 발생하지 않았습니다. 아래는 제 코드입니다. 나는 파손 된 라인을 주석 처리했고 아래 라인은 그것을 고쳤다. 그러나 나는 왜 ...이 문제를 일으키지 않는 다른 인스턴스 변수가 있다는 것을 알지 못합니다. 인스턴스 변수를 지정할 때 항상 "자체"예약어를 사용해야합니까? 저에게 알려주세요. 클래스 방법 내에서 NoteText 할당

선언

@property (nonatomic, readonly, assign) int IID; 
@property (nonatomic, assign) int ProfileIID; 
@property (nonatomic, retain) NSDate *NoteDate; 
@property (nonatomic, copy) NSString *NoteText; 

코드

// the default date format is Year-Month-Day 
NSDateFormatter *df = [[[NSDateFormatter alloc] init] autorelease]; 
[df setDateFormat:kDateFormat]; 

IID = sqlite3_column_int(selectstmt, 0); 
ProfileIID = sqlite3_column_int(selectstmt, 1); 

// notice this does not cause a memory error 
NoteDate = [[df dateFromString: [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)]] retain];  

// the following may be NULL. Checking using the sqlite3_column_text method 
const char *columnText = (const char *)sqlite3_column_text(selectstmt, 3); 
if(columnText != NULL) 
{ 
    // this causes a memory error 
    //NoteText = [NSString stringWithUTF8String: columnText ]; 
    // this does not cause memory error 
    self.NoteText = [NSString stringWithUTF8String: columnText ]; 
} 

답변

5

NoteDate = [[df dateFromString: [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)]] retain]; 

괜찮하는 이유입니다. 문자열을 할당하지 않고 NSStringstringWithUTF8String을 호출하면 변수의 소유권을 가져 가지 않으므로 반환 된 문자열은 자동으로 리 릴리스됩니다. 그러나 그것을 유지하기 때문에 문제가 발생하지 않습니다.

변수가 자동으로 반환되는 경우 각 이벤트가 끝날 때 자동 복구 풀이 비워지면 변수가 해제됩니다 (자세한 내용은 autorelease pools 참조). 인스턴스 변수를 사용하면 좋지 않습니다. 왜냐하면 현재 이벤트 이후에 계속 있어야하기 때문입니다.

당신은에 의해 변수를 할당 할 때 :

귀하의 setter 메소드가 호출되지 않습니다
NoteText = [NSString stringWithUTF8String: columnText]; 

때문에, 반환 된 문자열 (이, 다시 오토 릴리즈한다)에서 오토 릴리즈 풀에서 해제 그렇게 유지되지 않으며, 이벤트의 끝. 그것을 방지 변수를 당신의 setter 메소드를 호출하고 유지

[self setNoteText:[NSString stringWithUTF8String: columnText]]; 

: 라인이 또 다른 글을 쓰는 방식이기 때문에,

self.NoteText = [NSString stringWithUTF8String: columnText]; 

않습니다 문자열을 유지 :

로 호출 현재 이벤트가 끝날 때 발표되지 않습니다.

4

는 직접 인스턴스 변수를 설정하고, 상기 합성 세터 메소드를 호출하지 않는다. 이것은 문자열이 유지되지 않고 있거나 (설정자의 경우 복사 됨) 이미 충돌 한 객체를 해제하려고 할 때 발생한다는 것을 의미합니다. 이것을하십시오 :

self.NoteText = [NSString stringWithUTF8String: columnText ]; 

이것은 당신의 세터를 부를 것이며, 모두 잘 될 것입니다.

: 모든 ivars에서 마찬가지입니다. 당신이 변수를 유지 때문에

myVariable = someValue; // Sets the ivar directly. 
self.myVariable = someValue; // calls [self setMyVariable]. 
+0

젠장,이 xD Nice 응답을 입력하고있었습니다. –

0

이 ivar와 setter 방법 사이의 혼란은 내가 결코 나의 세터와 나의 ivars를 같은 이름으로 말하지 않는다.

Apple은 일반적으로 밑줄 (_)로 시작하는이 ivars 이름을 지정합니다 (예 : 참고 텍스트). 내 경우에는 접두사가 i 이블에 대해 인 것으로 나타났습니다.

NSString* i_name; 

@property (nonatomic, copy) NSString* name; 

@synthesize name = i_name; 

당신이 쉽게 바르 할당 사이의 차이를 말할 수있는 그 방법 :이 정의되어 있기 때문에,

i_name = [[whatever title] retain]; 

와 setter 메소드 호출

self.name = [whatever title]; // Equivalent to [self setName:[whatever title] 

세터를 예를 들어 copy (또는 retain과 비슷하게)는 전달 된 변수의 소유권을 가져 오며 이전 값의 소유권을 해제합니다. ivar 할당은 그 일을하지 않습니다.

성함 이름은 소문자로 시작해야하며 그렇지 않을 경우 이 아니어야합니다.

+0

Apple은 제 3자가 Apple 코드에 범주를 추가하는 경우와 같이 충돌을 피하기 위해 ivars 및 개인 메서드 모두에 대해 맨 앞의 밑줄을 사용합니다. (사실, Apple *은 자체적으로 사용하기 위해 *를 보유합니다.) 그러나 관용구는 ivars를 해당 속성과 동일한 이름으로 지정해야합니다. 사실 64 비트 런타임에서는 일치하는 ivar없이 * 속성을 선언 할 수 있습니다. 속성의 도트 구문이 혼동을 일으키는 경우 ivars의 이름을 바꾸는 대신 명시 적으로 setter 메서드를 사용하는 것이 좋습니다. 메서드가 호출 될 때 훨씬 더 분명 해져서 문제를 즉시 해결할 수 있습니다. –

관련 문제