Please, note that I've checked previous answers and I am not using callbacks in the code. In this case the delegate methods should be called
Environment iOS 14.4.2
URL is valid. File is downloaded. Just the delegate not get called.
The example code is below:
final class Downloader: NSObject, URLSessionDelegate {
private lazy var urlSession = URLSession(
configuration: .default,
delegate: self,
delegateQueue: .main
)
private var downloadTask: URLSessionDownloadTask?
func beginDownload(url: URL) {
downloadTask = urlSession.downloadTask(with: url)
downloadTask!.resume()
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
// NEVER CALLED
}
}
The func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) method you're implementing is part of URLSessionDownloadDelegate, not URLSessionDelegate, so you should declare conformance to URLSessionDownloadDelegate as well in order for the delegate call to occur.
Related
In my application, I need to download a file(size:50mb), also I need to support background downloading. By the following code I can do the download even in the background. The only problem is UI is not updating properly when I tried to switch the app (say I open WhatsApp) and come back to my app without going to iPhone's Home Screen.
I debugged the code, I found didWriteData is not called.
weak var downloadTask: URLSessionDownloadTask?
lazy var downloadSession: URLSession = {
let configuration = URLSessionConfiguration.background(withIdentifier: "MYDOWNLOADIDENTIFIER")
return URLSession(configuration: configuration,
delegate: self,
delegateQueue: OperationQueue.main)
}()
Download Pressed Event:
downloadTask = self.downloadSession.downloadTask(with: fileUrl)
downloadTask?.resume()
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
//UI update for progress level
}
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
logger.write("urlSessionDidFinishEvents\n")
DispatchQueue.main.async {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate,
let completionHandler = appDelegate.backgroundSessionCompletionHandler {
appDelegate.backgroundSessionCompletionHandler = nil
completionHandler()
}
}
}
AppDelegate.swift
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: #escaping () -> Void) {
backgroundSessionCompletionHandler = completionHandler
}
quick question. I want to extract the dowloaded image from the url and save it to a UI Image.
How would I do this?
fileprivate func beginDownload() {
let url = URL(string: "URL")!
let configuration = URLSessionConfiguration.default
let operationQueue = OperationQueue()
let urlSession = URLSession(configuration: configuration, delegate: self, delegateQueue: operationQueue)
let downloadTask = urlSession.downloadTask(with: url)
downloadTask.resume()
}
Here are my URL session protocol stubs:
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
print(totalBytesWritten, totalBytesExpectedToWrite)
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("Finished dowloading file")
}
You need to load the image from the download location created in the delegate method urlSession(_:downloadTask:didFinishDownloadingTo:):
class Request: NSObject {
func getPicture() {
let url = URL(string: "https://media.tractorsupply.com/is/image/TractorSupplyCompany/1305371?$456$")!
let session = URLSession(configuration: .default,
delegate: self,
delegateQueue: nil)
session.downloadTask(with: url).resume()
}
}
extension Request: URLSessionDownloadDelegate {
func urlSession(_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL) {
guard let data = try? Data(contentsOf: location),
let image = UIImage(data: data) else { return }
print(image)
}
}
Request().getPicture()
I use an SDK (YITechnology) but I have a problem to download videos that exceeds 40mb size. When I use that code in the ViewController, videos less than 40mb are okay. The problem is that if they are bigger than 40mb, it stops. How can I tell it to continue to download?
I tried that ticket but it is not exactly the same thing...
ActionCamera:
#objc public class ActionCamera : NSObject, URLSessionDownloadDelegate {
public func downloadFile(fileName: String, destFilePath: String, success: ((YICameraSDK.DownloadTask) -> ())?, fail: ((Error) -> ())?) -> YICameraSDK.ActionCamera
/// Cancel current download task.
public func cancelDownlad() -> YICameraSDK.ActionCamera
/// Download file from camera.
///
/// - Parameters:
/// - fileName: The file you want to download from camera.
/// - destFilePath: The file destination file path. Need to be a full path.
/// - success: This callback will be invoked multiple times to notify the progress.
/// - fail: This callback will be invoked if download failed.
public func downloadFile(fileName: String, destFilePath: String, success: ((YICameraSDK.DownloadTask) -> ())?, fail: ((Error) -> ())?) -> YICameraSDK.ActionCamera
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
}
ViewController.swift:
private var mCamera: ActionCamera!;
self.mCamera.downloadFile(fileName: lastFileName, destFilePath: originPath, success:
{
downloadTask in
self.testLbl.text = String(describing: downloadTask.downloadedBytes)
} , fail: {
error in
let alert = UIAlertView();
alert.message = error as? String;
alert.addButton(withTitle: "Ko")
alert.show()
});
I think it is easy for someone that is familiar with the UrlSession, but it is not my case...
I'm going to read file from API, but its size equal 1.6mb and it takes so much time. I wish to read it by parts, and when i founds data which i needs, i'm going to stop recieve data. I trying to use some delegate methods, but they don't works. I don't understand what goes wrong?
I have next code:
class ViewController: UIViewController, URLSessionTaskDelegate, URLSessionDelegate, URLSessionDataDelegate {
var httpString = "hided"
override func viewDidLoad() {
super.viewDidLoad()
getLogBinData()
}
func getLogBinData() {
let session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue.main)
if let url = URL(string: httpString + "log.bin") {
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = session.dataTask(with: request)
task.resume()
}
}
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
print()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
if dataTask.countOfBytesReceived >= 500 {
print(dataTask.countOfBytesReceived)
}
}
func urlSession(_ session: URLSession,
dataTask: URLSessionDataTask,
didReceive response: URLResponse,
completionHandler: #escaping (URLSession.ResponseDisposition) -> Void) {
if dataTask.countOfBytesReceived >= 500 {
print(dataTask.countOfBytesReceived)
}
}
}
according the comment, i edited code and it's worked.
class ViewController: UIViewController, URLSessionTaskDelegate, URLSessionDelegate, URLSessionDataDelegate {
var httpString = "hided"
override func viewDidLoad() {
super.viewDidLoad()
getLogBinData()
}
func getLogBinData() {
let session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue.main)
if let url = URL(string: httpString + "log.bin") {
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = session.dataTask(with: request)
task.resume()
}
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
if dataTask.countOfBytesReceived >= 500 {
print(dataTask.countOfBytesReceived)
}
}
}
I want to download a file from a certain url .
what I need is the data delegate ( the delegate which gives me the downloaded data) .
I implemented the :
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
delegate but it doesn't get called .
my code is :
func download(url: URL)
{
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
let task = session.downloadTask(with: url)
task.resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
print("apending ")
self.dataaa.append(data)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: #escaping (URLSession.ResponseDisposition) -> Void) {
print("here")
}
the two delegate functions don't get called !
You're using the delegate methods for a data task, but you're creating a download task. Those two task types work differently and use completely different delegate methods.