2

按照此链接:如何使用 NSKeyedArchiever 归档两个对象?我能够归档一个数组和一个单例对象。我可以在 didFinishLaunchingWithOptions 中归档和正确取消归档它。

但是,我的单例对象不会持续超过应用程序委托。在下一个视图控制器中,即使在 didFinishLaunchingWithOptions 中,我执行了 NSLog 并进行了验证,单例变量也会返回到其默认值。这是一个例子,

在应用中didFinishLaunchingWithOptions

Singleton *singleton = [Singleton sharedSingleton];
NSData *data = [NSData dataWithContentsOfFile:path];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
singleton = [unarchiver decodeObjectForKey:@"singleton"];
[unarchiver finishDecoding];

NSLog(@"singleton sorting after decode: %@", [singleton sort]);// 输出:字母

然后,我分配/初始化一个 viewController 并将其设置为我的导航控制器的根视图控制器:

navController = [[UINavigationController alloc] initWithRootViewController:viewController];

在 viewController -> viewWillAppear 中,

我调用一个排序函数:[self sort...];

在排序函数中,我调用了单例类: Singleton*singleton = [Singleton sharedSingleton]; 但是现在,NSLog(@"singleton sort: %@", [singleton sort]);// 输出:amount NOT alphabet

我可以发布我的单例代码,但我知道它有效。事实上,在我的设置视图控制器中,如果我更改 [singleton sort] 变量,它将在所有视图控制器中持续存在。

这让我很困惑,为什么我的单例对象不会从应用程序委托持续到我的视图控制器。任何提示/提示表示赞赏。

谢谢!!!

编辑:单例类实现

在 Singleton.m 中:

static Singleton *shared = NULL;

+ (id)sharedSingleton
{
    @synchronized(self)
    {
        if ( !shared || shared == NULL )
        {
            // allocate the shared instance, because it hasn't been done yet
            NSLog(@"Allocating Singleton...");
            shared = [[Singleton alloc] init];
        }
        return shared;
    }
}


- (id)init
{
    if ( self = [super init] )
    {
        sort = [[NSString alloc] initWithString:@"amount"];
        showTutorial = YES;
    }
    return self;    
}

-(id)initWithCoder:(NSCoder *)aDecoder
{
    [super init];
    [self setSort:[aDecoder decodeObjectForKey:@"sort"]];
    [self setShowTutorial:[aDecoder decodeBoolForKey:@"showTutorial"]];

    return self;
}

-(void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:sort forKey:@"sort"];
    [aCoder encodeBool:showTutorial forKey:@"showTutorial"];
}
4

5 回答 5

2

我认为你弄错了单例模式。

您在代码中创建它

Singleton *singleton = [Singleton sharedSingleton];

这是正确的,但是做

singleton = [unarchiver decodeObjectForKey:@"singleton"];

对于单身人士来说根本没有意义。一般来说,您不想从 nib 实例化您的单例。

于 2011-06-29T16:23:35.917 回答
2

在您的代码中,您只是在更新当前上下文中的单例指针的值,而不是 sharedSingleton 实例

尝试在 Singleton 类中创建一个方法,该方法使用 unarchiver 对象更新单例类,例如:

[[Singleton sharedSingleton] loadArchive:unarchiver];

或(我认为这更好)将您的代码移动到 Singleton init 函数中。

于 2011-06-29T15:42:26.733 回答
2

您还为局部变量分配了一个自动释放对象。下次通过事件循环,该对象将超出范围(即释放)。

singleton = [unarchiver decodeObjectForKey:@"singleton"];
于 2011-06-29T16:18:36.850 回答
1

您的singleton指针只是一个局部变量,最初指向 Singleton 的共享实例。然后,您来更改 的值singleton,使其指向您从解档器解码的对象。使这个本地指针指向新的 Singleton 不会改变 Singleton 的共享实例,也不会改变shared全局的值。

此外,我认为您可能误解了单例模式。当一个类的实例不超过一个时,应该使用单例模式。单例经常被使用,因为它们很容易在全球范围内访问,但许多聪明的人因此认为使用单例是对模式的滥用。您可以同意或不同意这一点,但这里的事实是您正在创建 Singleton 类的两个实例,根据定义,这意味着您的 Singleton 类不是单例设计模式的真正实现。

于 2011-06-29T17:19:00.153 回答
0

下面给出的大多数评论都指向正确的方向,在我的原始代码中,我创建了 Singleton 类的两个实例。我意识到我的愚蠢,所以这里是有效的代码:

Singleton *singleton = [unarchiver decodeObjectForKey:@"singleton"];

然后,使用 mySingleton 的唯一实例:

Singleton *mySingleton = [Singleton sharedSingleton];
[mySingleton setSort:[singleton sort]];

因此,通过这种方式,unarchiver 会拉取一个单例对象的实例,该对象是自动释放的,但值设置为真正的 Singleton 类。

注意:一些评论提到我可能没有正确使用 Singleton 类,我可能没有。我不是这方面的专家。我只想保存一些东西并在应用程序终止时将其取回。如果它对你有帮助,那就太好了。如果没有,请发表评论以帮助我们所有人更好地学习。如果我变得更好并了解更多,也许我会更新这篇文章。

感谢所有的评论。他们都很好。我对他们都投了赞成票。

于 2011-06-29T18:36:34.890 回答