2013-03-13 4 views
0

* 확실히 중단해야합니다 ... 원인은 간단합니다 - 배열이 할당되지 않았습니다 ... 도움을 주셔서 감사합니다. 그 당혹스러운 실수 때문에, 나는 그것을 삭제하기 위해 내 게시물에 플래그를 지정했습니다. 사용자에게 유용하지는 않습니다.) *목표 C - 샘플 싱글 톤 구현

iOS에서 싱글 톤 클래스를 만들려고했지만 실수를하고있는 것 같습니다. 코드 (더 ARC가 필요 없음) :

#import "PeopleDatabase.h" 
#import "Person.h" 

#import <Foundation/Foundation.h> 

@interface PeopleDatabase : NSObject{objetive 
    NSMutableArray* _arrayOfPeople; 
} 

+(PeopleDatabase *) getInstance; 

@property (nonatomic, retain) NSMutableArray* arrayOfPeople; 


@end 

-

@implementation PeopleDatabase 
    @synthesize arrayOfPeople = _arrayOfPeople; 

    static PeopleDatabase* instance = nil; 

    -(id)init{ 
     if(self = [super init]) { 
      Person* person = [[[Person alloc] initWithName:@"John" sname:@"Derovsky" descr:@"Some kind of description" iconName:@"johnphoto.png" title:Prof] retain]; 

      [_arrayOfPeople addObject:person]; 
      NSLog(@"array count = %d", [_arrayOfPeople count]); // <== array count = 0 
      [person release]; 
     } 
     return self; 
    } 

    +(PeopleDatabase *)getInstance { 
     @synchronized(self) 
     { 
      if (instance == nil) 
       NSLog(@"initializing"); 
       instance = [[[self alloc] init] retain]; 
       NSLog(@"Address: %p", instance); 
     } 
     return(instance); 
    } 

    -(void)dealloc { 

     [instance release]; 
     [super dealloc]; 
    } 
@end 

여기처럼의 getInstance를 호출 :

PeopleDatabase *database = [PeopleDatabase getInstance]; 
NSLog(@"Adress 2: %p", database); 

주소 2 값의 getInstance에서와 같은 값.

+0

정확하게 "주소 2는 getInstance와 동일한 값을가집니다."는 의미입니까? ? – Petar

+0

그것은 동일한 주소이어야한다. 그것의 동일한 목표부터? getInstance에서 반환 한 객체는 데이터베이스가 할당 된 객체입니다. – Fonix

+0

