UIApplication.delegate只能在主线程中使用。

12

我在我的应用程序委托中有以下代码,作为在其他视图控制器中使用CoreData的快捷方式:

let ad = UIApplication.shared.delegate as! AppDelegate
let context = ad.persistentContainer.viewContext

然而,我现在收到了错误信息:

"UI API called from background thread" 和 "UIApplication.delegate must be used from main thread only".

我在后台处理 CoreData,但这是我第一次看到这个错误信息。有人知道这里发生了什么吗?

更新:我试图将其移到 appDelegate 类本身中,并使用以下代码 -

let dispatch = DispatchQueue.main.async {
    let ad = UIApplication.shared.delegate as! AppDelegate
    let context = ad.persistentContainer.viewContext
}

现在,我无法在AppDelegate外部访问广告和上下文变量。 我是否遗漏了什么?


请查看此链接:https://dev59.com/NFcO5IYBdhLWcg3w5lfX - Anbu.Karthik
我正在使用Swift,而不是Objective-C。 - LFHS
我想我的问题是,正确的地方在哪里声明广告和上下文?我应该在我的视图控制器中的主调度中声明这些吗? - LFHS
@LFHS 尝试使用更新的答案。 - Krunal
1个回答

8

关于这个问题 (-[UIApplication delegate] must be called from main thread only),以下是针对您的疑问的Swift翻译:

    DispatchQueue.main.async(execute: {

      // Handle further UI related operations here....
      //let ad = UIApplication.shared.delegate as! AppDelegate
      //let context = ad.persistentContainer.viewContext   

    })

带编辑:(广告和上下文声明的正确位置在哪里?我应该在主派遣中的视图控制器中声明它们吗?)
变量(ad和context)的声明位置定义了其作用域。您需要决定这些变量的作用域。您可以将它们声明为项目或应用程序级别(全局),类级别或特定的函数级别。 如果您想在其他视图控制器中使用这些变量,则应使用公共/开放/内部访问控件来在全局或类级别声明。

   var ad: AppDelegate!    //or var ad: AppDelegate?
   var context: NSManagedObjectContext!    //or var context: NSManagedObjectContext?


   DispatchQueue.main.async(execute: {

      // Handle further UI related operations here....
      ad = UIApplication.shared.delegate as! AppDelegate
      context = ad.persistentContainer.viewContext   

      //or 

      //self.ad = UIApplication.shared.delegate as! AppDelegate
      //self.context = ad.persistentContainer.viewContext   

    })

太棒了,这解决了问题,谢谢。现在处理广告和上下文时,我需要使用if let吗?因为它们现在是可选的。或者我可以假设它们不会为空? - LFHS
如果您使用 ? 可选声明,例如 var ad: AppDelegate?,那么您应该使用 if-let 从变量 ad 中获取值。 - Krunal
没错,不过我把它们设置成了隐式解包。访问它们的时候有可能会是nil,导致我的应用崩溃,这种情况会发生吗?不隐式解包它们会更好吗? - LFHS
1
是的,它取决于您在此代码块周围设置的条件。您是否为此代码块设置了任何条件?我认为必须有一个条件,因为您可能正在使用数据库操作,并且作为数据库操作的成功结果,这些变量被初始化。因此,如果数据库操作失败,这些变量可能仍然为空。检查您的代码和条件。 - Krunal
谢谢,我明白了。本质上,如果应用程序没有在主调度中运行,我就不能使用coreData? - LFHS
我们的操作决定应用程序是在后台还是前台运行。如果您的操作正在后台运行,并且您尝试使用后台操作的结果来更新UI,则会出现此错误。 - Krunal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接