2012-06-25 2 views
0

이 사이트를 처음 사용하기 때문에 Objective-c를 처음 사용하게되었습니다. 이것은 간단한 질문이지만 어떤 이유로 나는 많은 문제가 있다고 확신합니다. 이 응용 프로그램은 사용자가 텍스트 필드를 통해 문자열을 입력하도록 설계되었습니다. 그러면 나머지 문장을 선택하여 표시합니다. 문제는 my * 이름이 키보드 메소드 후에 유지되고 changelabel 메소드에서 한 번 작동한다는 것입니다. 그럼 내가 다시 changelabel 메서드를 호출하는 버튼을 누르면, 이름이 공개되고 응용 프로그램을 충돌하는 것 같습니다. # import를 # import를 "Array.h"NSString이 한 번 작동하지 않는다면

@interface RandomBoredViewController : UIViewController { 
UILabel *label; 
UIButton *button; 
UITextField *textField; 
Array *array; 
NSString *name; 
NSString *description; 
NSMutableString *whole; 
} 
@property (nonatomic, retain) IBOutlet UILabel *label; 
@property (nonatomic, retain) IBOutlet UIButton *button; 
@property (nonatomic, retain) IBOutlet UITextField *textField; 
@property (nonatomic, retain) Array *array; 
@property (nonatomic, retain) NSString *name; 
@property (nonatomic, retain) NSString *description; 
@property (nonatomic, retain) NSMutableString *whole; 

-(IBAction) keyBoard; 
-(IBAction) changeLabel; 

@end 

내하는 .m

#import "RandomBoredViewController.h" 

@implementation RandomBoredViewController 

@synthesize label; 
@synthesize checker; 
@synthesize button; 
@synthesize textField; 
@synthesize array; 
@synthesize name; 
@synthesize description; 
@synthesize whole; 


-(IBAction) changeLabel { 
NSLog(@"Button being pushed"); 
description = [array getString]; 
NSLog(@"%@",description); 
NSLog(@"%@",name); 
name = [NSString stringWithString:name]; 
whole = [NSMutableString stringWithString:name]; 
NSLog(@"%@",name); 
NSLog(@"%@",whole); 
[whole appendString:description]; 
NSLog(@"%@",name); 
NSLog(@"%@",whole); 
label.text = whole; 
NSLog(@"%@",name); 
} 

-(IBAction) keyBoard { 
name = [NSString stringWithString:textField.text]; 
NSLog(@"%@",name); 
label.text = [NSString stringWithString: name]; 
[textField resignFirstResponder]; 
} 

- (void)viewDidLoad { 
[super viewDidLoad]; 
array = [[Array alloc]init]; 
[array createArray]; 
NSLog(@"%i",[array arrayCount]); 
whole = [[NSMutableString alloc]init]; 
name = [[NSString alloc]init]; 
} 

- (void)dealloc { 
[super dealloc]; 
[label release]; 
[button release]; 
[textField release]; 
[array release]; 
//[name release]; 
[description release]; 
} 

@end 
+0

이 줄은 약간 중복 된 것처럼 보입니다 :'name = [NSString stringWithString : name];'오류의 원인 일 수 있습니다. –

답변

1

소우주에서 한 가지를 취하면 게시 한 코드가 인스턴스 변수 및 속성 인 name이라는 두 가지를 만듭니다.

인스턴스 변수는 저장소에 직접 액세스됩니다. 그들은 행동이 없습니다.

속성은 getters 및 setters를 통해 액세스되는 명명 된 특성입니다. 그래서 그들은 임의의 행동을 할 수 있습니다. 인스턴스 변수 또는 인스턴스 변수에서 계산 된 값 또는 다른 방법으로 계산되거나 계산 된 값을보고 할 수 있습니다. 관련하여 세터는 retain, assign이거나 다른 방식으로 행동 할 수 있습니다.

인스턴스 변수는 자신이 속한 클래스의 인스턴스에서만 액세스 할 수 있습니다. 속성은 일반적으로 누구나 액세스 할 수 있도록 고안되었습니다.

유지는 동작이므로 사용자가 name 속성으로 돌렸으므로 그 값을 설정하면 retain이됩니다. 인스턴스 변수는 동작을 할 수 없기 때문에 값을 설정하면 retain 또는 그 밖의 것이 나오지 않습니다. 그 결과

,이 라인 :

name = [NSString stringWithString:name]; 

새로운 문자열을 생성하고 비 소유 참조를 반환합니다. 즉,이 autorelease pool의 지속 기간 동안 확실히 지속될 것입니다. 즉, autorelease 풀을 수동으로 제어하지 않았다고 가정하면 명시 적으로 인수로 전달하거나 안전하게 반환 할 수 있습니다.