[이 답변보기] (http://stackoverflow.com/a/145395/730701). 이 기능 +에서 – Adam

답변

20

싱글 톤처럼 만드는 표준 방법 ...

Singleton.h

@interface MySingleton : NSObject 

+ (MySingleton*)sharedInstance; 

@end 

을 싱글 톤.

#import "MySingleton.h" 

@implementation MySingleton 

#pragma mark - singleton method 

+ (MySingleton*)sharedInstance 
{ 
    static dispatch_once_t predicate = 0; 
    __strong static id sharedObject = nil; 
    //static id sharedObject = nil; //if you're not using ARC 
    dispatch_once(&predicate, ^{ 
     sharedObject = [[self alloc] init]; 
     //sharedObject = [[[self alloc] init] retain]; // if you're not using ARC 
    }); 
    return sharedObject; 
} 

@end 
+6

__strong은이 경우 중복되지만 그렇지 않으면 Apple에서 권장하는 방법입니다. 다른 방법은 구형입니다. – borrrden

2
@synchronized(self) 
    { 
     if (instance == nil) 
      NSLog(@"initializing"); 
      instance = [[[self alloc] init] retain]; 
      NSLog(@"Address: %p", instance); 
    } 

if 문에 중괄호가 누락 된 것 같습니다. 글로 쓰여진대로, instance == nil이 로그 메시지를 내보낼 때 당신이하는 유일한 일은 다릅니다. +(PeopleDatabase *)getInstance 내가 제대로 중괄호를 배치 할 필요가 있다고 생각이 기능에

+0

그게 사실이야 물론 ... 끔찍한 실수 ... 그건 고마워,하지만 원인이 아니야 ... –

+0

그건 맞지만 근본 원인을 해결하지 못합니다. 비록 나쁜 스타일이지만 nslogs가없는 oritinal 문장은 잘 작동했을 것입니다. –

+0

당신은 근본 원인을 해결하지 못하는 것이 맞지만, "nslogs가없는 oritinal 문은 유효합니다"라는 사실은 확실하지 않습니다. 루트 오류를 ​​지나치고 중괄호가 없으면'getInstance'를 호출 할 때마다 새로운 인스턴스를 생성하게됩니다. 이것은 인스턴스에 연결된'_arrayOfPeople'과 결합되어 싱글 톤 (singleton)이라는 개념을 제거합니다. – mah

0

+(PeopleDatabase *)getInstance { 
    @synchronized(self) 
    { 
     if (instance == nil) 
     { 
      NSLog(@"initializing"); 
      instance = [[[self alloc] init] retain]; 
      NSLog(@"Address: %p", instance); 
     } 
     return instance ; 
    } 
} 
0

이처럼 항상하는 경우와 다음에 중괄호를 사용하는 일부 disziplined 규칙 피할 수있는 오류입니다 그밖에.

+(PeopleDatabase *)getInstance { 
    @synchronized(self) 
    { 
     if (instance == nil) 
      NSLog(@"initializing"); 
      instance = [[[self alloc] init] retain]; 
      NSLog(@"Address: %p", instance); 
    } 
    return(instance); 
} 

인스턴스가 nil이면 다음 문장 만 실행됩니다. 그리고 그것은 할당이 아닌 nslog입니다. 인스턴스는 이전에 사용 된 것과 관계없이 어쨌든 할당됩니다. 이렇게하면 각 통화마다 새로운 싱글 톤이 제공됩니다. 누출의 원인이되는 BTW.

+(PeopleDatabase *)getInstance { 
    @synchronized(self) 
    { 
     if (instance == nil) { 
      NSLog(@"initializing"); 
      instance = [[[self alloc] init] retain]; 
      NSLog(@"Address: %p", instance); 
     } 
    } 
    return(instance); 
} 

그러나 디버깅하는 동안이 오류가 발생했습니다. 혼란 스러울 지 모르지만 원래의 문제는 해결되지 않습니다. alloc 및 init을 추가하고 _arrayOfPeople을 보유하십시오. 코드의 _arrayOfPeople에서

-(id)init{ 
    if(self = [super init]) { 
     Person* person = [[[Person alloc] initWithName:@"John" sname:@"Derovsky" descr:@"Some kind of description" iconName:@"johnphoto.png" title:Prof] retain]; 

     _arrayOfPeople = [[[NSMutableArray alloc] init] retain]; //dont forget the release 
     [_arrayOfPeople addObject:person]; 
     NSLog(@"array count = %d", [_arrayOfPeople count]); // <== array count = 1 !!! 
     [person release]; 
    } 
    return self; 
} 

은 전무하고 addObject는 중단이 발생하지 않지만 하나 아무것도하지 않습니다 전무로 전송됩니다. 그런 다음 count는 0/nil을 반환하는 nil로 보내집니다.

0

웹 읽기 및 개인 연습 후, 내 현재 싱글 구현은 다음과 같습니다

@interface MySingleton 

@property myProperty; 
+(instancetype) sharedInstance; 

@end 


@implementation MySingleton 

+ (instancetype) sharedInstance 
{ 
    static dispatch_once_t pred= 0; 
    __strong static MySingleton *singletonObj = nil; 
    dispatch_once (&pred, ^{ 
     singletonObj = [[super allocWithZone:NULL]init]; 
     singletonObj.myProperty = initialize ; 
    }); 

    return singletonObj; 
} 

+(id) allocWithZone:(NSZone *)zone 
{ 
    return [self sharedInstance]; 
} 

-(id)copyWithZone:(NSZone *)zone 
{ 
    return self; 
} 

이 스레드 안전 구현과 클래스의 "ALLOC 초기화"를 호출하여 새로운 개체를 만들 수있는 위험을 방지 할 수 있습니다. 속성 초기화는 유사한 이유로 "init"재정의가 아닌 블록 내부에서 이루어져야합니다.