从 Swift 命令行程序使用 NSURLSession
Using NSURLSession from a Swift command line program
我正在尝试先测试一些概念验证命令行应用程序,然后再将其集成到更大的应用程序中。我想做的是使用 this example 使用 NSURLSession 下载一些数据。但是,如果我使用简单的 OS X 命令行应用程序中给出的示例,那么应用程序会在检索数据之前退出。
如何使用 NSURLSession 从独立的命令行应用下载数据?我读到的是使用 NSRunLoop 但是我还没有在 Swift 中找到一个明确的例子所以如果 NSRunLoop 实际上是要走的路那么任何例子都将不胜感激。
也欢迎从 URL 为 Swift 命令行应用程序下载数据的任何其他策略(无限 while 循环?)。
您可以使用信号量来阻塞当前线程并等待 URL 会话完成。
创建信号量,启动您的 URL 会话,然后等待信号量。从您的 URL 会话完成回调中,发出信号量。
您可以使用一个全局标志(声明一个 volatile 布尔变量)并从 while 循环中轮询它,但这不是最佳选择。一方面,您不必要地消耗 CPU 个周期。
这是我使用 playground 做的一个简单示例:
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()
为了概念证明或 tryouts/testing 目的,您可以通过 硬编码 一些超时时间来简化异步复杂性,直到您的东西完成。 (见下面的注释)
SWIFT 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)
SWIFT 3 或更早
//...your stuff here
RunLoop.main.run(until: Date(timeIntervalSinceNow: 15)) //will execute things on main loop for 15 seconds
注释 :
- 不要在生产中使用它
- 遵守第一条规则
这是一种非常快速而肮脏的 方法来克服并行性的严重问题。探索此问题的其他答案中描述的更好、更复杂的解决方案。
试试这个
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
我正在尝试先测试一些概念验证命令行应用程序,然后再将其集成到更大的应用程序中。我想做的是使用 this example 使用 NSURLSession 下载一些数据。但是,如果我使用简单的 OS X 命令行应用程序中给出的示例,那么应用程序会在检索数据之前退出。
如何使用 NSURLSession 从独立的命令行应用下载数据?我读到的是使用 NSRunLoop 但是我还没有在 Swift 中找到一个明确的例子所以如果 NSRunLoop 实际上是要走的路那么任何例子都将不胜感激。
也欢迎从 URL 为 Swift 命令行应用程序下载数据的任何其他策略(无限 while 循环?)。
您可以使用信号量来阻塞当前线程并等待 URL 会话完成。
创建信号量,启动您的 URL 会话,然后等待信号量。从您的 URL 会话完成回调中,发出信号量。
您可以使用一个全局标志(声明一个 volatile 布尔变量)并从 while 循环中轮询它,但这不是最佳选择。一方面,您不必要地消耗 CPU 个周期。
这是我使用 playground 做的一个简单示例:
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()
为了概念证明或 tryouts/testing 目的,您可以通过 硬编码 一些超时时间来简化异步复杂性,直到您的东西完成。 (见下面的注释)
SWIFT 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)
SWIFT 3 或更早
//...your stuff here
RunLoop.main.run(until: Date(timeIntervalSinceNow: 15)) //will execute things on main loop for 15 seconds
注释 :
- 不要在生产中使用它
- 遵守第一条规则
这是一种非常快速而肮脏的 方法来克服并行性的严重问题。探索此问题的其他答案中描述的更好、更复杂的解决方案。
试试这个
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