境界穿越混乱

时间:2015-12-09 18:28:39

标签: ios xcode multithreading swift realm

所以我正在设置一个后台队列,它在自己的线程上执行所有域写操作。我遇到了一些我无法弄清楚的奇怪问题。

问题#1

我不确定这是否相关(请参阅帖子:Xcode debug issues with realm)但我的lldbg输出明显与某个字段是否存在不匹配: messages元素

我的数据类型

OTTOSession

class OTTOSession : Object {
  dynamic var messages : MessageList?
  dynamic var recordingStart  : Double = NSDate().timeIntervalSince1970

func addLocationMessage(msg : dmParsedMessage) -> LocationMessage {
    let dmsg : dmLocationMessage = msg as! dmLocationMessage
    let locMsg = LocationMessage(locMsg: dmsg)
    self.messages!.locationMessages.append(locMsg)
    return locMsg;
  }
}

MessageList中

public class MessageList : Object     {

dynamic var date : NSDate = NSDate();
dynamic var test : String = "HI";
let locationMessages = List<LocationMessage>()
let ahrsMessages = List<AHRSMessage>()
//    let statusMessages = List<StatusMessageRLM>()
let logMessages = List<LogMessage>()
}

Realm Interactions

在我的代码中,我在OTTOSession

的代码块中创建了新的realmQueue
internal var realmQueue = dispatch_queue_create("DataRecorder.realmQueue", 
                                                   DISPATCH_QUEUE_SERIAL)

所有领域调用都在此realmQueue线程

上完成
  dispatch_async(realmQueue) {
        self.session = OTTOSession()
    }

我也尝试了不同的变体,例如:

  dispatch_async(realmQueue) {
        self.session = OTTOSession()

        // Directly making a message list
        self.session!.messages = MessageList()

        //Making a separate message list var
        self.messages = MessageList()
        self.session!.messages = self.messages
    }

我使用MessageList的原因是,我无法从调试器告知.messages变量是否已设置

记录

一旦我向我的进程发出信号,我想开始录制,然后实际将写入调用进入Realm(我不能100%确定我正确地做了)

dispatch_async(realmQueue){

        // Update some of the data
        self.session!.recordingStart = NSDate().timeIntervalSince1970

        // Then start writing the objects
        try! Realm().write {

            // I've tried different variants of:
            let session = self.session!
            try! Realm().add(self.session!)                          
            // Or
            try! Realm().add(self.session!)

            // or            
            let session = self.session!                
            session.messages = MessageList()
            session.messages!.ahrsMessages
            try! Realm().add(self.session!)
            try! self.session!.messages = Realm().create(MessageList)
            try! Realm().add(self.session!.messages!)

            print ("Done")
        }
    }

基本上我已尝试过尝试将对象变为领域的各种组合。

问题:添加具有one-to-one关系的对象时,我必须将两个对象添加到Realm,或者只添加parent对象,导致相关对象也被添加到领域

添加数据

当事情开始出错时,我开始向我的对象添加数据。

在我的OTTOSession对象中,我有以下功能:

func addLocationMessage(msg : dmParsedMessage) -> LocationMessage {
    let dmsg : dmLocationMessage = msg as! dmLocationMessage
    let locMsg = LocationMessage(locMsg: dmsg)

    // THIS LINE IS CAUSING A 'REALM ACCESSED FROM INCORRECT THREAD ERROR
    self.messages!.locationMessages.append(locMsg)

    return locMsg;
}

我在这一行收到了访问错误:

  

self.messages!.locationMessages.append(locMsg)

现在函数调用本身包含在以下块中:

dispatch_async(realmQueue) {
    try! Realm().write {
        self.session?.addLocationMessage(msg)
   }
}

据我所知,通过查看调试器 - 并查看代码 - 一切都应该在正确的线程内运行。

我的队列是SERIAL所以事情应该一个接一个地发生。我唯一能做的就是当我在这一点上突破时调试器确实显示messagesnil,但我不相信,因为:

enter image description here

问题

所以我的问题是两次

1)我的代码是否正确地将对象添加到RealmDB中。即我是否需要为Realm().addOTTOSession分别进行两次MessageList来电,或者我可以通过一次通话取消

2)是否有任何东西可以解释为什么我在这里遇到线程违规 - 我应该在单个线程上编写所有内容吗?

1 个答案:

答案 0 :(得分:2)

1)不,您不需要对Realm.add()进行两次单独的调用。将对象添加到Realm时,所有相关对象也会保持不变。

2)您的线程违规很可能源于这样一个事实,即调度队列无法保证执行它们的线程(在主队列旁边)。这意味着您的Realm队列在不同的线程上执行。您需要确保从此线程上打开的Realm中检索会话对象。您可能希望为此目的使用主键并在队列/线程之间共享它们。