1

所以我正在做一个后台获取,并且在我想更新 UI 之后。后台获取本身(数据库)有效,但是当我想更新 UI 时,我遇到了崩溃unexpectedly found nil while unwrapping an Optional value 根据我的 xCodeself.newestPublicationsCollectionView.reloadData()是在 updateCollections() 函数中发生崩溃的地方。

 func updateCollections() {
        // get latest data from Database
        latestPublications = getNewestPublications()

        self.newestPublicationsCollectionView.reloadData()

        self.newestPublicationsCollectionView.layoutIfNeeded()

       // fix wrong content height
       self.newestPublicationsCollectionViewHeight.constant = self.newestPublicationsCollectionView.collectionViewLayout.collectionViewContentSize().height  
    }

AppDelegate 中的其他代码:

func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {

    let fetchViewController = PublicationOverviewController()
                fetchViewController.fetch {
                    dispatch_async(dispatch_get_main_queue()) {
                    fetchViewController.updateCollections()
                    }
                    completionHandler(.NewData)
                }
}

我的 PublicationOverviewController 中的 .fetch

func fetch(completion: () -> Void) {
    PublicationFetcher.shared.fetchAllPublications()
    completion()
}

我认为崩溃是因为我需要主线程上的 UI,但这并没有帮助。任何输入都会很好。

细节:

在我的 PublicationFetcher.shared.fetchAllPublications() 中,我执行以下操作:

  • 从后端获取数据
  • dispatch_async(dispatch_get_main_queue()) { () -> Void in NSNotificationCenter.defaultCenter().postNotificationName("RELOAD_NOTIFICATION", object: nil) }

在那个重新加载通知下我做了一个updateCollections()

斯威夫特 3

DispatchQueue.global(attributes: .qosBackground).async {
    print("This is run on the background queue")

    DispatchQueue.main.async {
        print("This is run on the main queue, after the previous code in outer block")
    }
}
4

2 回答 2

0

在开始 UI 操作之前,尝试给你的应用程序 30 秒的后台获取超时,这可能有助于你的后台网络连接:

func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {

    let fetchViewController = PublicationOverviewController()
                fetchViewController.fetch {
                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (Int64)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue()) {
                    <#code to be executed after a specified delay#>
                    fetchViewController.updateCollections()
                    completionHandler(.NewData)
                }
}

您还可以使用此功能:

func dispatchDelay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

将其称为此示例:

func application(application: UIApplication, performFetchWithCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {

        let fetchViewController = PublicationOverviewController()
                    fetchViewController.fetch {
                        dispatchDelay(25) { // put what you want
                            // this is main-thread queue
                            fetchViewController.updateCollections()
                            completionHandler(.NewData)
                        }
                    }
    }
于 2016-05-19T09:33:31.313 回答
0

不要PublicationOverviewController()再次初始化,因为它会为您提供该视图的新实例,并且您不会得到引用的collectionView. 此外,在接听电话之前,您将获得所有 UI 控件viewDidLoad:

例子:

let *controller : PublicationOverviewController = PublicationOverviewController()
// controller.collectionView will be nil here because view hasn't loaded yet

您可以做什么在方法中发布通知,applicationDidBecomeActive:然后在相应的方法observePublicationOverviewController重新加载您的通知。collectionView

于 2016-05-23T12:27:51.927 回答