2010-08-22 2 views
0

plist에 일부 데이터를로드하고 저장하는 PoolManager이라는 싱글 톤 개체가 있습니다. 내 프로그램에서 내 수영장에 대해 알아야 할 것이있을 때 [PoolManager sharedPoolManager]에 속성이 있는지 묻습니다. 나는이 속성을 설정하는 책임이있는 단일보기와 다른 모든 사람들이 방금 읽은보기를 가지고 있습니다. 모든 것이 잘 작동했는데, 아무 이유없이 내가 알 수 있듯이, 충돌이 시작되었습니다. NSZombieEnabled = YES을 설정하면 두 개의 NSString 속성 중 하나에 액세스 할 때 해당 속성이 해제 된 것처럼 보입니다. 디버거 메시지는 다음과 같습니다. *** -[CFString respondsToSelector:]: message sent to deallocated instance 0x5a336d0어떻게 든 내 싱글 톤 속성이 공개됩니다.

모든 것이 작동하는 이전 스냅 샷으로 돌아가려고했는데 여전히 작동합니다. 저는 어제부터 TimeMachine을 사용하여 프로젝트로 돌아갔습니다. 나는 당황 스럽다.

여기에 싱글 톤 객체 코드가 있습니다. 분명히 좀비 인 surfaceshape 문자열입니다. 죄송합니다 모든 NSLogs


// MyPoolSingleton.h 

#import <Foundation/Foundation.h> 

#define kFileName @"data.plist" 

@interface PoolManager : NSObject { 
    float volume; 
    float length; 
    float width; 
    float depth;  
    NSString *surface; 
    NSString *shape; 
    BOOL isMetric; 
    int fcTarget; 
    int cyaTarget; 
    int taTarget; 
    int chTarget; 
    int saltTarget; 
} 

@property float volume; 
@property float length; 
@property float width; 
@property float depth; 
@property (nonatomic, retain) NSString *surface; 
@property (nonatomic, retain) NSString *shape; 
@property BOOL isMetric; 
@property int fcTarget; 
@property int cyaTarget; 
@property int taTarget; 
@property int chTarget; 
@property int saltTarget; 

+ (PoolManager*)sharedPoolManager; 
- (void)retrieveState; 
- (void)saveState; 
- (NSString*)dataFilePath; 

@end 
개인적으로
// MyPoolSingleton.m 

#import "PoolManager.h" 

@implementation PoolManager 

@synthesize volume; 
@synthesize length; 
@synthesize width; 
@synthesize depth; 
@synthesize surface; 
@synthesize shape; 
@synthesize isMetric; 
@synthesize fcTarget; 
@synthesize cyaTarget; 
@synthesize taTarget; 
@synthesize chTarget; 
@synthesize saltTarget; 

static PoolManager* _sharedPoolManager = nil; 

+ (PoolManager*)sharedPoolManager { 
    @synchronized([PoolManager class]) 
    { 
     if (!_sharedPoolManager) 
      [[self alloc] init]; 
     return _sharedPoolManager; 
    } 
    return nil; 
} 

+ (id)alloc { 
    @synchronized([PoolManager class]) 
    { 
     NSAssert(_sharedPoolManager == nil, @"Attempted to allocate a second instance of a singleton."); 
     _sharedPoolManager = [super alloc]; 
     return _sharedPoolManager; 
    } 
    return nil; 
} 

- (id)init { 
    self = [super init]; 
    return self; 
} 

- (void)retrieveState { 
    NSLog(@"--retrieveState"); 
    NSString *filePath = [self dataFilePath]; 
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { 
     NSLog(@" fileExistsAtPath: reading array from plist"); 
     NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath]; 
     volume = [[array objectAtIndex:0] floatValue]; 
      NSLog(@"  reading array: volume = %1.1f", volume); 
     length = [[array objectAtIndex:1] floatValue]; 
      NSLog(@"  reading array: length = %1.1f", length); 
     width = [[array objectAtIndex:2] floatValue]; 
      NSLog(@"  reading array: width = %1.1f", width); 
     depth = [[array objectAtIndex:3] floatValue]; 
      NSLog(@"  reading array: depth = %1.1f", depth); 
     self.surface = [array objectAtIndex:4]; 
      NSLog(@"  reading array: surface = %@", surface); 
     self.shape = [array objectAtIndex:5]; 
      NSLog(@"  reading array: shape = %@", shape); 
     isMetric = [[array objectAtIndex:6] boolValue]; 
      NSLog(@"  reading array: isMetric = %d", isMetric); 
     fcTarget = [[array objectAtIndex:7] intValue]; 
      NSLog(@"  reading array: fcTarget = %d", fcTarget); 
     cyaTarget = [[array objectAtIndex:8] intValue]; 
      NSLog(@"  reading array: cyaTarget = %d", cyaTarget); 
     taTarget = [[array objectAtIndex:9] intValue]; 
      NSLog(@"  reading array: taTarget = %d", taTarget); 
     chTarget = [[array objectAtIndex:10] intValue]; 
      NSLog(@"  reading array: chTarget = %d", chTarget); 
     saltTarget = [[array objectAtIndex:11] intValue]; 
      NSLog(@"  reading array: saltTarget = %d", saltTarget); 
     [array release]; 
    } 
    else { 
     NSLog(@" !fileExistsAtPath: intitializing values to nil/zero"); 
     volume = 0.0; 
     length = 0.0; 
     width = 0.0; 
     depth = 0.0; 
     surface = @""; 
     shape = @""; 
     isMetric = NO; 
     fcTarget = 0.0; 
     cyaTarget = 0.0; 
     taTarget = 0.0; 
     chTarget = 0.0; 
     saltTarget = 0.0; 
    } 
} 

