1

*我绝对需要休息...原因很简单-未分配数组...感谢您的帮助。由于那个令人尴尬的错误,我标记了我的帖子以删除它。我觉得它对用户没有用 ;) *

我刚刚尝试在 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 中的值相同。

4

6 回答 6

25

创建单例的标准方法是......

单例.h

@interface MySingleton : NSObject

+ (MySingleton*)sharedInstance;

@end

单身人士.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
于 2013-03-13T11:07:42.403 回答
2

检查这个苹果文档如何创建单例实例:

https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html

于 2013-03-13T11:06:11.750 回答
2
    @synchronized(self)
    {
        if (instance == nil)
            NSLog(@"initializing");
            instance = [[[self alloc] init] retain];
            NSLog(@"Address: %p", instance);
    }

您似乎缺少该if陈述的括号。如前所述,您唯一不同instance == nil的是发出日志消息。

于 2013-03-13T11:09:57.033 回答
1

经过网络阅读和个人实践,我目前的单例实现是:

@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”覆盖内。

于 2014-10-06T20:47:06.917 回答
0

在这个函数中,+(PeopleDatabase *)getInstance我认为你需要正确放置花括号:像这样

+(PeopleDatabase *)getInstance {
    @synchronized(self)
    {
        if (instance == nil)
        {
            NSLog(@"initializing");
            instance = [[[self alloc] init] retain];
            NSLog(@"Address: %p", instance);
        }
        return instance ;
    }
}
于 2013-03-13T11:12:22.483 回答
0

这是一个可以通过一些不规则的约定来避免的错误,即始终使用大括号后跟 if 和 else。

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

如果 instance 为 nil,则下一个语句,并且仅执行该语句。那是 nslog 而不是分配。然后无论如何都会分配实例,无论它之前是否使用过。这将在每次调用时为您提供一个新的单例。顺便说一句,这会导致泄漏。

+(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 为 nil 并且 addObject 被发送到 nil ,这不会导致中止,但也不会执行任何操作。然后 count 被发送到 nil,它返回 0/nil。

于 2013-03-13T11:23:50.613 回答