代码之家  ›  专栏  ›  技术社区  ›  Kurt Peek

未在命令行脚本中执行UrlsessionDataTask的完成处理程序?[复制品]

  •  1
  • Kurt Peek  · 技术社区  · 7 年前

    这个问题已经有了答案:

    我正在尝试转换示例 https://developer.apple.com/documentation/foundation/url_loading_system/fetching_website_data_into_memory 我可以用它来做实验。我在Xcode中启动了一个新的“命令行工具”项目,并将其添加到 main.swift :

    import Foundation
    
    print("Hello, World!")
    
    func getToDos() {
        let url = URL(string: "https://jsonplaceholder.typicode.com/todos")!
        let task = URLSession.shared.dataTask(with: url) { data, response, error in
            if let error = error {
                print("Error: \(error)")
                return
            }
            guard let httpResponse = response as? HTTPURLResponse,
                (200...299).contains(httpResponse.statusCode) else {
                    print("Request was not successful")
                    return
            }
            print("Hello again!")
        }
        task.resume()
    }
    
    getToDos()
    

    但是,如果运行脚本,我会得到以下输出:

    Hello, World!
    Program ended with exit code: 0
    

    换句话说,似乎从未调用完成处理程序(因为它没有任何内容被打印出来),即使 getToDos() 在脚本末尾调用。另外,如果我在完成处理程序中设置了一个断点,它就不会被击中。

    为什么此脚本不执行完成处理程序?

    2 回复  |  直到 7 年前
        1
  •  2
  •   Dharmesh Kheni Steve Rosenberg    7 年前

    HERE 是一个类似的解决方案,我已经用您的代码对其进行了更新。

    import Foundation
    
    print("Hello, World!")
    
    var sema = DispatchSemaphore(value: 0)
    
    class Delegate : NSObject, URLSessionDataDelegate {
        func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
            print("Hello again!")
            print("got data \(String(data: data, encoding: .utf8 ) ?? "<empty>")");
            sema.signal()
        }
    }
    
    func getToDos() {
        let config = URLSessionConfiguration.default
        let url = URL(string: "https://jsonplaceholder.typicode.com/todos")!
        let session = URLSession(configuration: config, delegate: Delegate(), delegateQueue: nil)
        session.dataTask( with: url ).resume()
    }
    
    getToDos()
    sema.wait()
    

    基本上你错过了 DispatchSemaphore URLSessionDataDelegate 方法。

    所以在控制台中,您将得到:

    Hello, World!
    Hello again!
    got data [
      //your JSON here
    ]
    Program ended with exit code: 0
    
        2
  •  0
  •   Kurt Peek    7 年前

    我相信发生的事情是,在完成处理程序有机会执行之前,脚本已经完成了执行。跟随 Using NSURLSession from a Swift command line program ,我添加了一个 DispatchSemaphore 哪一个 .signal 在完成处理程序结束时 .wait S在脚本末尾:

    import Foundation
    
    var sema = DispatchSemaphore(value: 0)
    
    print("Hello, World!")
    
    func getToDos() {
        let url = URL(string: "https://jsonplaceholder.typicode.com/todos")!
        let task = URLSession.shared.dataTask(with: url) { data, response, error in
            if let error = error {
                print("Error: \(error)")
                return
            }
            guard let httpResponse = response as? HTTPURLResponse,
                (200...299).contains(httpResponse.statusCode) else {
                    print("Request was not successful")
                    return
            }
            print("Hello again!")
            sema.signal()
        }
        task.resume()
    }
    
    getToDos()
    sema.wait()
    

    现在,程序运行时间较长,但打印预期输出:

    Hello, World!
    Hello again!
    Program ended with exit code: 0