- (void)saveState { 
    NSLog(@"--saveState"); 
    NSMutableArray *array = [[NSMutableArray alloc] init]; 
     NSLog(@"  building array: volume = %1.1f", volume); 
    [array addObject:[NSNumber numberWithFloat:volume]]; 
     NSLog(@"  building array: length = %1.1f", length); 
    [array addObject:[NSNumber numberWithFloat:length]]; 
     NSLog(@"  building array: width = %1.1f", width); 
    [array addObject:[NSNumber numberWithFloat:width]]; 
     NSLog(@"  building array: depth = %1.1f", depth); 
    [array addObject:[NSNumber numberWithFloat:depth]]; 
     NSLog(@"  building array: surface = %@", surface); 
    [array addObject:surface]; 
     NSLog(@"  building array: shape = %@", shape); 
    [array addObject:shape]; 
     NSLog(@"  building array: isMetric = %d", isMetric); 
    [array addObject:[NSNumber numberWithBool:isMetric]]; 
     NSLog(@"  building array: fcTarget = %d", fcTarget); 
    [array addObject:[NSNumber numberWithInt:fcTarget]]; 
     NSLog(@"  building array: cyaTarget = %d", cyaTarget); 
    [array addObject:[NSNumber numberWithInt:cyaTarget]]; 
     NSLog(@"  building array: taTarget = %d", taTarget); 
    [array addObject:[NSNumber numberWithInt:taTarget]]; 
      NSLog(@"  building array: chTarget = %d", chTarget); 
    [array addObject:[NSNumber numberWithInt:chTarget]]; 
     NSLog(@"  building array: saltTarget = %d", saltTarget); 
    [array addObject:[NSNumber numberWithInt:saltTarget]]; 

    [array writeToFile:[self dataFilePath] atomically:YES]; 
    [array release]; 
}  

- (NSString*)dataFilePath { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    return [documentsDirectory stringByAppendingPathComponent:kFileName]; 
} 

- (void)dealloc { 
    [shape release], shape = nil; 
    [surface release], surface = nil; 
    [super dealloc]; 
} 

@end 
+1

코드를 짧게 만들려면 @synthesize var1, var2, var2; 각각에 대해 별도의 줄을 사용하는 대신 –

+0

고마워, 나는 돌아가서 그런 것들을 정리하기 시작했다. – Steve

답변

5

objectAtIndex:은 자동 회수 된 개체를 제공합니다. 그것을 유지하거나 속성 접근자인 self.surface = ...self.shape = ...을 사용할 때 설정해야합니다.

+0

'self.surface' 및'self.shape'로 전환하는 것이 트릭을 만들었습니다. 감사! 나는 어젯밤 이후로 어떻게 잘 돌아가는지 이해하지 못하고 부서지기 시작했다. 오 잘. BTW, 거기에 autoreleased 개체 또는 autoreleased 개체를 참조하는 메서드 목록이 있습니까? – Steve

2

내가 선호하는 싱글에 대한 다음과 같은 패턴 :

+ (id) sharedPoolManager 
{ 
    static id sharedPoolManager = nil; 
    @synchronized (self) { 
     if (sharedPoolManager == nil) { 
      sharedPoolManager = [self new]; 
     } 
    } 
    return sharedPoolManager; 
} 

- (id) init 
{ 
    if ((self = [super init]) != nil) { 
     // Initialize ... nothing special here ... 
    } 
    return self; 
} 

(클래스 메서드에서 self[SomeClass class]에 동등합니다)

위가 더 간결하며 필요한 경우 여러 인스턴스를 만들 수 있으므로 initalloc 외부에 싱글 톤 코드를 유지하는 것을 선호합니다. 예를 들어 단위 테스트에서.

개인적으로 나는 프로그래머가 다중 인스턴스를 만들지 않도록 보호해야한다고 생각하지 않습니다. 계약은 명확합니다. sharedPoolManager은 싱글 톤 인스턴스를 반환합니다. 그게 당신이 원하는/필요하다면 사용하십시오. 그렇지 않으면 일반적인 방법으로 인스턴스를 만듭니다.

+0

나는 이것이 내가보기에 더 좋아 보이는 방식을 좋아하지만'- (id) alloc'은 어떨까요? 인스턴스를 만들고 전달하는 것에 대해 생각했지만 더 많은 작업이 필요했습니다. 뭔가를 인스턴스화하고 뭔가를 전달하기 위해 속성을 할당하는 것은 쉽지만 다른 방법으로 이동하는 방법을 알아 낸 유일한 방법은 위임을 사용하는 것입니다. – Steve

+0

당신은 실제로 싱글 톤을 위해'alloc'을 필요로하지 않습니다. 기본 구현은 정상적으로 수행됩니다. 네가하려는 일을 오해하지 않는 한. –

+0

오. 예,'[Foo new]는''[[Foo alloc] init]'의 지름길입니다. 아무도 나를 제외하고는 더 이상 사용하지 않는 것 같습니다. 그러나 그것은 완벽하게 합법적입니다. NSObject의 일부. docs :-)를 참조하십시오. –