2013-03-13 6 views
0

* Мне определенно нужен перерыв ... причина была проста - массив не был выделен ... Спасибо за помощь. Из-за этой смущающей ошибки я пометил свой пост, чтобы удалить его. Я не считаю это полезным для пользователей;) *Objective C - пример реализации Singleton

Я только что попытался создать одноэлементный класс в 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 

Singleton.m

#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 испускает сообщение журнала.

+0

Thats true, конечно ... Ужасная ошибка ... Спасибо за это, но это не причина ... –

+0

Это правильно, но не решает первопричины. Несмотря на то, что плохой стиль, но оглавление без nslogs, сработало бы хорошо. –

+0

Вы правы, что это не решает первопричину, но я определенно не вижу, чтобы «утверждение oritinal без использования nslogs работало нормально». Пройдите корневую ошибку, и с отсутствующими фигурными скобками вы создаете новый экземпляр при каждом вызове 'getInstance'. Это, в сочетании с '_arrayOfPeople', привязанным к экземпляру, устраняет понятие наличия одноэлементного. – mah

0

в этой функции +(PeopleDatabase *)getInstance я думаю, что вам нужно правильно установить фигурные скобки: как этого

+(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.

-(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; 
} 

В программном коде _arrayOfPeople равна нулю и AddObject направляется к нолю, который не вызывает прерывание потока, но ничего не делает ни. Затем count отправляется в nil, который возвращает 0/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» на классе. Инициализация атрибутов должна происходить внутри блока, а не внутри переопределения «init» по тем же причинам.