菜鸟教程小白 发表于 2022-12-12 12:15:34

ios - swift realm::IncorrectThreadException:从不正确的线程访问的 Realm


                                            <p><p>我创建了一个名为"file"的模型,使用 Realm Browser 看起来还不错:
<a href="/image/BqTYa.png" rel="noreferrer noopener nofollow"><img src="/image/BqTYa.png" alt="Realm Browser"/></a> </p>

<p>但是当我使用模型时,它会返回错误:
<code>libc++abi.dylib: 以未捕获的 Realm 类型异常终止::IncorrectThreadException:Realm 从不正确的线程访问。</code></p>

<p>在我的代码中,我在每个需要添加/更新的地方创建 Realm 对象:</p>

<pre><code>private var allFiles : Results&lt;File&gt;!

private var downloadingFiles : Results&lt;File&gt;! {
    return self.allFiles.filter(&#34;completed = false&#34;)
}

private var downloadedFiles : Results&lt;File&gt;! {
    return self.allFiles.filter(&#34;completed = true&#34;)
}

private var downloading = false

private var request: Alamofire.Request?

func download() {

    let fileRealm = try! Realm()
    allFiles = fileRealm.objects(File).sorted(&#34;updatedAt&#34;)

    downloadFile()
}

private func downloadFile() {

    if !self.downloading, let file = self.downloadingFiles.first where !file.completed {

      self.reqForDownload(file)
    }
}

private func reqForDownload(file: File) -&gt; Void {

    downloading = true

    request = Alamofire
      .download(.GET, file.url, destination: { (url, response) -&gt; NSURL in

            return NSURL(fileURLWithPath: file.filePath)

      })
      .progress { (bytesRead, totalBytesRead, totalBytesExpectedToRead) in
            dispatch_async(dispatch_get_main_queue(), {
                let variable = Float(totalBytesRead)/Float(totalBytesExpectedToRead)
                debugPrint(variable)
            })
      }
      .response { (request, response, data, error) in
            if let error = error {

                dispatch_async(dispatch_get_main_queue(), {
                  let fileRealm = try! Realm()
                  try! fileRealm.write({
                        file.completed = false
                  })
                  self.allFiles = fileRealm.objects(File).sorted(&#34;updatedAt&#34;)
                })

                if error.code == NSURLErrorCancelled {
                  debugPrint(&#34;Canceled download&#34;)
                }

            } else {
                debugPrint(&#34;Downloaded file successfully&#34;)

                dispatch_async(dispatch_get_main_queue(), {
                  let fileRealm = try! Realm()
                  try! fileRealm.write({
                        file.completed = true
                  })
                  self.allFiles = fileRealm.objects(File).sorted(&#34;updatedAt&#34;)
                })
            }

            self.downloading = false
    }
}
</code></pre>

<p>我是 Realm 的新手,但我知道 Realm 不是线程安全的,所以我尝试使用主线程中的对象作为我的代码,但错误仍然出现。请高人帮帮我,谢谢。</p>

<p><strong>我已将代码更新为@TimOliver 的<a href="https://github.com/realm/realm-cocoa/issues/4249#issuecomment-256185393" rel="noreferrer noopener nofollow">suggest</a> ,但它仍然响应相同的错误。</strong>新代码如下:</p>

<pre><code>private var allFiles : Results&lt;File&gt;!

private var downloadingFiles : Results&lt;File&gt;! {
    return self.allFiles.filter(&#34;completed = false&#34;)
}

private var downloadedFiles : Results&lt;File&gt;! {
    return self.allFiles.filter(&#34;completed = true&#34;)
}

private var downloading = false

private var request: Alamofire.Request?

func download() {

    let fileRealm = try! Realm()
    allFiles = fileRealm.objects(File).sorted(&#34;updatedAt&#34;)

    downloadFile()
}

private func downloadFile() {

    if !self.downloading, let file = self.downloadingFiles.first where !file.completed {

      self.reqForDownload(file)
    }
}

private func reqForDownload(file: File) -&gt; Void {

    downloading = true

    request = Alamofire
      .download(.GET, file.url, destination: { (url, response) -&gt; NSURL in

            return NSURL(fileURLWithPath: file.filePath)

      })
      .progress { (bytesRead, totalBytesRead, totalBytesExpectedToRead) in
            dispatch_async(dispatch_get_main_queue(), {
                let variable = Float(totalBytesRead)/Float(totalBytesExpectedToRead)
                debugPrint(variable)
            })
      }
      .response { (request, response, data, error) in
            if let error = error {

                let fileRealm = try! Realm()
                  try! fileRealm.write({
                        file.completed = false
                  })
                  self.allFiles = fileRealm.objects(File.self).sorted(&#34;updatedAt&#34;)

                if error.code == NSURLErrorCancelled {
                  debugPrint(&#34;Canceled download&#34;)
                }

            } else {
                debugPrint(&#34;Downloaded file successfully&#34;)

                let fileRealm = try! Realm()
                  try! fileRealm.write({
                        file.completed = true
                  })
                  self.allFiles = fileRealm.objects(File.self).sorted(&#34;updatedAt&#34;)
            }

            self.downloading = false
    }
}
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>就像我在评论中问的那样,如果你设置了异常断点,你可以准确地看到哪一行代码触发了 Realm 异常,这样你就可以跟踪 Realm 事务发生在哪个线程中,以及哪些对象正在交互用它。</p>

<p>如果我没记错的话,我相信在该方法的 <code>.response</code> 部分中调用的闭包默认不会在主线程上调用,但是您正在尝试修改 <code>file</code> 明确在主线程上查询的对象。</p>

<p>没有强制其中的每个闭包在主线程上调用,更合适的是 <a href="https://realm.io/docs/swift/latest/#primary-keys" rel="noreferrer noopener nofollow">primary key</a> <code>file</code> 对象中的属性,直接持有对主键值的引用,然后在需要更新时直接查询 <code>file</code> 对象的线程本地版本(即使用 <a href="https://realm.io/docs/swift/2.0.3/api/Classes/Realm.html#/s:FC10RealmSwift5Realm6objectu0_RxCS_6ObjectrFT6ofTypeMx13forPrimaryKeyq__GSqx_" rel="noreferrer noopener nofollow"><code>Realm.object(ofType: primaryKey:)</code></a> 方法。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - swift realm::IncorrectThreadException:从不正确的线程访问的 Realm ,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/40201917/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/40201917/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - swift realm::IncorrectThreadException:从不正确的线程访问的 Realm