인스턴스 변수에 해당 참조를 저장합니다. 인스턴스 변수에는 동작이 없으므로 참조가 저장되지만 여전히 해당 객체를 소유하지 않습니다. autorelease 풀이 지속되는 동안 만 사용하는 것이 안전합니다.

그래서이 방법으로 액세스하면 안전합니다. 나중에 액세스하면 안전하지 않습니다.

당신이 갔던 대신하는 경우 :

self.name = [NSString stringWithString:name]; 

그럼 당신은 속성의 새 값으로 해당 문자열을 설정 한 것입니다. 속성에 retain 동작이 있기 때문에 나중에 달리 말할 때까지 문자열 개체에 완전히 안전하게 액세스 할 수 있습니다.

인스턴스 변수와 정확히 같은 이름의 속성이 있으므로 나중에 name 또는 self.name으로 액세스 할 수 있습니다. 마찬가지로 수동으로 소유 참조를 확보했다면 속성 대신 인스턴스 변수에 직접 저장할 수도 있습니다.

위에서 제안했듯이 ARC를 사용하면 컴파일러에서 이러한 모든 문제를 해결할 수 있습니다.

이 문제는 코드가 다운되는 원인입니다. 유효하지 않은 참조에 액세스하려는 경우가 발생합니다. 소유권을 소유했다면 적어도 소유권을 유지하는 한 계속 존재했을 것입니다.

+0

나를 도와 주셔서 고마워. 이 깊이있는 설명은 내 앱을 수정하고 언어를 이해하는 데 필요한 것입니다. 이것은 온라인 에서처럼 처음으로 게시 한 것이므로 내 문제가 심각하게 다루어지고 트롤되지 않았 음을 알았습니다. 다시 한 번 감사드립니다. –

0

self.name 가끔이 물건뿐만 아니라 나를 혼란스럽게하고 그것을 위해 당신이 고려하는 것이 좋습니다 사용해보십시오 이 경우 아크의 사용이 대부분을 피할 수 있습니다.

속성을 사용할 때는 항상 self.propertyName과 propertyName (only)을 사용해야하며 해당 포인터 값에 직접 액세스하는 것과는 대조적으로 접근 자 (get propertyName, set propertyName)를 사용합니다.

규칙에는 두 가지 예외가 있습니다. init 및 dealloc은 자체를 사용하면 안됩니다.

self.name = [NSString stringWithString:name]; 

당신은 기술적으로 또한 변수를 초기화 init 메소드 을해야한다, 그리고 난 당신이 당신의 dealloc 방법에 [슈퍼의 dealloc] 마지막되지 첫번째 호출해야합니다 생각하지만, 문제가되지 이잖아 그냥 (중요하지 않을 수 있습니다

+0

'self.' 물건은 좋지만 변수는'viewDidLoad'에'init'되어 있습니다. 다시 초기화 할 필요는 없습니다. –

+0

네, 그렇지만 초기화 할 곳이 아닙니다. 하지만 그렇습니다. 더 작고 단순한 프로젝트의 경우에는 문제가되지 않을 것입니다. –

+0

왜 그것이 "초기화 될 것"이라고 생각하지 않습니까? 다른 어느 곳보다 좋은 곳 같아. 실제로'self.name = [NSString stringWithString : @ "anything"];과 같은 것을 호출하는 것은'@ synthesize'가 생성 한 setter에서 당신을 위해'init'을 처리 할 것이라고 나는 믿습니다. –

3

NSore의 자동 릴리스 인스턴스에 이름을 설정하고 있는데, 이는 아마도 앱이 충돌하게 만드는 원인 일 것입니다.

사용

self.name = [NSString stringWithString:textField.text]; 

있는 NSString을 유지하고 출시되는 것을 방지 할 수 있습니다 귀하의 합성 뮤 테이터.

+0

감사합니다. 이것을 보면서 시간을내어 주셔서 대단히 감사합니다. 수정이 가장 쉬운 방법 중 하나라고 확신하지만, 매우 도움이되었습니다. –

+0

기꺼이 도와 드리겠습니다! –

0

changeLabel에서 인스턴스 변수를 변경하면 이전 값을 해제하고 새 값을 유지해야합니다. 접근자를 사용하여 메모리 관리 작업을 수행 할 수 있습니다. 또한 dealloc의 구현에서 인스턴스 변수를 해제하면 뒤에 [super dealloc]을 호출해야한다고 생각합니다.

코코아 메모리 관리에 익숙하지 않은 경우 (심지어 사용자가 그렇다고하더라도) 가장 좋은 방법은 ARC (Automatic Reference Counting)를 활성화하고 컴파일러가 처리하도록하는 것입니다.

+0

감사합니다. 나는 ARC를 살펴 보았지만 정말 멋져 보였지만 나는 여전히 스노우 레오파드를 사용하고 xcode 4를 실행할 수 없다. 그러나 감사한다. –

관련 문제