NSURLSessionを使って通信処理を書いてみる
http://woshidan.hatenablog.com/entry/2017/06/18/014734 の記事の続きで、先の記事の中の
2.
Foregroundでダウンロード処理を開始する場合は、ダウンロード中にアプリが停止ないし終了してもよいようにそのダウンロード処理の管理をシステム側へ手渡すことができる
の部分についてメモします。
ポイント
- ファイルをダウンロードするときは、NSURLSessionを使う
- そうすることでアプリがバックグラウンドでデータ通信している間はiOSのシステム側がアプリを停止してもダウンロード処理はシステム側でしてくれる
- ダウンロード/アップロードが終わったり、アプリに注目させる必要がある場合はアプリを起動させることができる
- その場合は、application(_:handleEventsForBackgroundURLSession:completionHandler:)メソッドを使う
- ただし、
NSURLSessionConfiguration
オブジェクトのsessionSendLaunchEvents
がYES
の場合
- どのNSURLSessionオブジェクトによるデータ通信処理か、どのNSURLSessionオブジェクトによる
application(_:handleEventsForBackgroundURLSession:completionHandler:
コールバックかを判定するためには、NSURLSessionとNSURLSessionConfigurationを作成する際にidenrifier
(NSString) を使う
試し書き
試しに書いてみたときのメモと置いておきます。
class ViewController: UIViewController, URLSessionTaskDelegate { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let button = UIButton(); button.frame = CGRect(x: 200, y: 200, width: 120, height: 50); button.setTitle("download test", for: UIControlState.normal); button.backgroundColor = UIColor.blue; button.addTarget(self, action: #selector(onClick(sender:)), for: UIControlEvents.touchUpInside); self.view.addSubview(button); } func onClick(sender: UIButton) { // let session = URLSession(); // -> [NSURLSession downloadTaskForRequest:downloadFilePath:resumeData:completion:]: unrecognized selector sent to instance 0x6180000103a0 // see: https://stackoverflow.com/questions/32905874/nsurlsession-datataskforrequestcompletion-unrecognized-selector-sent-to-instan // let config = URLSessionConfiguration.default; let config = URLSessionConfiguration.background(withIdentifier: "test"); // ここのidentiferが同じで、続けてボタン押してDLしようとした場合 // 2017-07-05 06:58:17.522 NSURLSessionTest[52291:6981685] A background URLSession with identifier test already exists! config.sessionSendsLaunchEvents = true; // config.isDiscretionary = true; // URLSessionのコンストラクタでDelegateの設定をすること // let session = URLSession(configuration: config); let session = URLSession(configuration: config, delegate: self, delegateQueue: nil); let url = URL(string: "https://some.page.html"); // let config = URLSessionConfiguration.background(withIdentifier: "test"); <- URLSessionConfiguration.background.default の変更 // 上記変更はバックグラウンドで処理ができるようにするため // この場合は下記のようにタスクを生成する際に、Completion Handlerを渡すのではなく // URLSessionTaskDelegateを渡し、レスポンス取得後の処理はDelegateに書く // Terminating app due to uncaught exception 'NSGenericException', reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.' // let task = session.downloadTask(with: url!, completionHandler: { (data, response, error) in // DispatchQueue.main.async(execute: { // print(response); // print("DONE"); // }) // }); let task = session.downloadTask(with: url!); task.resume(); } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // URLSessionTaskDelegateのメソッド // データ通信完了時の処理 // https://developer.apple.com/documentation/foundation/urlsessiontaskdelegate/1411610-urlsession func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { if (error != nil) { print("HTTPリクエスト失敗処理"); } else { print(task.response); } } }
参考
久しぶりだったので試しに少し書いて見るだけで力尽きてしまった。もう一回調べたほうがよさそう。 URLSessionTaskDelegate と URLSessionDelegateの違いとか、各Delegateメソッドの違いとか。