代码

下标

Swift 是允许我们自定义下标的。这不仅包含了对自己写的类型进行下标自定义,也包括了对那些已经支持下标访问的类型 (没错就是ArrayDictionary ) 进行扩展。我们重点来看看向已有类型添加下标访问的情况吧,比如说Array。很容易就可以在 Swift 的定义文件 (在 Xcode 中通过 Cmd + 单击任意一个 Swift 内建的类型或者函数就可以访问到) 里,找到Array已经支持的下标访问类型:

public subscript(index: Int) -> Element
public subscript(bounds: Range<Int>) -> ArraySlice<Element>

共有两种,它们分别接受单个Int类型的序号和一个表明范围的 Range<Int> ,作为对应,返回值也分别是单个元素和一组对应输入返回的元素。

于是我们发现一个挺郁闷的问题,那就是我们很难一次性取出某几个特定位置的元素,比如在一 个数组内,我想取出 index 为 0, 2, 3 的元素的时候,现有的体系就会比较吃力。我们很可能会要去枚举数组,然后在循环里判断是否是我们想要的位置。其实这里有更好的做法,比如说可以实现一个接受数组作为下标输入的读取方法:

extension Array {
    //subscript 下标
    subscript (input:[Int]) -> ArraySlice<Element> {
        get {
            var result = ArraySlice<Element>()
            for i in input {
                assert(i < self.count, "Index out of range")
                result.append(self[i])
            }
            return result
        }

        set {
            for (index, i) in input.enumerated() {
                assert(i < self.count, "Index out of range")
                self[i] = newValue[index]
            }
        }
    }
}

这样,我们的 Array 的灵活性就大大增强了:

    var arr = [1,2,3,4,5]
    arr[[0,2,3]]  = [-1,-3,-4]
    print(arr) //[-1, 2, -3, -4, 5]

可变参数列表

在 Swift 中写一个可变参数的函数只需要在声明参数时在类型后面加上 ... 就可以了,比如声明一个接受可变参数的 Int 累加函数,当然你可以用传统的for...in 做累加,但是这里我们选择一种看起来更Swift的方式:

func sum(_ input: Int...) -> Int {
    return input.reduce(0, +)
}
print(sum(1,2,3,4,5))  //15

可变参数在参数列表中的位置在Swift中是没有限制的,因为我们会对方法的参数进行命名,所以我们可以随意地放置可变参数的位置,而不必拘泥于最后一个参数。

    func myFunc(numbers: Int..., string: String)  {
        numbers.forEach {
            for i in 0..<$0  {
                  print("\(i+1): \(string)")
            }            
        }
    }
   myFunc(numbers:1,2,3, string:"hello")
   //1: hello
   //1: hello
   //2: hello
   //1: hello
   //2: hello
   //3: hello

当然限制自然是有的,比如在同一个方法中只能有一个参数是可变的,比如可变参数都必须是同一种类型的等。对于后一个限制,当我们想要同时传入多个类型的参数时就需要做一些变通。比如 -stringwithFormat: 方法。可变参数列表的第一个元素是等待格式化的字符串,在 Swift 中这会对应一个 String 类型,而剩下的参数应该可以是对应格式化标准的任意类型。一种解决方法是使用 Any 作为参数类型,然后对接收到的数组的首个元素进行特殊处理。不过因为 Swift 提供了使用下划线 _ 来作为参数的外部标签,来使调用时不再需要加上参数名字。我们可以利用这个特性,在声明方法时就指定第一个参数为一个字符串,然后跟一个匿名的参数列表, 这样在写起来的时候就 "好像" 是所有参数都是在同一个参数列表中进行的处理,会好看很多。比如 Swift 的 `NSString` 格式化的声明就是这样处理的:

extension NSString {
      convenience init(format: NSString, _ args: CVarRrgType...)
      //...
}

调用的时候就和 Objective-C几乎是一样了,非常方便:

let name = "Tom"
let date = NSDate()
let string = NSString(format: "Hello %@. Date: %@", name, date)

results matching ""

    No results matching ""