Asynchronous 如何在操场上运行异步回调
许多Cocoa和CoCoatTouch方法在Objective-C中以块的形式实现完成回调,在Swift中以闭包的形式实现。然而,当在操场上尝试这些游戏时,永远不会要求完成。例如:Asynchronous 如何在操场上运行异步回调,asynchronous,callback,closures,swift,swift-playground,Asynchronous,Callback,Closures,Swift,Swift Playground,许多Cocoa和CoCoatTouch方法在Objective-C中以块的形式实现完成回调,在Swift中以闭包的形式实现。然而,当在操场上尝试这些游戏时,永远不会要求完成。例如: // Playground - noun: a place where people can play import Cocoa import XCPlayground let url = NSURL(string: "http://stackoverflow.com") let request = NSURLR
// Playground - noun: a place where people can play
import Cocoa
import XCPlayground
let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.currentQueue() {
response, maybeData, error in
// This block never gets called?
if let data = maybeData {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
println(contents)
} else {
println(error.localizedDescription)
}
}
import Foundation
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://stackoverflow.com")!) {
result in
print("Got result: \(result)")
XCPlaygroundPage.currentPage.finishExecution()
}.resume()
我可以在我的游乐场时间轴中看到控制台输出,但我的完成块中的
println
从未被调用 不调用回调的原因是RunLoop没有在操场上运行(或者在REPL模式下运行)
让回调运行的一种有点僵硬但有效的方法是使用一个标志,然后在runloop上手动迭代:
// Playground - noun: a place where people can play
import Cocoa
import XCPlayground
let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url)
var waiting = true
NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.currentQueue() {
response, maybeData, error in
waiting = false
if let data = maybeData {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
println(contents)
} else {
println(error.localizedDescription)
}
}
while(waiting) {
NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate())
usleep(10)
}
此模式通常用于需要测试异步回调的单元测试中,例如:不调用回调的原因是因为RunLoop没有在操场上运行(或者在REPL模式下运行) 让回调运行的一种有点僵硬但有效的方法是使用一个标志,然后在runloop上手动迭代:
// Playground - noun: a place where people can play
import Cocoa
import XCPlayground
let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url)
var waiting = true
NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.currentQueue() {
response, maybeData, error in
waiting = false
if let data = maybeData {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
println(contents)
} else {
println(error.localizedDescription)
}
}
while(waiting) {
NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate())
usleep(10)
}
此模式通常用于需要测试异步回调的单元测试中,例如:当您可以手动运行运行循环时(或者,对于不需要运行循环的异步代码,使用其他等待方法,如调度信号量),“内置”我们在操场中提供的等待异步工作的方法是导入
XCPlaygroundPage
框架并设置XCPlaygroundPage.currentPage.needsIndefiniteExecution=true
。如果设置了这个属性,当顶级游乐场源代码完成时,我们将继续旋转主运行循环,而不是停止游乐场,这样异步代码就有机会运行。我们最终将在默认为30秒的超时后终止游乐场,但如果您打开助手编辑器并显示时间线助手,则可以对其进行配置;超时在右下角
例如,在Swift 3中(使用URLSession
而不是NSURLConnection
):
或在Swift 2中:
import UIKit
import XCPlayground
let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.currentQueue()) { response, maybeData, error in
if let data = maybeData {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
println(contents)
} else {
println(error.localizedDescription)
}
}
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
虽然您可以手动运行运行循环(或者,对于不需要运行循环的异步代码,可以使用其他等待方法,如调度信号量),但“内置”我们在操场中提供的等待异步工作的方法是导入
XCPlaygroundPage
框架并设置XCPlaygroundPage.currentPage.needsIndefiniteExecution=true
。如果设置了这个属性,当顶级游乐场源代码完成时,我们将继续旋转主运行循环,而不是停止游乐场,这样异步代码就有机会运行。我们最终将在默认为30秒的超时后终止游乐场,但如果您打开助手编辑器并显示时间线助手,则可以对其进行配置;超时在右下角
例如,在Swift 3中(使用URLSession
而不是NSURLConnection
):
或在Swift 2中:
import UIKit
import XCPlayground
let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.currentQueue()) { response, maybeData, error in
if let data = maybeData {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
println(contents)
} else {
println(error.localizedDescription)
}
}
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
从XCode 7.1开始,
XcpsetExecutionShouldContinueIndefinite()
已被弃用。现在正确的方法是首先请求无限期执行作为当前页面的属性:
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
…然后指示执行完成的时间,包括:
XCPlaygroundPage.currentPage.finishExecution()
例如:
// Playground - noun: a place where people can play
import Cocoa
import XCPlayground
let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.currentQueue() {
response, maybeData, error in
// This block never gets called?
if let data = maybeData {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
println(contents)
} else {
println(error.localizedDescription)
}
}
import Foundation
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://stackoverflow.com")!) {
result in
print("Got result: \(result)")
XCPlaygroundPage.currentPage.finishExecution()
}.resume()
从XCode 7.1开始,
XcpsetExecutionShouldContinueIndefinite()
已被弃用。现在正确的方法是首先请求无限期执行作为当前页面的属性:
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
…然后指示执行完成的时间,包括:
XCPlaygroundPage.currentPage.finishExecution()
例如:
// Playground - noun: a place where people can play
import Cocoa
import XCPlayground
let url = NSURL(string: "http://stackoverflow.com")
let request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.currentQueue() {
response, maybeData, error in
// This block never gets called?
if let data = maybeData {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
println(contents)
} else {
println(error.localizedDescription)
}
}
import Foundation
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: "http://stackoverflow.com")!) {
result in
print("Got result: \(result)")
XCPlaygroundPage.currentPage.finishExecution()
}.resume()
此API在Xcode 8中再次更改,并被移动到
PlaygroundSupport
:
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
此更改在中提到。此API在Xcode 8中再次更改,并移动到
PlaygroundSupport
:
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
此更改在中提到。针对XCode8、Swift3和iOS 10的新API包括:
// import the module
import PlaygroundSupport
// write this at the beginning
PlaygroundPage.current.needsIndefiniteExecution = true
// To finish execution
PlaygroundPage.current.finishExecution()
XCode8、Swift3和iOS 10的新API包括:
// import the module
import PlaygroundSupport
// write this at the beginning
PlaygroundPage.current.needsIndefiniteExecution = true
// To finish execution
PlaygroundPage.current.finishExecution()
Swift 3、xcode 8、iOS 10 注意事项:
import UIKit
import Foundation
import PlaygroundSupport
// resolve path errors
URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
// identify that the current page requires "indefinite execution"
PlaygroundPage.current.needsIndefiniteExecution = true
// encapsulate execution completion
func completeExecution() {
PlaygroundPage.current.finishExecution()
}
let url = URL(string: "http://i.imgur.com/aWkpX3W.png")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
var image = UIImage(data: data!)
// complete execution
completeExecution()
}
task.resume()
告诉编译器游乐场文件需要“无限执行”
通过在完成处理程序中调用PlaygroundSupport.current.completeExecution()
手动终止执行
缓存目录可能会出现问题,要解决此问题,需要手动重新实例化UICache.shared singleton
示例:
import UIKit
import Foundation
import PlaygroundSupport
// resolve path errors
URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
// identify that the current page requires "indefinite execution"
PlaygroundPage.current.needsIndefiniteExecution = true
// encapsulate execution completion
func completeExecution() {
PlaygroundPage.current.finishExecution()
}
let url = URL(string: "http://i.imgur.com/aWkpX3W.png")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
var image = UIImage(data: data!)
// complete execution
completeExecution()
}
task.resume()
Swift 3、xcode 8、iOS 10 注意事项:
import UIKit
import Foundation
import PlaygroundSupport
// resolve path errors
URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
// identify that the current page requires "indefinite execution"
PlaygroundPage.current.needsIndefiniteExecution = true
// encapsulate execution completion
func completeExecution() {
PlaygroundPage.current.finishExecution()
}
let url = URL(string: "http://i.imgur.com/aWkpX3W.png")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
var image = UIImage(data: data!)
// complete execution
completeExecution()
}
task.resume()
告诉编译器游乐场文件需要“无限执行”
通过在完成处理程序中调用PlaygroundSupport.current.completeExecution()
手动终止执行
缓存目录可能会出现问题,要解决此问题,需要手动重新实例化UICache.shared singleton
示例:
import UIKit
import Foundation
import PlaygroundSupport
// resolve path errors
URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
// identify that the current page requires "indefinite execution"
PlaygroundPage.current.needsIndefiniteExecution = true
// encapsulate execution completion
func completeExecution() {
PlaygroundPage.current.finishExecution()
}
let url = URL(string: "http://i.imgur.com/aWkpX3W.png")
let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
var image = UIImage(data: data!)
// complete execution
completeExecution()
}
task.resume()
Swift 4,Xcode 9.0 <代码>导入基础 导入PlaygroundSupport PlaygroundPage.current.NeedsDefiniteExecution=true 让url=url(字符串:https://jsonplaceholder.typicode.com/posts/1")! 让task=URLSession.shared.dataTask(带:url){(数据、响应、错误)在 保护错误==nil else{ 打印(错误?.localizedDescription??) 返回 } 如果let data=data,则let contents=String(数据:data,编码:String.encoding.utf8){ 印刷品(目录) } } task.resume()
Swift 4,Xcode 9.0 <代码>导入基础 导入PlaygroundSupport PlaygroundPage.current.NeedsDefiniteExecution=true 让url=url(字符串:https://jsonplaceholder.typicode.com/posts/1")! 让task=URLSession.shared.dataTask(带:url){(数据、响应、错误)在 保护错误==nil else{ 打印(错误?.localizedDescription??) 返回 } 如果let data=data,则let contents=String(数据:data,编码:String.encoding.utf8){ 印刷品(目录) } } task.resume()
2014年世界野生动植物保护大会(WWDC)对此作了详细介绍?