繁体   English   中英

Xcode DispatchQueue.main.async 在大循环内部还是外部?

[英]Xcode DispatchQueue.main.async inside or outside large loop?

我正在尝试编辑/插入 CoreData 对象,我正在做的是:

DispatchQueue.main.async {
  for track in allTracks
  {
    if let i = allObjects.index(where: { $0.sid == ddTools().md5("\(track.song_name)\(track.artist_name)") } )
    {
      self.log("[NEW][\(i)] Already in DB : \(track.song_name)")
    }else
    {
      self.insert_track(track)
    }
  }
}

但是如果 Array 有超过 500 个以上的对象,它仍然会阻塞 UI,如果我这样做是否安全?

  for track in allTracks
  {
     DispatchQueue.main.async {
        if let i = allObjects.index(where: { $0.sid == ddTools().md5("\(track.song_name)\(track.artist_name)") } )
        {
          self.log("[NEW][\(i)] Already in DB : \(track.song_name)")
        }else
        {
          self.insert_track(track)
        }
    }
  }

我可以在 CoreData 对象的循环中使用 DispatchQueue.main.async 吗! 取消阻塞 UI

经过一些建议,我已将功能更新为此

func insert_or_update_songs(tracks:[DTO_SONG],onComplete:(()->())!)
{

    let allTasksGroup     = DispatchGroup()
    var totalFinished:Int = 0


    for track in tracks
    {
        DispatchQueue.main.async
        {
          allTasksGroup.enter()

            //Fetch if Exists
          let context             = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
          let songHash            = ddTools().md5("\(track.song_name)\(track.artist_name)")
          let request             = NSFetchRequest<NSFetchRequestResult>(entityName: "Song_Entity")
              request.predicate   = NSCompoundPredicate(andPredicateWithSubpredicates: [NSPredicate(format:"sid = %@", songHash),
                                                                                        NSPredicate(format:"sid != %@", "")])

          do{

                  if  try context.count(for:request) > 0
                  {
                     //Update the Track
                     if let _tracks:[Song_Entity] = try context.fetch(request) as? [Song_Entity]
                     {
                        self.update_track(track, _tracks[0])
                     }

                  }else
                  //Insert as new track
                  {
                    self.insert_track(track,context :context)
                  }

                if context.hasChanges
                {
                   do {
                          try context.save()
                          self.log(" New Changes has been Saved.")
                       } catch let error as NSError {   self.log(" Could not save. \(error), \(error.userInfo)") }
                }

                totalFinished += 1
                print(" \(totalFinished)/\(tracks.count)")
                allTasksGroup.leave()

             }catch let error as NSError {  self.log("[HASH] Error while checking Track if in DB: \(error), \(error.userInfo)") }

        }
    }

    //When all done
    allTasksGroup.notify(queue: .main) {
        self.log("[INSERT OR UPDATE BATCH] Total Finished : \(totalFinished)/\(tracks.count) ")

        if totalFinished == tracks.count
        {
           if onComplete != nil
           {
              onComplete()
           }
        }
    }

对于您的 UI 的 CoreData 胎面安全性和响应性,我会在insert点进行线程切换:

for track in allTracks
{
    if let i = allObjects.index(where: { $0.sid == ddTools().md5("\(track.song_name)\(track.artist_name)") } ) {
      self.log("[NEW][\(i)] Already in DB : \(track.song_name)")
    } else {
        DispatchQueue.main.async {
            self.insert_track(track)
        }
    }
}

两段代码都是错误的。 allTracks是附加到特定上下文的核心数据对象 - 这不是线程安全的。 您不能从主线程访问这些对象——无论是读还是写。 您可以保存信息 - 然后将其传递给主线程。

如果您在主线程上执行 fetch 操作,则首先不应使用后台线程。 最好只在主线程上进行提取。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM