【问题标题】:How does Apple's new programming language Swift handle blocks and asynchronous requests?Apple 的新编程语言 Swift 如何处理块和异步请求?
【发布时间】:2014-07-23 06:30:38
【问题描述】:

参考苹果在 Swift 上的网页:https://developer.apple.com/swift/

在 Swift 中是否像在 Objective-c 中一样有块?它们是如何创建和调用的?

如何在 Swift 中进行异步请求?

在 swift 中创建与块相关的内存泄漏是否容易?如果是,您将如何避免它们?

【问题讨论】:

标签: swift


【解决方案1】:

正如我在另一个问题中所说,您有很多方法可以传递与 Swift 中的函数等效的块。

我找到了三个。

为了理解这一点,我建议你在操场上测试这段小代码。

func test(function:String -> String) -> String
{
    return function("test")
}

func funcStyle(s:String) -> String
{
    return "FUNC__" + s + "__FUNC"
}
let resultFunc = test(funcStyle)

let blockStyle:(String) -> String = {s in return "BLOCK__" + s + "__BLOCK"}
let resultBlock = test(blockStyle)

let resultAnon = test({(s:String) -> String in return "ANON_" + s + "__ANON" })


println(resultFunc)
println(resultBlock)
println(resultAnon)

更新:匿名函数有两种特殊情况。

首先是可以推断函数签名,因此您不必重写它。

let resultShortAnon = test({return "ANON_" + $0 + "__ANON" })

第二种特殊情况只有在块是最后一个参数时才有效,它被称为尾随闭包

这是一个例子(与推断的签名合并以显示 Swift 的力量)

let resultTrailingClosure = test { return "TRAILCLOS_" + $0 + "__TRAILCLOS" }

最后,举个例子:

使用所有这些功能,我要做的是混合尾随闭包和类型推断(为可读性而命名)

PFFacebookUtils.logInWithPermissions(permissions) {
    user, error in
    if (!user) {
        println("Uh oh. The user cancelled the Facebook login.")
    } else if (user.isNew) {
        println("User signed up and logged in through Facebook!")
    } else {
        println("User logged in through Facebook!")
    }
}

【讨论】:

  • 我认为这是很好的组合,但如果你使用 'callingFunctionsName' 而不是 's' 会更快。
【解决方案2】:

(Objective-)C 块的 Swift 等效项称为闭包。在 The Swift Programming Language 书籍中有关于它们的 a whole chapter

根据你使用闭包的上下文,你可以用非常简洁的语法声明/使用它。例如,可以像这样调用带有签名为(success: Bool, error: NSError) - > Void 的完成处理程序的方法:

someMethod(otherParameters: otherValues, completionHandler:{ success, error in
    if !success { NSLog("I am a leaf on the wind: %@", error) }
})

还有一个尾随闭包语法,在闭包本质上提供流控制的情况下读起来很好。当您想要非常简短时,您可以删除参数名称(以牺牲可读性为代价,但在以下一些明显的情况下没关系)。通常return 语句也是隐含的。

myArray.sort { $0 < $1 }
let squares = myArray.map { value in
    value * 2
}    

Swift 本身没有任何用于异步请求的功能,因此您可以使用现有的 API。不过,您可以使用尾随闭包语法:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // do some async stuff
    NSOperationQueue.mainQueue().addOperationWithBlock {
        // do some main thread stuff stuff
    }
}

在大多数情况下,您无需像使用 ObjC 块那样担心使用 Swift 闭包创建引用循环。简而言之,捕获语义与大多数东西的“正常工作”方式非常相似,但对于块/闭包的常见模式使用(例如调度到后台/主线程并引用@987654329 @ 的属性)不会导致循环。

不过,循环仍然是可能的,并且有一个解决方案。这个答案已经有点长了,所以请查看文档中的Strong Reference Cycles for Closures 以获得完整的解释。

【讨论】:

  • 我很沮丧他们没有提供语言内的东西来简化异步编程,比如 monads、ES6 yield/generators 等。
  • 我想我在标准库中看到了一些看起来像生成器的东西。 Cmd 并单击 String 之类的符号并滚动——那里有很多有趣的细节。
  • 看起来他们只是将它们用于迭代。
  • @rickster,我将您引向这个问题stackoverflow.com/a/20760583/294884,它现在已经过时了。您和/或 Francescu 或许能够提供更好的见解!
【解决方案3】:

Swift 中的块称为闭包。它们的操作与块非常相似(尽管更灵活,并且可以在更多地方操作)。 Swift 中的闭包可以实现引用循环,并且可以通过闭包捕获列表来避免。

“Swift 为这个问题提供了一个优雅的解决方案,称为闭包捕获列表。但是,在学习如何使用闭包捕获列表打破强引用循环之前,了解如何导致这样的循环很有用”

摘自:Apple Inc.“Swift 编程语言”。电子书。 https://itun.es/us/jEUH0.l

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多