如何在Swift> 2.2中表示闭包中的可变参数?

Kyl*_*len 2 closures swift swift3

也许这是一个Xcode 8 beta问题,但是,在2.2之前的版本中,var允许关键字在函数签名中添加参数:

func (var stringName: String) { ... }
Run Code Online (Sandbox Code Playgroud)

此后已被弃用,以代替 inout

func (stringName: inout String) { ... }
Run Code Online (Sandbox Code Playgroud)

我已经尝试了以下操作map,尽管我没有像我预期的那样收到过时警告,但错误是segmentation fault: 11

let demoString = ["hi", "there", "world"].map { (var word) -> String in 
    let firstChar = word.remove(at: word.startIndex)
}
Run Code Online (Sandbox Code Playgroud)

一旦我尝试突变(假定是可变的)word变量,该错误就会开始。

我尝试了其他变化,例如使用 inout

let demoString = ["hi", "there", "world"].map { (word: inout String) -> String in 
    let firstChar = word.remove(at: word.startIndex)
}
Run Code Online (Sandbox Code Playgroud)

但是编译器抱怨这完全错误地更改了闭包的签名,因此无法编译。

显然,解决方法只是将变量复制到闭包内的本地变量:

let demoString = ["hi", "there", "world"].map { (word) -> String in 
    let tempWord = word
    let firstChar = tempWord.remove(at: tempWord.startIndex)
}
Run Code Online (Sandbox Code Playgroud)

但是,我有兴趣知道这是否是预期的功能以及是否有一种方法可以直接更改传递给闭包的参数?

Lig*_*ard 5

闭包可以使inout参数发生变化:

var str1 = "Pine"
var str2 = "Juniper"

let closure = { (s1: inout String, s2: inout String) -> Void in
    s1 = "Oak"
    s2 = "Chestnut"
}

closure(&str1, &str2)

print(str1, str2)
Run Code Online (Sandbox Code Playgroud)

您面临的问题是Array.map没有包含inout参数的方法签名。

我能想到的唯一解决方法是扩展Array并map自己添加方法:

extension Array {
    func map<T>(_ closure: (inout T) -> Void) -> Array<T> {
        var arr = [T]()
        for i in 0..<self.count {
            var temp : T = self[i] as! T
            closure(&temp)
            arr.append(temp)
        }
        return arr
    }
}

var hi = "hi", there = "there", world = "world"
var demoStrings = [hi, there, world]
var result = demoStrings.map { (word: inout String) in 
    word.remove(at: word.startIndex)
}

print(result) // ["i", "here", "orld"]
Run Code Online (Sandbox Code Playgroud)