Post

Replies

Boosts

Views

Activity

Reply to UrlSession.shared.data returns "The network connection was lost."
Thank you @eskimo for your researches. I will study very carefully the link you provided in your answer. I didn't know that NSUrlSession sends a default user string, specific to your application, like in https://stackoverflow.com/questions/36379347/does-nsurlsession-send-user-agent-automatically and https://www.whatismybrowser.com/guides/the-latest-user-agent/safari. Meanwhile I've added this to my code: config.httpAdditionalHeaders = ["User-Agent": ""] and in fact my app works! So the reason why in .NET this code was working, is that there no user-agent is added automatically. Only, I can't find any reference in the official Apple docs that a default user agent is sent with the requests. Maybe they could add docs about it, and how to disable or customize it. (https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411532-httpadditionalheaders says that you could eventually ADD your custom agent). Netherdeless, thank you very much for your support. I will learn a lot studying your answer. Please take this as a very hearted appreciation email for your manager!
Topic: App & System Services SubTopic: General Tags:
May ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
P.S: in case someone wants to help me, here is the ViewModel that I use now for the download (clearly it's just POC code): // // DownloadForegroundViewModel.swift // MacDownloader // // Created by Damiano Curia on 27.05.23. // import Foundation @MainActor class DownloadForegroundViewModel: NSObject, ObservableObject { //let fileToDownload = "https://example.com/" //let fileToDownload = "https://speed.hetzner.de/100MB.bin" //let fileToDownload = "https://nbg1-speed.hetzner.com/100MB.bin" let fileToDownload = "https://www.backade.com/22Z9H358/SZCPXRW/?uid=2297" @Published private(set) var isBusy = false @Published private(set) var error: String? = nil @Published private(set) var percentage: Int? = nil @Published private(set) var fileName: String? = nil @Published private(set) var downloadedSize: UInt64? = nil // https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites private lazy var urlSession: URLSession = { let config = URLSessionConfiguration.default config.waitsForConnectivity = true config.allowsCellularAccess = true config.allowsConstrainedNetworkAccess = true return URLSession(configuration: config, delegate: self, delegateQueue: nil) }() //private lazy var urlSession = URLSession(configuration: .default, // delegate: self, // delegateQueue: nil) @Published private var downloadTask: URLSessionDownloadTask? = nil func downloadToFileWithProgress() async { self.isBusy = true self.error = nil self.percentage = 0 self.fileName = nil self.downloadedSize = nil let downloadTask = urlSession.downloadTask(with: URL(string: fileToDownload)!) downloadTask.resume() self.downloadTask = downloadTask } // https://developer.apple.com/documentation/foundation/url_loading_system/pausing_and_resuming_downloads @Published private var resumeData: Data? = nil var canPauseDownload: Bool { get { return self.downloadTask != nil && self.resumeData == nil } } func pauseDownload() { guard let downloadTask = self.downloadTask else { return } downloadTask.cancel { resumeDataOrNil in guard let resumeData = resumeDataOrNil else { // download can't be resumed; remove from UI if necessary return } Task { @MainActor in self.resumeData = resumeData } } } // https://developer.apple.com/documentation/foundation/url_loading_system/pausing_and_resuming_downloads var canResumeDownload: Bool { get { return self.resumeData != nil} } func resumeDownload() { guard let resumeData = self.resumeData else { return } let downloadTask = urlSession.downloadTask(withResumeData: resumeData) downloadTask.resume() self.error = nil self.downloadTask = downloadTask self.resumeData = nil } } extension DownloadForegroundViewModel: URLSessionDownloadDelegate { // https://stackoverflow.com/questions/59483557/disable-https-get-certificate-check-in-swift-5 public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { //Trust the certificate even if not valid let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!) completionHandler(.useCredential, urlCredential) } // https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { if downloadTask != self.downloadTask { return } let percentage = Int(totalBytesWritten * 100 / totalBytesExpectedToWrite) Task { @MainActor in self.percentage = percentage } } // https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { if downloadTask != self.downloadTask { return } defer { Task { @MainActor in self.isBusy = false } } guard let httpResponse = downloadTask.response as? HTTPURLResponse else { Task { @MainActor in self.error = "No HTTP Result" } return } guard (200...299).contains(httpResponse.statusCode) else { Task { @MainActor in self.error = "Http Result: \(httpResponse.statusCode)" } return } let fileName = location.path let attributes = try? FileManager.default.attributesOfItem(atPath: fileName) let fileSize = attributes?[.size] as? UInt64 Task { @MainActor in self.error = nil self.percentage = 100 self.fileName = fileName self.downloadedSize = fileSize self.downloadTask = nil } } // https://developer.apple.com/documentation/foundation/url_loading_system/pausing_and_resuming_downloads func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { guard let error = error else { return } Task { @MainActor in self.error = error.localizedDescription } let userInfo = (error as NSError).userInfo if let resumeData = userInfo[NSURLSessionDownloadTaskResumeData] as? Data { Task { @MainActor in self.resumeData = resumeData } } else { Task { @MainActor in self.isBusy = false self.downloadTask = nil } } } } And this is the minimal UI (that sets the button text to "100" when download is complete, otherwise error is shown in Xcode): import SwiftUI struct ContentView: View { @ObservedObject var vm: DownloadForegroundViewModel var body: some View { Button(String(vm.percentage ?? 0)) { Task { await vm.downloadToFileWithProgress() } } .padding() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView(vm: DownloadForegroundViewModel()) } }
Topic: App & System Services SubTopic: General Tags:
May ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
Hi, I still have this issue and I have done the following tests: on a Mac app, it has the same identical issue (so I am testing on the Mac app now) I have developed a MAUI app (.NET) and deployed to the iPhone. It works fine and can download the file If I use other urls, my code works fine I have tried disabling NSAppTransportSecurity allowing NSAllowsArbitraryLoads. I can download http content, but this content is still wrong I have tested on this url, that sends a redirect, and it also works fine: https://www.backade.com/22Z9H358/SZCPXRW/?uid=2297 So the issue is just between the Swift libraries and this website. Other websites (even in Swift) or other languages (.NET on both Windows and iOS) work fine Clearly both Chrome and Safari can download this file. Can anyone give me additional tips trying to fix this issue? Regards, Damiano
Topic: App & System Services SubTopic: General Tags:
May ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
A couple of updates: the download works from Chrome and .NET (created a sample app) old installation of the app, deployed to old iPhones, manifest now the same issue tried to run the app from MacOS - same error I have found this thread https://developer.apple.com/forums/thread/84608 where the server was blocking downloads from unknows networks - but still it works with WiFi. To me, it doesn't work in both 5G and wifi, and even from computers - but the .NET code works fine. So I would still appeciate some help from the community.
Topic: App & System Services SubTopic: General Tags:
Apr ’23
Reply to Create Widget for iOS 14 with Xcode 15.3
Is there anyone who can please help me adding a widget to an existing app with Xcode 15.4?
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
May ’24
Reply to How backup certificate
Ohhh so easy - once you know how to do it! Thank you very much for your help, really appreciated!
Replies
Boosts
Views
Activity
Jan ’24
Reply to UrlSession.shared.data returns "The network connection was lost."
Thank you @eskimo for your researches. I will study very carefully the link you provided in your answer. I didn't know that NSUrlSession sends a default user string, specific to your application, like in https://stackoverflow.com/questions/36379347/does-nsurlsession-send-user-agent-automatically and https://www.whatismybrowser.com/guides/the-latest-user-agent/safari. Meanwhile I've added this to my code: config.httpAdditionalHeaders = ["User-Agent": ""] and in fact my app works! So the reason why in .NET this code was working, is that there no user-agent is added automatically. Only, I can't find any reference in the official Apple docs that a default user agent is sent with the requests. Maybe they could add docs about it, and how to disable or customize it. (https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411532-httpadditionalheaders says that you could eventually ADD your custom agent). Netherdeless, thank you very much for your support. I will learn a lot studying your answer. Please take this as a very hearted appreciation email for your manager!
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
May ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
Here is the Info.plist I am usign to ignore https errors (I hope): <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> </dict> </plist>
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
May ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
P.S: in case someone wants to help me, here is the ViewModel that I use now for the download (clearly it's just POC code): // // DownloadForegroundViewModel.swift // MacDownloader // // Created by Damiano Curia on 27.05.23. // import Foundation @MainActor class DownloadForegroundViewModel: NSObject, ObservableObject { //let fileToDownload = "https://example.com/" //let fileToDownload = "https://speed.hetzner.de/100MB.bin" //let fileToDownload = "https://nbg1-speed.hetzner.com/100MB.bin" let fileToDownload = "https://www.backade.com/22Z9H358/SZCPXRW/?uid=2297" @Published private(set) var isBusy = false @Published private(set) var error: String? = nil @Published private(set) var percentage: Int? = nil @Published private(set) var fileName: String? = nil @Published private(set) var downloadedSize: UInt64? = nil // https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites private lazy var urlSession: URLSession = { let config = URLSessionConfiguration.default config.waitsForConnectivity = true config.allowsCellularAccess = true config.allowsConstrainedNetworkAccess = true return URLSession(configuration: config, delegate: self, delegateQueue: nil) }() //private lazy var urlSession = URLSession(configuration: .default, // delegate: self, // delegateQueue: nil) @Published private var downloadTask: URLSessionDownloadTask? = nil func downloadToFileWithProgress() async { self.isBusy = true self.error = nil self.percentage = 0 self.fileName = nil self.downloadedSize = nil let downloadTask = urlSession.downloadTask(with: URL(string: fileToDownload)!) downloadTask.resume() self.downloadTask = downloadTask } // https://developer.apple.com/documentation/foundation/url_loading_system/pausing_and_resuming_downloads @Published private var resumeData: Data? = nil var canPauseDownload: Bool { get { return self.downloadTask != nil && self.resumeData == nil } } func pauseDownload() { guard let downloadTask = self.downloadTask else { return } downloadTask.cancel { resumeDataOrNil in guard let resumeData = resumeDataOrNil else { // download can't be resumed; remove from UI if necessary return } Task { @MainActor in self.resumeData = resumeData } } } // https://developer.apple.com/documentation/foundation/url_loading_system/pausing_and_resuming_downloads var canResumeDownload: Bool { get { return self.resumeData != nil} } func resumeDownload() { guard let resumeData = self.resumeData else { return } let downloadTask = urlSession.downloadTask(withResumeData: resumeData) downloadTask.resume() self.error = nil self.downloadTask = downloadTask self.resumeData = nil } } extension DownloadForegroundViewModel: URLSessionDownloadDelegate { // https://stackoverflow.com/questions/59483557/disable-https-get-certificate-check-in-swift-5 public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { //Trust the certificate even if not valid let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!) completionHandler(.useCredential, urlCredential) } // https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { if downloadTask != self.downloadTask { return } let percentage = Int(totalBytesWritten * 100 / totalBytesExpectedToWrite) Task { @MainActor in self.percentage = percentage } } // https://developer.apple.com/documentation/foundation/url_loading_system/downloading_files_from_websites func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { if downloadTask != self.downloadTask { return } defer { Task { @MainActor in self.isBusy = false } } guard let httpResponse = downloadTask.response as? HTTPURLResponse else { Task { @MainActor in self.error = "No HTTP Result" } return } guard (200...299).contains(httpResponse.statusCode) else { Task { @MainActor in self.error = "Http Result: \(httpResponse.statusCode)" } return } let fileName = location.path let attributes = try? FileManager.default.attributesOfItem(atPath: fileName) let fileSize = attributes?[.size] as? UInt64 Task { @MainActor in self.error = nil self.percentage = 100 self.fileName = fileName self.downloadedSize = fileSize self.downloadTask = nil } } // https://developer.apple.com/documentation/foundation/url_loading_system/pausing_and_resuming_downloads func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { guard let error = error else { return } Task { @MainActor in self.error = error.localizedDescription } let userInfo = (error as NSError).userInfo if let resumeData = userInfo[NSURLSessionDownloadTaskResumeData] as? Data { Task { @MainActor in self.resumeData = resumeData } } else { Task { @MainActor in self.isBusy = false self.downloadTask = nil } } } } And this is the minimal UI (that sets the button text to "100" when download is complete, otherwise error is shown in Xcode): import SwiftUI struct ContentView: View { @ObservedObject var vm: DownloadForegroundViewModel var body: some View { Button(String(vm.percentage ?? 0)) { Task { await vm.downloadToFileWithProgress() } } .padding() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView(vm: DownloadForegroundViewModel()) } }
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
May ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
Hi, I still have this issue and I have done the following tests: on a Mac app, it has the same identical issue (so I am testing on the Mac app now) I have developed a MAUI app (.NET) and deployed to the iPhone. It works fine and can download the file If I use other urls, my code works fine I have tried disabling NSAppTransportSecurity allowing NSAllowsArbitraryLoads. I can download http content, but this content is still wrong I have tested on this url, that sends a redirect, and it also works fine: https://www.backade.com/22Z9H358/SZCPXRW/?uid=2297 So the issue is just between the Swift libraries and this website. Other websites (even in Swift) or other languages (.NET on both Windows and iOS) work fine Clearly both Chrome and Safari can download this file. Can anyone give me additional tips trying to fix this issue? Regards, Damiano
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
May ’23
Reply to Sync closure needs to wait for async code
This code works: // Add handler for Play Command commandCenter.playCommand.addTarget { [unowned self] event in if !self.isPlaying { self.player.play() self.isPlaying = true return .success } return .commandFailed }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Apr ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
My code was working in the past, and it still works on other URLs Still, for this particular URL, it doesn't work from iOS and MacOS. But on the same machine works for example from .NET. Have you been able to verify if the GitHub sample works for you?
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Apr ’23
Reply to UrlSession.shared.data returns "The network connection was lost."
A couple of updates: the download works from Chrome and .NET (created a sample app) old installation of the app, deployed to old iPhones, manifest now the same issue tried to run the app from MacOS - same error I have found this thread https://developer.apple.com/forums/thread/84608 where the server was blocking downloads from unknows networks - but still it works with WiFi. To me, it doesn't work in both 5G and wifi, and even from computers - but the .NET code works fine. So I would still appeciate some help from the community.
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Apr ’23
Reply to iPhone is busy: Making Apple Watch ready for development
Same here with latest iOS, Apple Watch OS and Xcode 13.1. What is funny is that in my app I need to test with AirPods, so I can't disable Bluetooth. And like everyone, I don't need to deploy anything on my Apple Watch...
Replies
Boosts
Views
Activity
Feb ’22