从Swift命令行程序中使用NSURLSession

Fre*_*sen 26 macos nsrunloop nsurlsession swift

我想在将它集成到更大的应用程序之前测试一个小概念验证命令行应用程序.我要做的是使用NSURLSession使用此示例下载一些数据.但是,如果我使用简单OS X命令行应用程序中给出的示例,则应用程序会在检索数据之前退出.

如何使用NSURLSession从独立命令行应用程序下载数据?我读到的是使用NSRunLoop但是我还没有在Swift中找到一个明确的例子,所以如果NSRunLoop实际上是要走的路,那么任何例子都会受到赞赏.

从Swift命令行应用程序的URL下载数据的任何其他策略也是受欢迎的(无限循环?).

nie*_*bot 36

您可以使用信号量来阻止当前线程并等待URL会话完成.

创建信号量,启动URL会话,然后等待信号量.从您的URL会话完成回调,发信号通知信号量.

您可以使用全局标志(声明一个易失性布尔变量)并从while循环中轮询它,但这不是最佳的.首先,你不必要地燃烧CPU周期.

这是我使用游乐场做的一个简单示例:

import Foundation

var sema = DispatchSemaphore( value: 0 )

class Delegate : NSObject, URLSessionDataDelegate
{
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
    {
        print("got data \(String(data: data, encoding: .utf8 ) ?? "<empty>")");
        sema.signal()
    }
}

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: Delegate(), delegateQueue: nil )

guard let url = URL( string:"http://apple.com" ) else { fatalError("Could not create URL object") }

session.dataTask( with: url ).resume()    

sema.wait()
Run Code Online (Sandbox Code Playgroud)


thi*_*goh 8

试试这个

let sema = DispatchSemaphore( value: 0)

let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/4/4d/Cat_November_2010-1a.jpg")!;

let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
  print("after image is downloaded");
  sema.signal(); // signals the process to continue
};

task.resume();
sema.wait(); // sets the process to wait
Run Code Online (Sandbox Code Playgroud)


Vex*_*exy 5

为了概念证明或试用/测试目的,您可以通过硬编码一些超时时间来简化异步复杂性,直到您的东西完成。(见下面的注释)

快速 5

    //...your magic here
    // add a little iness to make it fun at least...
    RunLoop.main.run(until: Date() + 0x10)  //oh boi, default init && hex craze 
    // yeah, 16 seconds timeout

    // or even worse (!)
    RunLoop.main.run(until: .distantFuture)

Run Code Online (Sandbox Code Playgroud)

SWIFT 3 或更早版本

    //...your stuff here
    RunLoop.main.run(until: Date(timeIntervalSinceNow: 15))  //will execute things on main loop for 15 seconds
Run Code Online (Sandbox Code Playgroud)

注意事项

  1. 不要在生产中使用它
  2. 尊重第一条规则

这是克服并行性的严重问题的非常快速和肮脏的方法。探索此问题的其他答案中描述的更好、更复杂的解决方案。