许多Cocoa和CoCoatTouch方法在Objective-C中以块的形式实现完成回调,在Swift中以闭包的形式实现.然而,当在操场上try 这些时,永远不会要求完成.例如:

// 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)
    }
}

我可以在我的playground 时间线中看到控制台输出,但我的完成块中的println从未被调用...

推荐答案

虽然可以手动运行运行循环(或者,对于不需要运行循环的异步代码,可以使用其他等待方法,如调度信号量),但我们在操场中提供的等待异步工作的"内置"方式是导入XCPlayground框架并设置XCPlaygroundPage.currentPage.needsIndefiniteExecution = true.如果设置了这个属性,当顶级playground 源代码完成时,我们将继续旋转主运行循环,而不是停止playground ,这样异步代码就有机会运行.我们最终会在一个默认为30秒的超时后终止playground ,但如果您打开助手编辑器并显示时间线助手,则可以对其进行配置;超时在右下角.

例如,在Swift 3中(使用URLSession而不是NSURLConnection):

import UIKit
import PlaygroundSupport

let url = URL(string: "http://stackoverflow.com")!

URLSession.shared.dataTask(with: url) { data, response, error in
    guard let data = data, error == nil else {
        print(error ?? "Unknown error")
        return
    }

    let contents = String(data: data, encoding: .utf8)
    print(contents!)
}.resume()

PlaygroundPage.current.needsIndefiniteExecution = true

或者在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

Swift相关问答推荐

对多个项目的数组进行排序

如何在HStack中均匀分布视图?

不使用`lockFocus`将两个重叠的NSImage转换为单个NSImage

从后台线程获取@发布属性的值(不更改它)是正确的吗?

如何让ScrollView缩小到合适的大小,并在没有黑客攻击的情况下占用最小空间

SwiftUI,如何更改具有多个按钮和一个布尔条件的一个按钮标签

当将新值推送到 NavigationStack 时,SwiftUI 的 navigationDestination 已在堆栈的早期声明

减小SF符号的边框宽度

如何在visionOS中将模型锚定在用户头部上方?

如何在 SwiftUI 中用图像替换占位符文本?

Swift-如何接受多个(联合)类型作为参数

使用列表的下一项更新相同的视图

Subclass.fetchRequest() Swift 3.0,扩展并没有真正帮助 100%?

在 Xcode 中自动实现 Swift 协议方法

Swift 中 NSFetchRequest 的多个 NSPredicates?

Swift 自定义字体 Xcode

如何使用 swift 将 Images.xcassets 中的图像加载到 UIImage 中

Swift 3:小数到 Int

如何在 Swift 中使用 Crashlytics 登录?

SwiftUI:将多个 BindableObjects 放入环境