【问题标题】:Swift - Downloading files on ios 13 errorSwift - 在 ios 13 上下载文件错误
【发布时间】:2019-10-01 08:30:05
【问题描述】:

我有一个可以从 web 视图下载文件的应用程序。它在 ios 12 中运行良好,但无法正常工作。我收到了错误

从主线程访问后,不得从后台线程对其进行修改。

在从主线程访问引擎后,此应用程序正在从后台线程修改自动布局引擎。这可能会导致引擎损坏和奇怪的崩溃。

这是我的 view.controller 代码:

func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
    print(request.url as Any)
    if request.url!.absoluteString.range(of: "/download/") != nil {
        let extention = request.url!.absoluteString.slice(from: "&fileextension=", to: "&")?.lowercased()
        var name = request.url!.absoluteString.slice(from: "&name=", to: "&")?.lowercased()
        name =  name?.replacingOccurrences(of: "+", with: " ")
        DownlondFromUrl(request.url! as URL,name!, extention!)
        return false
    }
    return true
}
func DownlondFromUrl(_ url: URL,_ name:String,_ extensionfile:String){
    // Create destination URL
    let documentsUrl =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
    let destinationUrl = documentsUrl!.appendingPathComponent(name + ".\(extensionfile)")

    //Create URL to the source file you want to download
    let fileURL = url

    let sessionConfig = URLSessionConfiguration.default
    let session = URLSession(configuration: sessionConfig)

    let request = URLRequest(url:fileURL)

    let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
        if let tempLocalUrl = tempLocalUrl, error == nil {
            let dataFromURL = NSData(contentsOf: tempLocalUrl)
            dataFromURL?.write(to: destinationUrl, atomically: true)

            let alert = UIAlertController.init(title: "Download", message: "File download Successful. Do you want open file ", preferredStyle: .actionSheet)
            alert.addAction(UIAlertAction(title: "Open", style: .default , handler:{ (UIAlertAction)in
                let fileBrowser = FileBrowser()
                self.present(fileBrowser, animated: true, completion: nil)
            }))
            alert.addAction(UIAlertAction(title: "Share", style: .default , handler:{ (UIAlertAction)in

                let activityViewController = UIActivityViewController(activityItems: [destinationUrl], applicationActivities: nil)
                activityViewController.popoverPresentationController?.sourceView = self.view
                self.present(activityViewController, animated: true, completion: nil)
            }))
            alert.addAction(UIAlertAction(title: "Dismiss", style: .cancel, handler:{ (UIAlertAction)in
            }))

            self.present(alert, animated: true, completion: {
                print("completion block")
            })
        } else {
            print("Error took place while downloading a file. Error description: %@", error?.localizedDescription as Any);
        }
    }
    task.resume()
}
override func viewWillAppear(_ animated: Bool) {
    self.navigationController?.isNavigationBarHidden = true;
}

}

我找到了这篇文章 (Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread),但我还是个初学者,不知道如何实现它。

【问题讨论】:

  • 我有类似的需求,但它与使用 WKWebView 下载 zip 文件有关。你的问题是我要求的解决方案。您能否为 Swift 5 编辑和更新此代码?

标签: ios swift xcode


【解决方案1】:

您必须在主线程上运行任何访问 UI 的代码。

由于URLSession 任务在后台线程上运行,您必须添加一个DispatchQueue

DispatchQueue.main.async {
    let alert = UIAlertController.init(title: "Download", message: "File download Successful. Do you want open file ", preferredStyle: .actionSheet)
    alert.addAction(UIAlertAction(title: "Open", style: .default , handler:{ action in
        let fileBrowser = FileBrowser()
        self.present(fileBrowser, animated: true, completion: nil)
    }))
    alert.addAction(UIAlertAction(title: "Share", style: .default , handler:{ action in

        let activityViewController = UIActivityViewController(activityItems: [destinationUrl], applicationActivities: nil)
        activityViewController.popoverPresentationController?.sourceView = self.view
        self.present(activityViewController, animated: true, completion: nil)
    }))
    alert.addAction(UIAlertAction(title: "Dismiss", style: .cancel)

    self.present(alert, animated: true, completion: {
        print("completion block")
    })
}

注意:

UIAlertAction 闭包中的参数必须是实例而不是类型。如果不使用该参数,您可以将其替换为下划线字符(例如handler:{ _ in

【讨论】:

  • 谢谢老兄这解决了我的问题:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-12
  • 1970-01-01
相关资源
最近更新 更多