我有一个使用Realm执行CRUD操作的模型类。
我正在尝试在串行队列上执行所有操作。
我已经声明了队列属性:
@property (nonatomic, strong) dispatch_queue_t realmQueue;
@property (strong,nonatomic) RLMRealm *secureRealm;
我用singleton初始化队列:
+ (id)sharedInstance {
static ActivityManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[self alloc] init];
});
return sharedManager;
}
-(id)init{
self.realmQueue = dispatch_queue_create("realm_activity", DISPATCH_QUEUE_SERIAL);
dispatch_async(self.realmQueue, ^{
_secureRealm = [RLMRealm defaultRealm];
});
return self;
}
-(NSArray *)getDataOnSettingFilter{
NSMutableArray *activityArr = [NSMutableArray array];
NSString *filterSQL = //;
RLMResults *activityResults = [[[self getActivitySource]activities] objectsWhere:filterSQL];
dispatch_async(self.realmQueue, ^{
[_secureRealm beginWriteTransaction];
for (RealmActivity *activity in activityResults){
//modify realm properties
[_secureRealm addOrUpdateObject:activity];
[activityArr addObject:activity];
}
[_secureRealm commitWriteTransaction];
});
return [activityArr copy];
}
当我使用以下方法调用上述方法时:
[[ActivityManager sharedInstance]getDataOnSettingFilter]
我发现一个崩溃,说从一个不正确的线程访问领域。
我在这里做错了什么。如何检查我是否总是在正确的线程上调用域?
答案 0 :(得分:1)
您不应该存储对单例Realm
实例的引用,因为您无法确保始终从同一个线程访问它。正如Realm
文档所述,
RLMRealm,RLMResults或RLMArray或托管实例的实例 RLMObject是线程限制的,这意味着它们只能被使用 在它们被创建的线程上,否则是一个例外 抛出
意味着您永远不应该尝试使用RLMRealm *realm = [RLMRealm defaultRealm];
来创建单个Realm
实例,而不是尝试从您的应用中访问它。
您可以尝试使用RLMThreadSafeReference
创建对可以在线程之间安全共享的Realm
个对象的引用,但正如文档的Passing instances across threads部分所述,这些引用只能使用一次,所以他们不能作为单身人士重复使用。
但是,没有必要这样做,因为每次调用RLMRealm *realm = [RLMRealm defaultRealm];
时,框架会自动创建对您正在使用的线程上当前使用的Realm
的引用,使您能够安全地进行交互只要你不离开那个帖子就可以了。
以线程安全的方式使用Realm
的最佳方法是,每次在线程之间移动并需要访问{时,使用Realm
创建对RLMRealm *realm = [RLMRealm defaultRealm];
的新引用{1}}。这样您就可以确保永远不会得到不正确的线程异常。