{"action":"created","comment":{"url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/comments/25617459","id":25617459,"diff_hunk":"@@ -5,223 +5,587 @@ contributors:\n   - [\"Grant Timmerman\", \"http://github.com/grant\"]\n translators:\n   - [\"Xavier Yao\", \"http://github.com/xavieryao\"]\n+  - [\"Joey Huang\", \"http://github.com/kamidox\"]  \n lang: zh-cn\n ---\n \n-Swift 是Apple 开发的用于iOS 和OS X 开发的编程语言。Swift 于2014年Apple WWDC （全球开发者大会）中被引入，用以与Objective-C 共存，同时对错误代码更具弹性。Swift 由Xcode 6 beta 中包含的LLVM编译器编译。\n+Swift 是 Apple 开发的用于 iOS 和 OS X 开发的编程语言。Swift 于2014年 Apple WWDC （全球开发者大会）中被引入，用以与 Objective-C 共存，同时对错误代码更具弹性。Swift 由 Xcode 6 beta 中包含的 LLVM 编译器编译。\n \n-参阅：Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) ——一个完整的Swift 教程\n+Swift 的官方语言教程 [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) 可以从 iBooks 免费下载.\n+\n+亦可参阅：Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html) ——一个完整的Swift 教程\n \n ```swift\n-//\n-// 基础\n+// 导入外部模块\n+import UIKit\n+\n+// \n+// MARK: 基础\n //\n \n+// XCODE 支持给注释代码作标记，这些标记会列在 XCODE 的跳转栏里，支持的标记为\n+// MARK: 普通标记\n+// TODO: TODO 标记\n+// FIXME: FIXME 标记\n+\n println(\"Hello, world\")\n+\n+// 变量 (var) 的值设置后可以随意改变\n+// 常量 (let) 的值设置后不能改变\n var myVariable = 42\n+let øπΩ = \"value\" // 可以支持 unicode 变量名 \n+let π = 3.1415926\n let myConstant = 3.1415926\n-let explicitDouble: Double = 70\n-let label = \"some text \" + String(myVariable)     // Casting\n-let piText = \"Pi = \\(myConstant)\"                 // String interpolation\n-var optionalString: String? = \"optional\"          // Can be nil\n-optionalString = nil\n+let explicitDouble: Double = 70   // 明确指定变量类型为 Double ，否则编译器将自动推断变量类型\n+let weak = \"keyword\"; let override = \"another keyword\" // 语句之间可以用分号隔开，语句未尾不需要分号\n+let intValue = 0007 // 7\n+let largeIntValue = 77_000 // 77000\n+let label = \"some text \" + String(myVariable) // 类型转换\n+let piText = \"Pi = \\(π), Pi 2 = \\(π * 2)\" // 格式化字符串\n+\n+// 条件编译\n+// 使用 -D 定义编译开关\n+#if false\n+    println(\"Not printed\")\n+    let buildValue = 3\n+#else\n+    let buildValue = 7\n+#endif\n+println(\"Build value: \\(buildValue)\") // Build value: 7\n+\n+/*\n+    Optionals 是 Swift 的新特性，它允许你存储两种状态的值给 Optional 变量：有效值或 None\n+    \n+    Swift 要求所有的 Optinal 属性都必须有明确的值，如果为空，则必须明确设定为 nil\n+\n+    Optional<T> 是个枚举类型\n+*/\n+var someOptionalString: String? = \"optional\" // 可以是 nil\n+// 下面的语句和上面完全等价，上面的写法更推荐，因为它更简洁，问号 (?) 是 Swift 提供的语法糖\n+var someOptionalString2: Optional<String> = \"optional\"\n+\n+if someOptionalString != nil {\n+    // 变量不为空\n+    if someOptionalString!.hasPrefix(\"opt\") {\n+        println(\"has the prefix\")\n+    }\n+    \n+    let empty = someOptionalString?.isEmpty\n+}\n+someOptionalString = nil\n+\n+// 显式解包 optional 变量\n+var unwrappedString: String! = \"Value is expected.\"\n+// 下面语句和上面完全等价，感叹号 (!) 是个后缀运算符，这也是个语法糖\n+var unwrappedString2: ImplicitlyUnwrappedOptional<String> = \"Value is expected.\"\n+\n+if let someOptionalStringConstant = someOptionalString {\n+    // 由于变量 someOptinalString 有值，不为空，所以 if 条件为真\n+    if !someOptionalStringConstant.hasPrefix(\"ok\") {\n+        // does not have the prefix\n+    }\n+}\n+\n+// Swift 支持可保存任何数据类型的变量\n+// AnyObject == id\n+// 和 Objective-C `id` 不一样, AnyObject 可以保存任何类型的值 (Class, Int, struct, 等)\n+var anyObjectVar: AnyObject = 7\n+anyObjectVar = \"Changed value to a string, not good practice, but possible.\"\n+\n+/*\n+    这里是注释\n+    \n+    /*\n+        支持嵌套的注释\n+    */\n+*/\n \n \n //\n-// 数组与字典（关联数组）\n+// Mark: 数组与字典（关联数组）\n //\n \n-// 数组\n+/*\n+    Array 和 Dictionary 是结构体，不是类，他们作为函数参数时，是用值传递而不是指针传递。\n+    可以用 `var` 和 `let` 来定义变量和常量。\n+*/\n+\n+// Array\n var shoppingList = [\"catfish\", \"water\", \"lemons\"]\n shoppingList[1] = \"bottle of water\"\n-let emptyArray = String[]()\n+let emptyArray = [String]() // 使用 let 定义常量，此时 emptyArray 数组不能添加或删除内容\n+let emptyArray2 = Array<String>() // 与上一语句等价，上一语句更常用\n+var emptyMutableArray = [String]() // 使用 var 定义变量，可以向 emptyMutableArray 添加数组元素\n \n // 字典\n var occupations = [\n-  \"Malcolm\": \"Captain\",\n-  \"kaylee\": \"Mechanic\"\n+    \"Malcolm\": \"Captain\",\n+    \"kaylee\": \"Mechanic\"\n ]\n-occupations[\"Jayne\"] = \"Public Relations\"\n-let emptyDictionary = Dictionary<String, Float>()\n+occupations[\"Jayne\"] = \"Public Relations\"   // 修改字典，如果 key 不存在，自动添加一个字典元素\n+let emptyDictionary = [String: Float]() // 使用 let 定义字典常量，字典常量不能修改里面的值\n+let emptyDictionary2 = Dictionary<String, Float>() // 与上一语句类型等价，上一语句更常用\n+var emptyMutableDictionary = [String: Float]() // 使用 var 定义字典变量\n \n \n //\n-// 控制流\n+// MARK: 控制流\n //\n \n-// 用于数组的for 循环\n+// 数组的 for 循环\n let myArray = [1, 1, 2, 3, 5]\n for value in myArray {\n-  if value == 1 {\n-    println(\"One!\")\n-  } else {\n-    println(\"Not one!\")\n-  }\n+    if value == 1 {\n+        println(\"One!\")\n+    } else {\n+        println(\"Not one!\")\n+    }\n }\n \n-// 用于字典的for 循环\n+// 字典的 for 循环\n+var dict = [\"one\": 1, \"two\": 2]\n for (key, value) in dict {\n-  println(\"\\(key): \\(value)\")\n+    println(\"\\(key): \\(value)\")\n }\n \n-// 用于区间的for 循环\n-for i in -1...1 { // [-1, 0, 1]\n-  println(i)\n+// 区间的 loop 循环：其中 `...` 表示闭环区间，即[-1, 3]；`..<` 表示半开闭区间，即[-1,3)\n+for i in -1...shoppingList.count {\n+    println(i)\n }\n-// 使用 .. 表示的区间不包含最后一个元素 [-1,0,1)\n+shoppingList[1...2] = [\"steak\", \"peacons\"]\n+// 可以使用 `..<` 来去掉最后一个元素\n \n // while 循环\n var i = 1\n while i < 1000 {\n-  i *= 2\n+    i *= 2\n }\n \n // do-while 循环\n do {\n-  println(\"hello\")\n+    println(\"hello\")\n } while 1 == 2\n \n-// Switch\n+// Switch 语句\n+// Swift 里的 Switch 语句功能异常强大，结合枚举类型，可以实现非常简洁的代码，可以把 switch 语句想象成 `if` 的语法糖\n+// 它支持字符串，类实例或原生数据类型 (Int, Double, etc)\n let vegetable = \"red pepper\"\n switch vegetable {\n case \"celery\":\n-  let vegetableComment = \"Add some raisins and make ants on a log.\"\n+    let vegetableComment = \"Add some raisins and make ants on a log.\"\n case \"cucumber\", \"watercress\":\n-  let vegetableComment = \"That would make a good tea sandwich.\"\n-case let x where x.hasSuffix(\"pepper\"):\n-  let vegetableComment = \"Is it a spicy \\(x)?\"\n-default: // 必须 (为了覆盖所有可能的输入)\n-  let vegetableComment = \"Everything tastes good in soup.\"\n+    let vegetableComment = \"That would make a good tea sandwich.\"\n+case let localScopeValue where localScopeValue.hasSuffix(\"pepper\"):\n+    let vegetableComment = \"Is it a spicy \\(localScopeValue)?\"\n+default: // 在 Swift 里，switch 语句的 case 必须处理所有可能的情况，如果 case 无法全部处理，则必须包含 default语句 \n+    let vegetableComment = \"Everything tastes good in soup.\"\n }\n \n \n //\n-// 函数\n+// MARK: 函数\n //\n \n-// 函数是一等类型，这意味着可以在函数中构建函数\n-// 并且可以被传递\n+// 函数是一个 first-class 类型，他们可以嵌套，可以作为函数参数传递\n \n-// 函数\n+// 函数文档可使用 reStructedText 格式直接写在函数的头部\n+/**\n+    A greet operation\n+\n+    - A bullet in docs\n+    - Another bullet in the docs\n+\n+    :param: name A name\n+    :param: day A day\n+    :returns: A string containing the name and day value.\n+*/\n func greet(name: String, day: String) -> String {\n-  return \"Hello \\(name), today is \\(day).\"\n+    return \"Hello \\(name), today is \\(day).\"\n }\n greet(\"Bob\", \"Tuesday\")\n \n-// 使用多元数组返回多返回值的函数\n-func getGasPrices() -> (Double, Double, Double) {\n-  return (3.59, 3.69, 3.79)\n+// 函数参数前带 `#` 表示外部参数名和内部参数名使用同一个名称。\n+// 第二个参数表示外部参数名使用 `externalParamName` ，内部参数名使用 `localParamName`\n+func greet2(#requiredName: String, externalParamName localParamName: String) -> String {\n+    return \"Hello \\(requiredName), the day is \\(localParamName)\"\n }\n+greet2(requiredName:\"John\", externalParamName: \"Sunday\")    // 调用时，使用命名参数来指定参数的值\n \n-// 不定参数\n-func setup(numbers: Int...) {}\n+// 函数可以通过元组 (tuple) 返回多个值\n+func getGasPrices() -> (Double, Double, Double) {\n+    return (3.59, 3.69, 3.79)\n+}\n+let pricesTuple = getGasPrices()\n+let price = pricesTuple.2 // 3.79\n+// 通过下划线 (_) 来忽略不关心的值\n+let (_, price1, _) = pricesTuple // price1 == 3.69\n+println(price1 == pricesTuple.1) // true\n+println(\"Gas price: \\(price)\")\n+\n+// 可变参数\n+func setup(numbers: Int...) {\n+    // 可变参数是个数组\n+    let number = numbers[0]\n+    let argCount = numbers.count\n+}\n \n-// 传递、返回函数\n+// 函数变量以及函数作为返回值返回\n func makeIncrementer() -> (Int -> Int) {\n-  func addOne(number: Int) -> Int {\n-    return 1 + number\n-  }\n-  return addOne\n+    func addOne(number: Int) -> Int {\n+        return 1 + number\n+    }\n+    return addOne\n }\n var increment = makeIncrementer()\n increment(7)\n \n+// 强制进行指针传递 (引用传递)，使用 `inout` 关键字修饰函数参数\n+func swapTwoInts(inout a: Int, inout b: Int) {\n+    let tempA = a\n+    a = b\n+    b = tempA\n+}\n+var someIntA = 7\n+var someIntB = 3\n+swapTwoInts(&someIntA, &someIntB)\n+println(someIntB) // 7\n+\n \n //\n-// 闭包\n+// MARK: 闭包\n //\n+var numbers = [1, 2, 6]\n \n-// 函数是特殊的闭包({})\n+// 函数是闭包的一个特例\n \n-// 闭包示例.\n-// `->` 分隔参数和返回类型\n-// `in` 分隔闭包头和闭包体\n+// 闭包实例\n+// `->` 分隔了闭包的参数和返回值\n+// `in` 分隔了闭包头 (包括参数及返回值) 和闭包体\n+// 下面例子中，`map` 的参数是一个函数类型，它的功能是把数组里的元素作为参数，逐个调用 `map` 参数传递进来的函数。\n numbers.map({\n-  (number: Int) -> Int in\n-  let result = 3 * number\n-  return result\n-  })\n+    (number: Int) -> Int in\n+    let result = 3 * number\n+    return result\n+})\n \n-// 当类型已知时，可以这样做：\n-var numbers = [1, 2, 6]\n+// 当闭包的参数类型和返回值都是己知的情况下，且只有一个语句作为其返回值时，我们可以简化闭包的写法\n numbers = numbers.map({ number in 3 * number })\n+// 我们也可以使用 $0, $1 来指代第 1 个，第 2 个参数，上面的语句最终可简写为如下形式\n+// numbers = numbers.map({ $0 * 3 })\n+\n+print(numbers) // [3, 6, 18]\n+\n+// 简洁的闭包\n+numbers = sorted(numbers) { $0 > $1 }\n+// 函数的最后一个参数可以放在括号之外，上面的语句是这个语句的简写形式\n+// numbers = sorted(numbers, { $0 > $1 })\n+\n+print(numbers) // [18, 6, 3]\n+\n+// 超级简洁的闭包，因为 `<` 是个操作符函数\n+numbers = sorted(numbers, < )\n+\n print(numbers) // [3, 6, 18]\n \n \n //\n-// 类\n+// MARK: 结构体\n //\n \n-// 类的全部方法和属性都是public 的\n-// 如果你在一个数据结构中只需储存数据，\n-// 应使用 `struct`\n+// 结构体和类非常类似，可以有属性和方法\n \n-// 集成自`Shape` 类的简单的类`Square\n-class Rect: Shape {\n-  var sideLength: Int = 1\n-\n-  // Custom getter and setter property\n-  var perimeter: Int {\n-    get {\n-      return 4 * sideLength\n-    }\n-    set {\n-      sideLength = newValue / 4\n+struct NamesTable {\n+    let names = [String]()\n+    \n+    // 自定义下标运算符\n+    subscript(index: Int) -> String {\n+        return names[index]\n     }\n-  }\n+}\n+\n+// 结构体有一个自动生成的隐含的命名构造函数\n+let namesTable = NamesTable(names: [\"Me\", \"Them\"])\n+let name = namesTable[1]\n+println(\"Name is \\(name)\") // Name is Them\n+\n+//\n+// MARK: 类\n+//\n \n-  init(sideLength: Int) {\n-    super.init()\n-    self.sideLength = sideLength\n-  }\n+// 类和结构体的有三个访问控制级别，他们分别是 internal (默认), public, private\n+// internal: 模块内部可以访问\n+// public: 其他模块可以访问\n+// private: 只有定义这个类或结构体的源文件才能访问\n \n-  func shrink() {\n-    if sideLength > 0 {\n-      --sideLength\n+public class Shape {\n+    public func getArea() -> Int {\n+        return 0;\n+    }\n+}\n+\n+// 类的所有方法和属性都是 public 的\n+// 如果你只是需要把数据保存在一个结构化的实例里面，应该用结构体\n+\n+internal class Rect: Shape {\n+    // 值属性 (Stored properties)\n+    var sideLength: Int = 1\n+    \n+    // 计算属性 (Computed properties)\n+    private var perimeter: Int {\n+        get {\n+            return 4 * sideLength\n+        }\n+        set {\n+            // `newValue` 是个隐含的变量，它表示将要设置进来的新值\n+            sideLength = newValue / 4\n+        }\n+    }\n+    \n+    // 延时加载的属性，只有这个属性第一次被引用时才进行初始化，而不是定义时就初始化\n+    // subShape 值为 nil ，直到 subShape 第一次被引用时才初始化为一个 Rect 实例\n+    lazy var subShape = Rect(sideLength: 4)\n+    \n+    // 监控属性值的变化。\n+    // 当我们需要在属性值改变时做一些事情，可以使用 `willSet` 和 `didSet` 来设置监控函数\n+    // `willSet`: 值改变之前被调用\n+    // `didSet`: 值改变之后被调用\n+    var identifier: String = \"defaultID\" {\n+        // `willSet` 的参数是即将设置的新值，参数名可以指定，如果没有指定，就是 `newValue`\n+        willSet(someIdentifier) {\n+            println(someIdentifier)\n+        }\n+        // `didSet` 的参数是已经被覆盖掉的旧的值，参数名也可以指定，如果没有指定，就是 `oldValue`\n+        didSet {\n+            println(oldValue)\n+        }\n+    }\n+    \n+    // 命名构造函数 (designated inits)，它必须初始化所有的成员变量，\n+    // 然后调用父类的命名构造函数继续初始化父类的所有变量。\n+    init(sideLength: Int) {\n+        self.sideLength = sideLength\n+        // 必须显式地在构造函数最后调用父类的构造函数 super.init\n+        super.init()\n+    }\n+    \n+    func shrink() {\n+        if sideLength > 0 {\n+            --sideLength\n+        }\n     }\n-  }\n+    \n+    // 函数重载使用 override 关键字\n+    override func getArea() -> Int {\n+        return sideLength * sideLength\n+    }\n+}\n \n-  override func getArea() -> Int {\n-    return sideLength * sideLength\n-  }\n+// 类 `Square` 从 `Rect` 继承\n+class Square: Rect {\n+    // 便捷构造函数 (convenience inits) 是调用自己的命名构造函数 (designated inits) 的构造函数\n+    // Square 自动继承了父类的命名构造函数\n+    convenience init() {\n+        self.init(sideLength: 5)\n+    }\n+    // 关于构造函数的继承，有以下几个规则：\n+    // 1. 如果你没有实现任何命名构造函数，那么你就继承了父类的所有命名构造函数\n+    // 2. 如果你重载了父类的所有命名构造函数，那么你就自动继承了所有的父类快捷构造函数\n+    // 3. 如果你没有实现任何构造函数，那么你继承了父类的所有构造函数，包括命名构造函数和便捷构造函数\n }\n-var mySquare = new Square(sideLength: 5)\n-print(mySquare.getArea()) // 25\n+\n+var mySquare = Square()\n+println(mySquare.getArea()) // 25\n mySquare.shrink()\n-print(mySquare.sideLength) // 4\n+println(mySquare.sideLength) // 4\n+\n+// 类型转换\n+let aShape = mySquare as Shape\n+\n+// 使用三个等号来比较是不是同一个实例\n+if mySquare === aShape {\n+    println(\"Yep, it's mySquare\")\n+}\n+\n+class Circle: Shape {\n+    var radius: Int\n+    override func getArea() -> Int {\n+        return 3 * radius * radius\n+    }\n+    \n+    // optional 构造函数，可能会返回 nil\n+    init?(radius: Int) {\n+        self.radius = radius\n+        super.init()\n+        \n+        if radius <= 0 {\n+            return nil\n+        }\n+    }\n+}\n \n-// 如果你不需要自定义getter 和setter,\n-// 但仍希望在获取或设置一个属性之前或之后运行\n-// 一些代码，你可以使用`willSet` 和 `didSet`\n+// 根据 Swift 类型推断，myCircle 是 Optional<Circle> 类型的变量\n+var myCircle = Circle(radius: 1)\n+println(myCircle?.getArea())    // Optional(3)\n+println(myCircle!.getArea())    // 3\n+var myEmptyCircle = Circle(radius: -1)\n+println(myEmptyCircle?.getArea())    // \"nil\"\n+if let circle = myEmptyCircle {\n+    // 此语句不会输出，因为 myEmptyCircle 变量值为 nil\n+    println(\"circle is not nil\")\n+}\n \n \n //\n-// 枚举类型\n+// MARK: 枚举\n //\n \n-// 枚举类型可以是某种指定的类型，抑或自成一种类型\n-// 像类一样，枚举类型可以包含方法\n+// 枚举可以像类一样，拥有方法\n \n enum Suit {\n-  case Spades, Hearts, Diamonds, Clubs\n-  func getIcon() -> String {\n-    switch self {\n-    case .Spades: return \"♤\"\n-    case .Hearts: return \"♡\"\n-    case .Diamonds: return \"♢\"\n-    case .Clubs: return \"♧\"\n+    case Spades, Hearts, Diamonds, Clubs\n+    func getIcon() -> String {\n+        switch self {\n+        case .Spades: return \"♤\"\n+        case .Hearts: return \"♡\"\n+        case .Diamonds: return \"♢\"\n+        case .Clubs: return \"♧\"\n+        }\n     }\n-  }\n }\n \n+// 当变量类型明确指定为某个枚举类型时，赋值时可以省略枚举类型\n+var suitValue: Suit = .Hearts\n+\n+// 非整型的枚举类型需要在定义时赋值\n+enum BookName: String {\n+    case John = \"John\"\n+    case Luke = \"Luke\"\n+}\n+println(\"Name: \\(BookName.John.rawValue)\")\n+\n+// 与特定数据类型关联的枚举\n+enum Furniture {\n+    // 和 Int 型数据关联的枚举记录\n+    case Desk(height: Int)\n+    // 和 String, Int 关联的枚举记录\n+    case Chair(brand: String, height: Int)\n+    \n+    func description() -> String {\n+        switch self {\n+        case .Desk(let height):\n+            return \"Desk with \\(height) cm\"\n+        case .Chair(let brand, let height):\n+            return \"Chair of \\(brand) with \\(height) cm\"\n+        }\n+    }\n+}\n+\n+var desk: Furniture = .Desk(height: 80)\n+println(desk.description())     // \"Desk with 80 cm\"\n+var chair = Furniture.Chair(brand: \"Foo\", height: 40)\n+println(chair.description())    // \"Chair of Foo with 40 cm\"\n+\n \n //\n-// 其它\n+// MARK: 协议\n+// 与 Java 的 interface 类似\n //\n \n-// `协议(protocol)`: 与Java 的接口(Interface) 类似.\n-// `扩展(extension)`: 为现有类型添加额外特性\n-// 泛型: 与Java 相似。使用`where` 关键字指定\n-//   泛型的要求.\n+// 协议可以让遵循同一协议的类型实例拥有相同的属性，方法，类方法，操作符或下标运算符等\n+// 下面代码定义一个协议，这个协议包含一个名为 enabled 的计算属性且包含 buildShape 方法\n+protocol ShapeGenerator {\n+    var enabled: Bool { get set }\n+    func buildShape() -> Shape\n+}\n+\n+// 协议声明时可以添加 @objc 前缀，添加 @objc 前缀后，\n+// 可以使用 is, as, as? 等来检查协议兼容性\n+// 需要注意，添加 @objc 前缀后，协议就只能被类来实现，\n+// 结构体和枚举不能实现加了 @objc 的前缀\n+// 只有添加了 @objc 前缀的协议才能声明 optional 方法\n+// 一个类实现一个带 optional 方法的协议时，可以实现或不实现这个方法\n+// optional 方法可以使用 optional 规则来调用\n+@objc protocol TransformShape {\n+    optional func reshaped()\n+    optional func canReshape() -> Bool\n+}\n+\n+class MyShape: Rect {\n+    var delegate: TransformShape?\n+    \n+    func grow() {\n+        sideLength += 2\n+\n+        // 在 optional 属性，方法或下标运算符后面加一个问号，可以优雅地忽略 nil 值，返回 nil。\n+        // 这样就不会引起运行时错误 (runtime error)\n+        if let allow = self.delegate?.canReshape?() {\n+            // 注意语句中的问号\n+            self.delegate?.reshaped?()\n+        }\n+    }\n+}\n+\n+\n+//\n+// MARK: 其它\n+//\n+\n+// 扩展: 给一个已经存在的数据类型添加功能\n+\n+// 给 Square 类添加 `Printable` 协议的实现，现在其支持 `Printable` 协议\n+extension Square: Printable {\n+    var description: String {\n+        return \"Area: \\(self.getArea()) - ID: \\(self.identifier)\"\n+    }\n+}\n+\n+println(\"Square: \\(mySquare)\")  // Area: 16 - ID: defaultID\n+\n+// 也可以给系统内置类型添加功能支持\n+extension Int {\n+    var customProperty: String {\n+        return \"This is \\(self)\"\n+    }\n+    \n+    func multiplyBy(num: Int) -> Int {\n+        return num * self\n+    }\n+}\n+\n+println(7.customProperty) // \"This is 7\"\n+println(14.multiplyBy(3)) // 42\n+\n+// 泛型: 和 Java 及 C# 的泛型类似，使用 `where` 关键字来限制类型。\n+// 如果只有一个类型限制，可以省略 `where` 关键字\n+func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {\n+    for (index, value) in enumerate(array) {\n+        if value == valueToFind {\n+            return index\n+        }\n+    }\n+    return nil\n+}\n+let foundAtIndex = findIndex([1, 2, 3, 4], 3)\n+println(foundAtIndex == 2) // true\n+\n+// 自定义运算符:\n+// 自定义运算符可以以下面的字符打头:\n+//      / = - + * % < > ! & | ^ . ~\n+// 甚至是 Unicode 的数学运算符等\n+prefix operator !!! {}\n+\n+// 定义一个前缀运算符，使矩形的边长放大倍","path":"zh-cn/swift-cn.html.markdown","position":686,"original_position":686,"commit_id":"d05baf5bd02cf6c7270e35ee79964764848d8f1b","original_commit_id":"d05baf5bd02cf6c7270e35ee79964764848d8f1b","user":{"login":"geoffliu","id":1714648,"avatar_url":"https://avatars.githubusercontent.com/u/1714648?v=3","gravatar_id":"","url":"https://api.github.com/users/geoffliu","html_url":"https://github.com/geoffliu","followers_url":"https://api.github.com/users/geoffliu/followers","following_url":"https://api.github.com/users/geoffliu/following{/other_user}","gists_url":"https://api.github.com/users/geoffliu/gists{/gist_id}","starred_url":"https://api.github.com/users/geoffliu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/geoffliu/subscriptions","organizations_url":"https://api.github.com/users/geoffliu/orgs","repos_url":"https://api.github.com/users/geoffliu/repos","events_url":"https://api.github.com/users/geoffliu/events{/privacy}","received_events_url":"https://api.github.com/users/geoffliu/received_events","type":"User","site_admin":false},"body":"Still not quite there. :)","created_at":"2015-03-02T17:27:38Z","updated_at":"2015-03-02T17:27:38Z","html_url":"https://github.com/adambard/learnxinyminutes-docs/pull/978#discussion_r25617459","pull_request_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/978","_links":{"self":{"href":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/comments/25617459"},"html":{"href":"https://github.com/adambard/learnxinyminutes-docs/pull/978#discussion_r25617459"},"pull_request":{"href":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/978"}}},"pull_request":{"url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/978","id":30224397,"html_url":"https://github.com/adambard/learnxinyminutes-docs/pull/978","diff_url":"https://github.com/adambard/learnxinyminutes-docs/pull/978.diff","patch_url":"https://github.com/adambard/learnxinyminutes-docs/pull/978.patch","issue_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/issues/978","number":978,"state":"open","locked":false,"title":"Add two swift feature and make a full translation for swift to zh-cn","user":{"login":"kamidox","id":6936127,"avatar_url":"https://avatars.githubusercontent.com/u/6936127?v=3","gravatar_id":"","url":"https://api.github.com/users/kamidox","html_url":"https://github.com/kamidox","followers_url":"https://api.github.com/users/kamidox/followers","following_url":"https://api.github.com/users/kamidox/following{/other_user}","gists_url":"https://api.github.com/users/kamidox/gists{/gist_id}","starred_url":"https://api.github.com/users/kamidox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kamidox/subscriptions","organizations_url":"https://api.github.com/users/kamidox/orgs","repos_url":"https://api.github.com/users/kamidox/repos","events_url":"https://api.github.com/users/kamidox/events{/privacy}","received_events_url":"https://api.github.com/users/kamidox/received_events","type":"User","site_admin":false},"body":"### Add two swift feature:\r\n\r\n* Optional init\r\n* Enum with associated values\r\n\r\n### Make full translation for swift to zh-cn","created_at":"2015-02-28T13:31:49Z","updated_at":"2015-03-02T17:27:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"48a634b1454fafc03ef5c582790a9a62d09ded61","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/978/commits","review_comments_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/978/comments","review_comment_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/issues/978/comments","statuses_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/statuses/d05baf5bd02cf6c7270e35ee79964764848d8f1b","head":{"label":"kamidox:master","ref":"master","sha":"d05baf5bd02cf6c7270e35ee79964764848d8f1b","user":{"login":"kamidox","id":6936127,"avatar_url":"https://avatars.githubusercontent.com/u/6936127?v=3","gravatar_id":"","url":"https://api.github.com/users/kamidox","html_url":"https://github.com/kamidox","followers_url":"https://api.github.com/users/kamidox/followers","following_url":"https://api.github.com/users/kamidox/following{/other_user}","gists_url":"https://api.github.com/users/kamidox/gists{/gist_id}","starred_url":"https://api.github.com/users/kamidox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kamidox/subscriptions","organizations_url":"https://api.github.com/users/kamidox/orgs","repos_url":"https://api.github.com/users/kamidox/repos","events_url":"https://api.github.com/users/kamidox/events{/privacy}","received_events_url":"https://api.github.com/users/kamidox/received_events","type":"User","site_admin":false},"repo":{"id":31446951,"name":"learnxinyminutes-docs","full_name":"kamidox/learnxinyminutes-docs","owner":{"login":"kamidox","id":6936127,"avatar_url":"https://avatars.githubusercontent.com/u/6936127?v=3","gravatar_id":"","url":"https://api.github.com/users/kamidox","html_url":"https://github.com/kamidox","followers_url":"https://api.github.com/users/kamidox/followers","following_url":"https://api.github.com/users/kamidox/following{/other_user}","gists_url":"https://api.github.com/users/kamidox/gists{/gist_id}","starred_url":"https://api.github.com/users/kamidox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kamidox/subscriptions","organizations_url":"https://api.github.com/users/kamidox/orgs","repos_url":"https://api.github.com/users/kamidox/repos","events_url":"https://api.github.com/users/kamidox/events{/privacy}","received_events_url":"https://api.github.com/users/kamidox/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/kamidox/learnxinyminutes-docs","description":"Code documentation written as code! How novel and totally my idea!","fork":true,"url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs","forks_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/forks","keys_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/teams","hooks_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/hooks","issue_events_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/issues/events{/number}","events_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/events","assignees_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/assignees{/user}","branches_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/branches{/branch}","tags_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/tags","blobs_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/statuses/{sha}","languages_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/languages","stargazers_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/stargazers","contributors_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/contributors","subscribers_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/subscribers","subscription_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/subscription","commits_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/contents/{+path}","compare_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/merges","archive_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/downloads","issues_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/issues{/number}","pulls_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/pulls{/number}","milestones_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/milestones{/number}","notifications_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/labels{/name}","releases_url":"https://api.github.com/repos/kamidox/learnxinyminutes-docs/releases{/id}","created_at":"2015-02-28T01:40:43Z","updated_at":"2015-03-02T17:04:31Z","pushed_at":"2015-03-02T17:04:31Z","git_url":"git://github.com/kamidox/learnxinyminutes-docs.git","ssh_url":"git@github.com:kamidox/learnxinyminutes-docs.git","clone_url":"https://github.com/kamidox/learnxinyminutes-docs.git","svn_url":"https://github.com/kamidox/learnxinyminutes-docs","homepage":"http://learnxinyminutes.com/","size":5185,"stargazers_count":0,"watchers_count":0,"language":"HTML","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"adambard:master","ref":"master","sha":"a8592af4e8a5a2381dd55344b6af8de35df673d1","user":{"login":"adambard","id":515720,"avatar_url":"https://avatars.githubusercontent.com/u/515720?v=3","gravatar_id":"","url":"https://api.github.com/users/adambard","html_url":"https://github.com/adambard","followers_url":"https://api.github.com/users/adambard/followers","following_url":"https://api.github.com/users/adambard/following{/other_user}","gists_url":"https://api.github.com/users/adambard/gists{/gist_id}","starred_url":"https://api.github.com/users/adambard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adambard/subscriptions","organizations_url":"https://api.github.com/users/adambard/orgs","repos_url":"https://api.github.com/users/adambard/repos","events_url":"https://api.github.com/users/adambard/events{/privacy}","received_events_url":"https://api.github.com/users/adambard/received_events","type":"User","site_admin":false},"repo":{"id":10974951,"name":"learnxinyminutes-docs","full_name":"adambard/learnxinyminutes-docs","owner":{"login":"adambard","id":515720,"avatar_url":"https://avatars.githubusercontent.com/u/515720?v=3","gravatar_id":"","url":"https://api.github.com/users/adambard","html_url":"https://github.com/adambard","followers_url":"https://api.github.com/users/adambard/followers","following_url":"https://api.github.com/users/adambard/following{/other_user}","gists_url":"https://api.github.com/users/adambard/gists{/gist_id}","starred_url":"https://api.github.com/users/adambard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adambard/subscriptions","organizations_url":"https://api.github.com/users/adambard/orgs","repos_url":"https://api.github.com/users/adambard/repos","events_url":"https://api.github.com/users/adambard/events{/privacy}","received_events_url":"https://api.github.com/users/adambard/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/adambard/learnxinyminutes-docs","description":"Code documentation written as code! How novel and totally my idea!","fork":false,"url":"https://api.github.com/repos/adambard/learnxinyminutes-docs","forks_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/forks","keys_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/teams","hooks_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/hooks","issue_events_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/issues/events{/number}","events_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/events","assignees_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/assignees{/user}","branches_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/branches{/branch}","tags_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/tags","blobs_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/git/refs{/sha}","trees_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/statuses/{sha}","languages_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/languages","stargazers_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/stargazers","contributors_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/contributors","subscribers_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/subscribers","subscription_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/subscription","commits_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/commits{/sha}","git_commits_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/git/commits{/sha}","comments_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/comments{/number}","issue_comment_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/issues/comments{/number}","contents_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/contents/{+path}","compare_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/merges","archive_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/downloads","issues_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/issues{/number}","pulls_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls{/number}","milestones_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/milestones{/number}","notifications_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/labels{/name}","releases_url":"https://api.github.com/repos/adambard/learnxinyminutes-docs/releases{/id}","created_at":"2013-06-26T17:58:34Z","updated_at":"2015-03-02T15:33:41Z","pushed_at":"2015-03-02T08:22:04Z","git_url":"git://github.com/adambard/learnxinyminutes-docs.git","ssh_url":"git@github.com:adambard/learnxinyminutes-docs.git","clone_url":"https://github.com/adambard/learnxinyminutes-docs.git","svn_url":"https://github.com/adambard/learnxinyminutes-docs","homepage":"http://learnxinyminutes.com/","size":9897,"stargazers_count":2179,"watchers_count":2179,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":718,"mirror_url":null,"open_issues_count":34,"forks":718,"open_issues":34,"watchers":2179,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/978"},"html":{"href":"https://github.com/adambard/learnxinyminutes-docs/pull/978"},"issue":{"href":"https://api.github.com/repos/adambard/learnxinyminutes-docs/issues/978"},"comments":{"href":"https://api.github.com/repos/adambard/learnxinyminutes-docs/issues/978/comments"},"review_comments":{"href":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/978/comments"},"review_comment":{"href":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/adambard/learnxinyminutes-docs/pulls/978/commits"},"statuses":{"href":"https://api.github.com/repos/adambard/learnxinyminutes-docs/statuses/d05baf5bd02cf6c7270e35ee79964764848d8f1b"}}}}