1

そのため、バックグラウンド フェッチを行っており、その後 UI を更新したいと考えています。バックグラウンド フェッチ自体 (データベース) は機能しますが、UI を更新したいときにクラッシュunexpectedly found nil while unwrapping an Optional value します。xCode によるとself.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 に答える