6

これを適切に使用する方法については明確ではありませんが、他の人がこの種のことをしているのを見たことがあります:

func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
    manager.sharedInstance.backgroundCompletionHandler = completionHandler
}

同様の実装では、この時点completionHandlerpartial apply forwarder for reabstraction thunk helper...

manager基本的に(シングルトンであるにもかかわらず)どこにありますか:

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.ourcompany.app")
let manager = Alamofire.Manager(configuration: configuration)

ただし、これにより、次の警告がコンソールに出力されます。

Warning: Application delegate received call to -application:handleEventsForBackgroundURLSession:completionHandler: but the completion handler was never called.

ここにブレークポイントを設定しました。この時点で、メッセージはコンソールに既に表示されておりbackgroundCompletionHandlernil.

Xcode 7.0 を使用して iOS 9 SDK に対してビルドしており、現在 Alamofire 2.0.2 を使用しています。

これは当初、Swift 2.0 ブランチをマージしたときに導入されたと思っていましたが、iOS 8 SDK に対して Xcode 6.4 を使用した以前のコミットのメッセージも表示されています。


更新 1

@cnoon の提案に対処するには:

  • 識別子が一致します。構成とマネージャーはシングルトン内に設定されているため、間違っていることはありません。
  • didSetクラスのonbackgroundCompletionHandler内に追加して印刷すると、警告の前にManagerメッセージがログに記録されます。
  • クラス内でsessionDidFinishEventsForBackgroundURLSessionon に設定されたクロージャの内部を出力すると、警告のにメッセージが出力されます。delegateManager
  • sessionDidFinishEventsForBackgroundURLSessionを呼び出す前にその内部でオーバーライドして出力すると、警告のbackgroundCompletionHandlerにメッセージが出力されます。
  • Xcode プロジェクトがバックグラウンド セッション用に正しくセットアップされていることを確認する方法については、その方法がわかりません。また、その方法に関するドキュメントも見つかりませんでした。

携帯電話からいくつかのスクリーンショットをアップロードしようとしたときに、これらの提案を試すために最初にこの問題を再現できなかったことを覚えておく必要があります.

これを再現できるようになったのは、いくつかの写真を共有しようとした後でした。相関関係があるかどうかはわかりませんが、写真のアップロードに時間がかかることに関連している可能性があります.


更新 2

UIBackgroundModes@Nick が説明したとおりに設定されており、completionHandler()内部で直接呼び出しapplication:handleEventsForBackgroundURLSession:completionHandler:ても警告は表示されません。


アップデート 3

そのため、私は小さいながらも重要な詳細を見落としていたようです。Alamofire.Managerそれを直接公開しないラッパーがあります。その実装の関連部分は次のようになります。

private var manager: Manager

public var backgroundCompletionHandler: (() -> Void)? {
    get {
        return manager.backgroundCompletionHandler
    }
    set {
        manager.backgroundCompletionHandler = backgroundCompletionHandler
    }
}

AppDelegateそのコードパスを実行する際に完了ハンドラを設定します。

func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
    myManager.sharedInstance.backgroundCompletionHandler = completionHandler
}

Alamofire.Managerのインスタンスを公開して直接アクセスする次の変更では、警告が生成されないことを確認しました。

public var manager: Manager

//    public var backgroundCompletionHandler: (() -> Void)? {
//        get {
//            return manager.backgroundCompletionHandler
//        }
//        set {
//            manager.backgroundCompletionHandler = backgroundCompletionHandler
//        }
//    }

とでAppDelegate

func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
    myManager.sharedInstance.manager.backgroundCompletionHandler = completionHandler
}

これに基づいて、計算されたプロパティを使用して完了ハンドラーをプロキシすることが問題の原因であると思われます。

このプロパティを公開したくないので、回避策や代替手段を知りたいです。

4

1 に答える 1

1

あなたがしていることはすべて正しいように見えます。あなたが説明したことを正確に実行し、正しく動作し、表示されている警告をスローしないサンプルアプリがあります。まだどこかに小さなエラーがあると思います。試してみるいくつかのアイデアを次に示します。

  • 識別子がバックグラウンド セッションの識別子と一致することを確認します
  • クラスにdidSetログ ステートメントを一時的に追加して、設定されていることを確認します。backgroundSessionHandlerManager
  • ログ ステートメントを に追加して、sessionDidFinishEventsForBackgroundURLSession期待どおりに呼び出されていることを確認します。
  • sessionDidFinishEventsForBackgroundURLSessionデリゲートの をオーバーライドし、手動でbackgroundSessionHandler
  • バックグラウンド セッション用に Xcode プロジェクトが正しく設定されていることを確認します。

更新 2

計算されたプロパティが間違っています。代わりに、 を に設定する必要がありbackgroundCompletionHandlerますnewValue。そうしないと、新しい値に正しく設定されません。詳細については、このスレッドを参照してください。

于 2015-09-26T18:47:39.243 に答える