【问题标题】:Error while using Realm Object as a singleton. Is it a good idea?将领域对象用作单例时出错。这是个好主意吗?
【发布时间】:2014-12-31 12:37:53
【问题描述】:

我目前正在尝试在我的应用程序中使用Realm,我想使用RLMObject 的子类作为单例来存储应用程序状态。

我的第一个想法是这是不是一个非常糟糕的主意。

我的AppState 类有两个主要方法:

+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance = nil;

    RLMResults *result = [[self class] allObjects];

    if (result.count == 0) {
        dispatch_once(&once, ^{
            RLMRealm *realm = [RLMRealm defaultRealm];
            sharedInstance = [[self alloc] init];
            [realm beginWriteTransaction];
            [realm addObject:sharedInstance];
            [realm commitWriteTransaction];
        });
    }
    else {
        sharedInstance = [[[self class] allObjects] lastObject];
    }

    return sharedInstance;
}

- (void)update {
    RLMRealm *realm = self.realm;

    [realm beginWriteTransaction];
    [realm addOrUpdateObject:[[self class] sharedInstance]];
    [realm commitWriteTransaction];
}

我有一些属性用于存储有关应用程序状态的几个参数。

在我的一个视图控制器中,我收到以下错误:

'试图在写事务之外修改对象 - 调用 首先在 RLMRealm 实例上开始写事务。'

出现错误的代码sn-p如下:

AppState *defaultState = [AppState sharedInstance];
defaultState.appStateX = newAppStateValue; // This is where the app crashes.
[defaultState update];

我在 -(void)update 方法中将 self.realm 更改为 [RLMRealm defaultRealm]。没有骰子!

我觉得我对单身人士和/或RLMObjects 的理解存在根本性错误。 任何帮助表示赞赏。


更新

基于Sakamoto's 答案,我修改了-(void)update 方法以接受block 作为参数。 这种方法有很大的错误空间,但我可以继续我当前的实现,而无需进行任何重大更改。

- (void)update:(void(^)(void))block {
    RLMRealm *realm = self.realm;

    [realm beginWriteTransaction];
    block();
    [realm commitWriteTransaction];
}

我更新了块中的所有属性。

【问题讨论】:

    标签: ios iphone grand-central-dispatch realm


    【解决方案1】:

    根据Realm文档http://realm.io/docs/cocoa/0.89.1/

    Realm 对象可以像普通对象一样被实例化和独立使用。

    ...

    将对象添加到领域后,您可以继续使用它,并且您对其所做的所有更改都将被持久化(并且必须在写入事务中进行)。

    [AppState sharedInstance] 方法返回的对象已经添加到领域。因此,改变对象的属性需要如下的写事务。

    AppState *defaultState = [AppState sharedInstance];
    [defaultState.realm beginWriteTransaction];
    defaultState.appStateX = newAppStateValue;
    [defaultState.realm commitWriteTransaction];
    

    【讨论】:

    • 这个答案是正确的,但更好的方法是根本不使用单例。它不仅鼓励了许多危险的设计模式,而且会绕过 Realm 的一些内部设计决策。
    • 为什么不发布没有 Singleton 的更好方法? AppState 的基本思想与持久化[NSUserDefaults standardUserDefaults] 单例模式完全相同。
    • 哇!我在文档中读过那一行,但它从未在我的脑海中注册过。我对这些对象的工作方式有自己的假设,并试图以这种方式使用它们。正如你所说的那样,我正在尝试使用 AppState 作为 NSUserDefaults 的替代品。我可能不得不重新考虑这个想法。谢谢!
    猜你喜欢
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    相关资源
    最近更新 更多