iPhone에서 예기치 않은 싱글 톤 클래스 행동, 내가 뭔가 잘못하고 있습니까?
-
05-07-2019 - |
문제
다음과 같이 싱글 톤 클래스를 구현하고 있습니다.
static Singleton* _singletonInstance;
@implementation Singleton
+(void)initialize
{
_singletonInstance = [[Singleton alloc] init];
}
+(Singleton*)instance
{
return(_singletonInstance);
}
누군가가 처음으로 인스턴스를 호출 할 때만 초기화 만 호출됩니다. 그런 다음 인스턴스 변수를 설정하기 위해 호출 할 수있는 메소드가 있습니다. 그래서 그것은 이렇게 보입니다.
_singleton = [Singleton instance];
[_singleton setupWithParams: blah];
이 싱글 톤의 인스턴스를 객체 안에서 얻으면 처음으로 잘 작동합니다. 그러나 싱글 톤의 인스턴스가 필요한 객체의 새 사본을 작성한 후 설정 함수를 호출하려고 할 때 액세스 오류가 잘못됩니다.
설정을 테스트하기 위해 설정 호출을하기 전에 인스턴스의 주소를 인쇄하고 동일한 주소를보고하지만 액세스 호출이 잘못된 오류 로그를 확인하면 완전히 다른 메모리 주소가 나열됩니다.
인스턴스에 대한이 포인터가 인쇄 할 때 왜 괜찮아 보이는지에 대한 아이디어가 있습니까? 그러나 전화를 걸 때 임의의 데이터를 가리키는 것처럼 보입니까?
해결책
포인터 값은 예전 이었기 때문에 유효한 것처럼 보이지만 메모리가 무료 였기 때문에 임의의 데이터처럼 보이는 이유입니다.
당신은 당신과 하나의 참조를 얻었습니다 [[Singleton alloc] init]
위, 그러나 a release
실행 중일 수있는 다른 곳? 나는 당신의 코드가 호출 할 것이라고 확신합니다 instance
, 그리고 release
나중에 코드가 참조를 얻지 못했지만 나중에. 그리고 어쨌든 싱글 톤에는 필요하지 않습니다. 그냥 추측 ...
다른 팁
당신은 당신의 _singletoninstance를 어딘가에 거래하고 있습니까?
훨씬 더 복잡하지만 매우 안정적인 버전의 Singleton Template를 사용하고 있습니다 (설명과 함께 Brandon "Quazie"Kwaselow 블로그):
static SampleSingleton *sharedSampleSingletonDelegate = nil;
+ (SampleSingleton *)sharedInstance {
@synchronized(self) {
if (sharedSampleSingletonDelegate == nil) {
[[self alloc] init]; // assignment not done here
}
}
return sharedSampleSingletonDelegate;
}
+ (id)allocWithZone:(NSZone *)zone {
@synchronized(self) {
if (sharedSampleSingletonDelegate == nil) {
sharedSampleSingletonDelegate = [super allocWithZone:zone];
// assignment and return on first allocation
return sharedSampleSingletonDelegate;
}
}
// on subsequent allocation attempts return nil
return nil;
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain {
return self;
}
- (unsigned)retainCount {
return UINT_MAX; // denotes an object that cannot be released
}
- (void)release {
//do nothing
}
- (id)autorelease {
return self;
}
Valerii의 코드는 싱글 톤을 구현하는 데 더 좋지만, 문제는 [Singleton 인스턴스]를 호출하는 코드가 실제로 소유권을 사용하지 않고 소유권이있는 것처럼 운영되고 나중에이를 공개하는 것입니다.
버그를 찾아서 읽으십시오 메모리 관리 규칙.
또한 Xcode에서 nszombieenabled를 활성화합니다 그리고 콘솔이 릴리스 된 후 객체를 메시지를 보내려고 할 때 콘솔이 표시됩니다.