apple文档 swift

2018-04-13 00:10:25 weixin_40840896 阅读数 3135

该文章翻译自apple官方文档:The Swift Programming Language(Swift 4.1)

A Swift Tour  -- 一个Swift 旅行

Tradition suggests that the first program in a new language should print the words “Hello, world!” on the screen. In Swift, this can be done in a single line:
print("Hello, world!")

译:传统认为,一种新语言的第一个程序应该打印“Hello world!”在屏幕上。 用Swift,它可以用简单的一行代码搞定。

If you have written code in C or Objective-C, this syntax looks familiar to you—in Swift, this line of code is a complete program. You don’t need to import a separate library for functionality like input/output or string handling. Code written at global scope is used as the entry point for the program, so you don’t need a main()function. You also don’t need to write semicolons at the end of every statement.

译:如果你用C或 OC写代码,这语法看起来很熟悉 —— 在 Swift里,这行代码就是一个完整的程序。你不需要为输入/输出或字符串处理之类的功能导入单独的库。在全局范围内编写的代码用作程序的入口点,所以你不需要一个主函数功能。你也不需要在每一个语句的末尾写分号。

This tour gives you enough information to start writing code in Swift by showing you how to accomplish a variety of programming tasks. Don’t worry if you don’t understand something—everything introduced in this tour is explained in detail in the rest of this book.

译:这个旅行给你足够的信息可以开始用Swift写代码,它展示给你怎样完成各项编程任务。不要担心如果你不理解一些部分 ——这个旅行里每一项在本书的其他部分都有详细的介绍。

NOTE

For the best experience, open this chapter as a playground in Xcode. Playgrounds allow you to edit the code listings and see the result immediately.

Download Playground

提示:

为了一个更好的体验,在Xcode的里用一个playground打开本章内容,Playgrounds 允许你编辑代码列表并且立马看结果。

 

 

Simple Values -- 简单的值

Use let to make a constant and var to make a variable. The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once. This means you can use constants to name a value that you determine once but use in many places.

  1. var myVariable = 42
  2. myVariable = 50
  3. let myConstant = 42

译:用 let 表示常量,用 var 表示变量,这个常量的值在编译时不需要知道,但是你必须马上赋给它一个确切的值。这意味着你可以用常量去为一个你定义的值命名,这个值可以在多处使用。

A constant or variable must have the same type as the value you want to assign to it. However, you don’t always have to write the type explicitly. Providing a value when you create a constant or variable lets the compiler infer its type. In the example above, the compiler infers that myVariable is an integer because its initial value is an integer.
If the initial value doesn’t provide enough information (or if there is no initial value), specify the type by writing it after the variable, separated by a colon.

  1. let implicitInteger = 70
  2. let implicitDouble = 70.0
  3. let explicitDouble: Double = 70

EXPERIMENT

Create a constant with an explicit type of Float and a value of 4.
 

译:常量或变量必须与你赋给它的值有同样的类型.然而,然而你并不必须写出具体的类型.当你创建一个常量或变量时提供一个值可以让编译器判断它的类型,在上面的例子中,编译器判断 myVarible 是一个整数因为它的初始化值是一个整数.

如果这个初始化的值没有提供足够的信息(或者如果没有初始化的值),可以通过在变量后面写下指定的类型,用冒号隔开

 尝试1
创建一个有明确类型为Float的常量,值为4

 

Values are never implicitly converted to another type. If you need to convert a value to a different type, explicitly make an instance of the desired type.

  1. let label = "The width is "
  2. let width = 94
  3. let widthLabel = label + String(width)

EXPERIMENT

Try removing the conversion to String from the last line. What error do you get?

译:这个值是绝不能换成其他类型的,如果你需要将值转换为不同的类型,明确地做一个期望类型的实例
实验
试着从最后一行移除String转换,你得到什么错误?

 

There’s an even simpler way to include values in strings: Write the value in parentheses, and write a backslash (\) before the parentheses. For example:

  1. let apples = 3
  2. let oranges = 5
  3. let appleSummary = "I have \(apples) apples."
  4. let fruitSummary = "I have \(apples + oranges) pieces of fruit."

EXPERIMENT

Use \() to include a floating-point calculation in a string and to include someone’s name in a greeting.
 

译:这里有一个更简单的方式去在字符串里包含值:将这个值写进圆括号()里,并且在原括号前写一个反斜杠(\),例如:code
实验
用\()去在字符串里包含一个浮点值的计算并且在问候语里包含某个人的名字

 

Use three double quotation marks (""") for strings that take up multiple lines. Indentation at the start of each quoted line is removed, as long as it matches the indentation of the closing quotation marks. For example:

  1. let quotation = """
    I said "I have \(apples) apples."
    And then I said "I have \(apples + oranges) pieces of fruit."
    """

译:用三个双引号(" " ")来表示多行字符串。只要它匹配上结束引用标记的缩格,在每个引用行行头的缩格就是被删除的,例如:code

Create arrays and dictionaries using brackets ([]), and access their elements by writing the index or key in brackets. A comma is allowed after the last element.

  1. var shoppingList = ["catfish", "water", "tulips", "blue paint"]
    shoppingList[1] = "bottle of water"
    
    var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
    ]
    occupations["Jayne"] = "Public Relations"

To create an empty array or dictionary, use the initializer syntax.

  1. let emptyArray = [String]()
    let emptyDictionary = [String: Float]()

If type information can be inferred, you can write an empty array as [] and an empty dictionary as [:]—for example, when you set a new value for a variable or pass an argument to a function.

  1. shoppingList = []
  2. occupations = [:]

译:
1.用([]) 方括号创建数组和字典,通过元素的索引或字典的key值访问到方括号中的元素。最后一个元素后面允许逗号.ex: code

2. 用初始化语法创建一个空数组或字典

3.如果类型信息可以被判断,你可以写一个空数组[],或空字典[:] -- 例如,当你设置一个值为一个变量或传一个参数给函数时.

 

 

2018-08-01 10:33:34 Philm_iOS 阅读数 3449

该文章翻译自Apple官方文档: The Swift 4 Programming Language

Guards翻译组 正在翻译Swift 4的全套文档, 这是该文档第一章节的上半部分, 下半部分我们将于明天下午发布. 如果你感兴趣, 可以关注我们的简书.
原文链接: The Basics

Swift 是一门开发 iOS, macOS, watchOS 和 tvOS 应用的新语言。即便如此,如果你有 C 或者 Objective-C 开发经验,你会发现 Swift 的有很多你熟悉的内容。Swift 提供了与 C 和 Objective-C 上所有基础数据类型,如整型Int; 浮点型Double和Float; 布尔型值Bool;文本型数据String 。 Swift 还提供了三个基本的集合类型,Array ,Set和 Dictionary ,详见集合类型。

和 C 语言类似,Swift 使用变量来进行存储并通过变量名来关联对应的值。在 Swift 中,不可变的变量非常常用,它们就是常量,而且比 C 语言的常量更强大。在 Swift 中,如果你要处理的值不需要改变,那使用常量可以让你的代码更加安全并且更清晰地表达你的意图。

除了我们熟悉的类型,Swift 还增加了 Objective-C 中没有的高阶数据类型, 比如元组Tuples。元组可以让你创建或者传递一组数据,当函数需要返回单一复合值时,你可以用一个元组可以返回多个值。

Swift 还增加了Optional类型(译者注: Optional类型即可选类型),用于处理值不存在的情况。可选的意思是 “这里有一个值,并且它等于x ” 或 “这里没有值” 。可选有点像在 Objective-C 中使用nil ,但是它可以用在任何类型上,不仅仅是类。可选类型比 Objective-C 中的 nil指针更加安全也更具表现力,它是 Swift 许多强大特性的重要组成部分。
Swift 是一门类型安全的语言,这意味着 Swift 可以让你清楚地知道值的类型。如果你的代码期望得到一个String ,类型安全会阻止你错误地传入一个Int。同样的,如果你的代码期望得到一个 String,类型安全会阻止你意外传入一个可选的 String 。类型安全可以帮助你在开发阶段尽早发现并修正错误。

常量和变量

常量和变量把一个名字(比如maximumNumberOfLoginAttempts或者 welcomeMessage)和一个指定类型的值(比如数字 10或者字符串”Hello”)关联起来。常量的值一旦设定就不能改变,而变量的值可以随意更改。

声明常量和变量

常量和变量必须在使用前声明,用 关键字let来声明常量和关键字 var来声明变量。下面的例子展示了如何用常量和变量来记录用户尝试登录的次数:

  let maximumNumberOfLoginAttempts = 10
  var currentLoginAttempt = 0

这两行代码可以被理解为:
“声明一个名字是maximumNumberOfLoginAttempts的新常量,并给它一个值 10。然后,声明一个名字是currentLoginAttempt的变量并将它的值初始化为0 ”。

在这个例子中,允许的最大尝试登录次数被声明为一个常量,因为这个值不会改变。当前尝试登录次数被声明为一个变量,因为每次尝试登录失败的时候都需要增加这个值。
你可以在一行中声明多个常量或者多个变量,用逗号隔开:

  var x = 0.0, y = 0.0, z = 0.0

Note:如果你的代码中有不需要改变的值,请使用 let 关键字将它声明为常量。只将需要改变的值声明为变量。

类型标注

当你声明常量或者变量的时候可以加上 类型标注 (type annotation),说明常量或者变量中要存储的值的类型。通过在常量或变量名后面接一个冒号来写一个类型标注,后跟一个空格,后跟要使用的类型的名称。

这个例子给welcomeMessage 变量添加了类型标注,表示这个变量可以存储 String类型的值:

   var welcomeMessage: String

声明中的冒号代表着“xx是xx类型”,所以这行代码可以被理解为:

声明一个类型为 String,名字为welcomeMessage的变量。
类型为 String ”的意思是“可以存储任意 String 类型的值。

welcomeMessage 变量现在可以被正确地设置成任意字符串:

  welcomeMessage = "Hello"

你可以在一行中定义多个同样类型的变量,用逗号分割,并在最后一个变量名之后添加类型标注:

  var red, green, blue: Double

Note:一般来说你很少需要写类型标注。如果你在声明常量或者变量的时候赋了一个初始值,Swift可以推断出这个常量或者变量的类型,请参考类型安全和类型推断。在上面的例子中,没有给 welcomeMessage
赋初始值,所以变量 welcomeMessage
的类型是通过一个类型标注指定的,而不是通过初始值推断的。
常量和变量的命名

你可以用任何你喜欢的字符作为常量和变量名,包括 Unicode 字符:

let π = 3.14159
let 你好 = "你好世界"
let  = "dogcow"

常量与变量名不能包含空格,数学符号,箭头,保留的(或者非法的)Unicode 码位,连线与制表符。不能以数字开头,但是可以在常量与变量名的其他地方包含数字。
一旦你将常量或者变量声明为确定的类型,你就不能使用相同的名字再次进行声明,或者改变其存储的值的类型。同时,你也不能将常量与变量进行互转。

Note:如果你需要使用与Swift保留关键字相同的名称作为常量或者变量名,你可以使用反引号(`)将关键字包围的方式将其作为名字使用。无论如何,你应当避免使用关键字作为常量或变量名,除非你别无选择。
你可以更改现有的变量值为其他同类型的值,在下面的例子中,friendlyWelcome的值从”Hello!”改为了”Bonjour!”:

var friendlyWelcome = "Hello!"
friendlyWelcome = "Bonjour!"
// friendlyWelcome 现在是 "Bonjour!"

与变量不同,常量的值一旦被确定就不能更改了。尝试这样做会导致编译时报错:

let languageName = "Swift"
languageName = "Swift++"
// 这会报编译时错误 - languageName 不可改变

输出常量和变量

你可以用print(_:separator:terminator:)
函数来输出当前常量或变量的值:

print(friendlyWelcome)// 输出 "Bonjour!"

print(:separator:terminator:)是一个用来输出一个或多个值到适当输出区的全局函数。在 Xcode中,print(:separator:terminator:)将会输出内容到“console”面板上。separator和 terminator参数具有默认值,因此你调用这个函数的时候可以忽略它们。默认情况下,该函数通过添加换行符来结束当前行。如果不想换行,可以传递一个空字符串给 terminator 参数–例如,print(someValue, terminator:”“)
。关于参数默认值的更多信息,请参考默认参数值。

Swift 用字符串插值(string interpolation)的方式把常量名或者变量名当做占位符加入到长字符串中,Swift 会用当前常量或变量的值替换这些占位符。将常量或变量名放入圆括号中,并在开括号前使用反斜杠将其转义:

print("The current value of friendlyWelcome is \(friendlyWelcome)")
// 输出 "The current value of friendlyWelcome is Bonjour!

Note:字符串插值所有可用的选项,请参考字符串插值。
注释

请将你的代码中的非执行文本注释成提示或者笔记以方便你将来阅读。Swift 的编译器将会在编译代码时自动忽略掉注释部分。
Swift 中的注释与 C 语言的注释非常相似。单行注释以双正斜杠 (//)
作为起始标记:

  // 这是一个注释
  ```
行注释的起始标记为单个正斜杠后跟随一个星号(/*),终止标记为一个星号后跟随单个正斜杠(*/):

/* 这是一个,多行注释 */

C 语言多行注释不同,Swift 的多行注释可以嵌套在其它的多行注释之中。你可以先生成一个多行注释块,然后在这个注释块之中再嵌套成第二个多行注释。终止注释时先插入第二个注释块的终止标记,然后再插入第一个注释块的终止标记:

/* 这是第一个多行注释的开头
/* 这是第二个被嵌套的多行注释 */
这是第一个多行注释的结尾 */


通过运用嵌套多行注释,你可以方便快速的注释掉一大段代码,即使这段代码之中已经含有了多行注释块。

#### 分号

与其他大部分编程语言不同,Swift 并不强制要求你在每条语句的结尾处使用分号(;),当然,你也可以按照你自己的习惯添加分号。有一种情况下必须要用分号,即你打算在同一行内写多条独立的语句:

let cat = “”;
print(cat)// 输出 “”

#### 整数

整数就是没有小数部分的数字,比如 42和 -23 。整数可以是 有符号(正数、零和负数)或者无符号(正数、零)。
Swift 提供了8163264位的有符号和无符号整数类型。这些整数类型和 C 语言的命名方式很像,比如8位无符号整数类型是UInt8,32位有符号整数类型是Int32。就像 Swift 的其他类型一样,整数类型采用大写命名法。

#### 整数范围

你可以访问不同整数类型的 minmax 属性来获取对应类型的最小值和最大值:

let minValue = UInt8.min // minValue 为 0,是 UInt8 类型
let maxValue = UInt8.max // maxValue 为 255,是 UInt8 类型

这些属性的值具有适当大小的数字类型(例如上例中的UInt8),因此可以与表达式一起使用同一类型的其他值。

#### Int

大多数情况下,你不需要专门指定整数的长度。Swift 提供了一个特殊的整数类型Int,长度与当前平台的原生字长相同:

在32位平台上,Int和 Int32长度相同。
在64位平台上,Int和 Int64长度相同。
除非你需要特定长度的整数,一般来说使用 Int就够了。这可以提高代码一致性和可复用性。即使是在32位平台上,Int 可以存储的整数范围也可以达到 -2,147,483,648 ~ 2,147,483,647,大多数时候这已经足够大了。

#### UInt

Swift 也提供了一个特殊的无符号类型 UInt,长度与当前平台的原生字长相同:

在32位平台上,UInt 和 UInt32长度相同。
在64位平台上,UInt 和 UInt64长度相同。
Note:尽量不要使用UInt,除非你真的需要存储一个和当前平台原生字长相同的无符号整数。除了这种情况,最好使用Int,即使你要存储的值已知是非负的。统一使用Int可以提高代码的可复用性,避免不同类型数字之间的转换,并且匹配数字的类型推断,请参考类型安全和类型推断。
##### 浮点数

浮点数是有小数部分的数字,比如 3.141590.1 和 -273.15。
浮点类型比整数类型表示的范围更广,可以存储比Int
类型更大或者更小的数字。Swift 提供了两种有符号浮点数类型:

Double表示64位浮点数。
Float表示32位浮点数。
Note:Double精确度很高,至少有15位数字,而Float只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围,在两种类型都可以选择的情况下,将优先选择 Double。
##### 类型安全和类型推断

Swift 是一个类型安全(type-safe)的语言。类型安全的语言可以让你清楚地知道代码要处理的值的类型。如果你的代码需要一个String,你绝对不可能错误地传进去一个Int。

由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。

当你要处理不同类型的值时,类型检查可以帮你避免错误。然而,这并不是说你每次声明常量和变量的时候都需要显式指定类型。如果你没有显式指定类型,Swift 会使用类型推断(type inference)来选择合适的类型。有了类型推断,编译器可以在编译代码的时候自动推断出表达式的类型。原理很简单,只要检查你赋的值即可。

因为有了类型推断,和 C 或者 Objective-C 比起来 Swift 很少需要声明类型。常量和变量虽然需要明确类型,但是大部分工作并不需要你自己来完成。

当你声明常量或者变量并赋初值的时候类型推断非常有用。当你在声明常量或者变量的时候赋给它们一个确定值(literal value 或 literal)即可触发类型推断。(字面量就是会直接出现在你代码中的值,比如 423.14159。)
例如,如果你给一个新常量赋值42并且没有标明类型,Swift 可以推断出常量类型是 Int,因为你给它赋的初始值看起来像一个整数:

let meaningOfLife = 42// meaningOfLife 会被推测为 Int 类型

同理,如果你没有给浮点数标明类型,Swift 会推断你想要的是Double

let pi = 3.14159// pi 会被推测为 Double 类型

当推断浮点数的类型时,Swift 总是会优先选择 Double而不是Float。如果表达式中同时出现了整数和浮点数,会被推断为 Double
类型:

let anotherPi = 3 + 0.14159 // anotherPi 会被推测为 Double 类型

原始值3 没有显式声明类型,而表达式中出现了一个浮点数,所以表达式会被推断为 Double类型。

#### 数值型字面量

整数字面量可以被写作:

一个十进制数,没有前缀
一个二进制数,前缀是0b
一个八进制数,前缀是0o
一个十六进制数,前缀是0x
下面的所有整数字面量的十进制值都是17

let decimalInteger = 17
let binaryInteger = 0b10001 // 二进制的17
let octalInteger = 0o21 // 八进制的17
let hexadecimalInteger = 0x11 // 十六进制的17

浮点字面量可以是十进制(没有前缀)或者是十六进制(前缀是 0x )。小数点两边必须有至少一个十进制数字(或者是十六进制的数字)。十进制浮点数也可以有一个可选的指数(exponent),通过大写或者小写的 e来指定;十六进制浮点数必须有一个指数,通过大写或者小写的 p来指定。如果一个十进制数的指数为 exp,那这个数相当于基数和10^exp的乘积:

1.25e2 表示 1.25 × 10^2,等于 125.0。
1.25e-2 表示 1.25 × 10^-2,等于 0.0125。

如果一个十六进制数的指数为exp,那这个数相当于基数和2^exp的乘积:

0xFp2 表示 15 × 2^2,等于 60.0。
0xFp-2 表示 15 × 2^-2,等于 3.75。

下面的这些浮点字面量都等于十进制的12.1875:

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

数值类字面量可以包括额外的格式来增强可读性。整数和浮点数都可以添加额外的零并且包含下划线,并不会影响字面量:

let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

#### 数值型类型转换

通常来讲,即使代码中的整数常量和变量已知非负,也请使用Int类型。总是使用默认的整数类型可以保证你的整数常量和变量可以直接被复用并且可以匹配整数类字面量的类型推断。

只有在必要的时候才使用其他整数类型,比如要处理外部的长度明确的数据或者为了优化性能、内存占用等等。使用显式指定长度的类型可以及时发现值溢出并且可以暗示正在处理特殊数据。

##### 整数转换

不同整数类型的变量和常量可以存储不同范围的数字。Int8类型的常量或者变量可以存储的数字范围是-128~127,而UInt8类型的常量或者变量能存储的数字范围是0~255。如果数字超出了常量或者变量可存储的范围,编译的时候会报错:

let cannotBeNegative: UInt8 = -1// UInt8 类型不能存储负数,所以会报错
let tooBig: Int8 = Int8.max + 1// Int8 类型不能存储超过最大值的数,所以会报错

由于每种整数类型都可以存储不同范围的值,所以你必须根据不同情况选择性使用数值型类型转换。这种选择性使用的方式,可以预防隐式转换的错误并让你的代码中的类型转换意图变得清晰。

为了将一种数字类型转换成另一种,你要用当前值来初始化一个期望类型的新数字,这个数字的类型就是你的目标类型。在下面的例子中,常量twoThousand是UInt16类型,然而常量one是UInt8类型。它们不能直接相加,因为它们类型不同。所以要调用UInt16(one)来创建一个新的UInt16数字并用one的值来初始化,然后使用这个新数字来计算:

let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)
“`
现在两个数字的类型都是 UInt16,可以进行相加。输出常量 twoThousandAndOne 的类型被推断为 UInt16,因为它是两个 UInt16值的和。

SomeType(ofInitialValue)是调用Swift类型的初始化器并传入初始值的默认方式。
在语言内部,UInt16有接受一个UInt8的值,这个初始化器用来从现有的UInt8中创建一个新的UInt16。然而,你并不能传入任意类型的值,只能传入UInt16类型的值。不过你可以扩展现有的类型来让它可以接收其他类型的值(包括自定义类型),请参考扩展。

整数和浮点数转换

整数和浮点数的转换必须显式指定类型:

let three = 3let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine // pi 等于 3.14159,所以被推测为 Double 类型
这个例子中,常量 three的值被用来创建一个Double类型的值,所以加号两边的数类型须相同。如果不进行转换,两者无法相加。浮点数到整数的反向转换同样行,整数类型可以用` Double 或者Float类型来初始化:

let integerPi = Int(pi)// integerPi 等于 3,所以被推测为 Int 类型
当用浮点类型来初始化一个新的整数值时,浮点值会被截断。也就是说 4.75会变成 4,-3.9会变成 -3。

Note:结合数字类常量和变量不同于结合数字类字面量。字面量3可以直接和字面量0.14159相加,因为数字字面量本身没有明确的类型。它们的类型只在编译器需要求值的时候被推测。

类型别名

类型别名type aliases就是给现有类型定义另一个名字。你可以使用typealias关键字来定义类型别名。

当你想要给现有类型起一个更合适的名字时,类型别名非常有用。比如你正在处理特定长度的外部资源的数据:

typealias AudioSample = UInt16

定义了一个类型别名之后,你可以在任何使用原始名的地方使用别名:

var maxAmplitudeFound = AudioSample.min// maxAmplitudeFound 现在是 0

本例中,AudioSample被定义为UInt16的一个别名。因为它是别名,AudioSample.min实际上是UInt16.min,所以会给maxAmplitudeFound赋一个初值0。

布尔值

Swift 有一个基本的布尔Boolean类型,叫做Bool。布尔值指逻辑上的值,因为它们只能是真或者假。Swift 有两个布尔常量,true和false:

let orangesAreOrange = truelet
turnipsAreDelicious = false

orangesAreOrange和turnipsAreDelicious 的类型会被推断为 Bool,因为它们的初值是布尔字面量。就像之前提到的 Int 和 Double一样,如果创建变量的时候给它们赋值 true或者false,那你不需要将常量或者变量声明为Bool类型。初始化常量或者变量的时候如果所赋的值类型已知,就可以触发类型推断,这让 Swift 代码更加简洁并且可读性更高。当你编写条件语句比如 if 语句的时候,布尔值非常有用:

if turnipsAreDelicious {
     print("Mmm, tasty turnips!")
} else {
     print("Eww, turnips are horrible.")
}

// 输出 “Eww, turnips are horrible.”
条件语句,例如if,请参考控制流。

如果你在需要使用 Bool类型的地方使用了非布尔值,Swift 的类型安全机制会报错。下面的例子会报告一个编译时错误:

let i = 1if i { // 这个例子不会通过编译,会报错}

然而,下面的例子是合法的:

let i = 1
if i == 1 {
    // 这个例子会编译成功
}

i == 1 的比较结果是 Bool类型,所以第二个例子可以通过类型检查。类似i ==1这样的比较,请参考基本操作符。和 Swift 中的其他类型安全的例子一样,这个方法可以避免错误,并确保特定代码的意图总是清晰的。

元组

元组tuples把多个值组合成一个复合值。元组内的值可以是任意类型,并不要求是相同类型。

下面这个例子中,(404, “Not Found”)是一个描述 HTTP 状态码HTTP status code的元组。HTTP 状态码是当你请求网页的时候 web 服务器返回的一个特定值。如果你请求的网页不存在就会返回一个 404 Not Found 状态码。

let http404Error = (404, "Not Found")
// http404Error 的类型是 (Int, String),值是 (404, "Not Found")

404, “Not Found”元组把一个 Int 值和一个String值组合起来表示HTTP状态码的两个部分:一个数字和一个人类可读的描述。这个元组被定义为“一个类型为 (Int, String)的元组”。
你可以把任意顺序的类型组合成一个元组,这个元组可以包含所有类型。你可以创建任何一个类型为(Int, Int, Int)或者 (String, Bool) 或者其他任何你想要的组合的元组。你可以将一个元组内容分解(decompose)成单独的常量和变量,然后你就可以正常使用它们了:

let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)")
// 输出 "The status code is 404"
print("The status message is \(statusMessage)")
// 输出 "The status message is Not Found"

如果你只需要一部分元组值,分解的时候可以把要忽略的部分用下划线(_
)表示:

let (justTheStatusCode, \_) = http404Error
print("The status code is \(justTheStatusCode)")
// 输出 "The status code is 404"

此外,你还可以通过下标来访问元组中的单个元素,下标从零开始:

print("The status code is \(http404Error.0)")
// 输出 "The status code is 404"
print("The status message is \(http404Error.≥   1)")
// 输出 "The status message is Not Found"

你可以在定义元组的时候给单个元素命名:

let http200Status = (statusCode: 200, description: "OK")

给元组中的元素命名后,你可以通过名字来获取这些元素的值:

print("The status code is \(http200Status.statusCode)")
// 输出 "The status code is 200"
print("The status message is \(http200Status.description)")
// 输出 "The status message is OK"

作为函数返回值时,元组非常有用。一个用来获取网页的函数可能会返回一个(Int, String) 元组来描述是否获取成功。和只能返回一个类型的值比较起来,一个包含两个不同类型值的元组可以让函数的返回信息更有用。请参考函数参数与返回值。

Note:元组在临时组织值的时候很有用,但是并不适合创建复杂的数据结构。如果你的数据结构并不是临时使用,请使用类或者结构体而不是元组。请参考类和结构体。
The Basics 上半部分完结, 下半部分我们将于明天下午发布.

2017-11-03 18:54:17 fengmm521 阅读数 1740
苹果2014 WWDC中发布了一种新的编程语言--swift。
这个语言初一看有点像python一样简洁。看了一下教程,总体上来说,在使用这个语言进行编程时,是比使用OC快很多。开发人员不用再为各种没有用的符号来打很多字符,可以让自已编写的代码更有效率。下边是网上找到的一个教程,自已觉得看过这个教程之后,这个语言就基本上掌握了一多半了。值得收藏和学习。
另一个连接,是一个开源的合作swift英文教程文档翻译:

1   简介

今天凌晨Apple刚刚发布了Swift编程语言,本文从其发布的书籍《The Swift Programming Language》中摘录和提取而成。希望对各位的iOS&OSX开发有所帮助。

Swift是供iOS和OS X应用编程的新编程语言,基于C和Objective-C,而却没有C的一些兼容约束。Swift采用了安全的编程模式和添加现代的功能来是的编程更加简 单、灵活和有趣。界面则基于广受人民群众爱戴的Cocoa和Cocoa Touch框架,展示了软件开发的新方向。

Swift已经存在了多年。Apple基于已有的编译器、调试器、框架作为其基础架构。通过ARC(Automatic Reference Counting,自动引用计数)来简化内存管理。我们的框架栈则一直基于Cocoa。Objective-C进化支持了块、collection literal和模块,允许现代语言的框架无需深入即可使用。(by gashero)感谢这些基础工作,才使得可以在Apple软件开发中引入新的编程语言。

Objective-C开发者会感到Swift的似曾相识。Swift采用了Objective-C的命名参数和动态对象模型。提供了对Cocoa框架和mix-and-match的互操作性。基于这些基础,Swift引入了很多新功能和结合面向过程和面向对象的功能。

Swift对新的程序员也是友好的。他是工业级品质的系统编程语言,却又像脚本语言一样的友好。他支持playground,允许程序员实验一段Swift代码功能并立即看到结果,而无需麻烦的构建和运行一个应用。

Swift集成了现代编程语言思想,以及Apple工程文化的智慧。编译器是按照性能优化的,而语言是为开发优化的,无需互相折中。(by gashero)可以从"Hello, world"开始学起并过渡到整个系统。所有这些使得Swift成为Apple软件开发者创新的源泉。

Swift是编写iOS和OSX应用的梦幻方式,并且会持续推进新功能的引入。我们迫不及待的看到你用他来做点什么。

2   Swift入门

一个新语言的学习应该从打印"Hello, world"开始。在Swift,就是一行:

println("Hello, world")

如果你写过C或Objective-C代码,这个语法看起来很熟悉,在Swift,这就是完整的程序了。你无需导入(import)一个单独的库供输入输出和字符串处理。全局范围的代码就是用于程序的入口,所以你无需编写一个 main() 函数。你也无需在每个语句后写分号。

这个入门会给出足够的信息教你完成一个编程任务。无需担心你还不理解一些东西,所有没解释清楚的,会在本书后续详细讲解。

Note

作为最佳实践,可以将本章在Xcode的playground中打开。Playground允许你编辑代码并立即看到结果。

3   简单值

使用 let 来定义常量, var 定义变量。常量的值无需在编译时指定,但是至少要赋值一次。这意味着你可以使用常量来命名一个值,你发现只需一次确定,却用在多个地方。

var myVariable = 42
myVariable = 50
let myConstant = 42

Note

gashero注记

这里的常量定义类似于函数式编程语言中的变量,一次赋值后就无法修改。多多使用有益健康。

一个常量或变量必须与赋值时拥有相同的类型。因此你不用严格定义类型。提供一个值就可以创建常量或变量,并让编译器推断其类型。在上面例子中,编译其会推断myVariable是一个整数类型,因为其初始化值就是个整数。

Note

gashero注记

类型与变量名绑定,属于静态类型语言。有助于静态优化。与Python、JavaScript等有所区别。

如果初始化值没有提供足够的信息(或没有初始化值),可以在变量名后写类型,以冒号分隔。

let imlicitInteger = 70
let imlicitDouble = 70.0
let explicitDouble: Double = 70

Note

练习

创建一个常量,类型为Float,值为4。

值永远不会隐含转换到其他类型。如果你需要转换一个值到不同类型,明确的构造一个所需类型的实例。

let label = "The width is "
let width = 94
let widthLabel = label + String(width)

Note

练习

尝试删除最后一行的String转换,你会得到什么错误?

还有更简单的方法来在字符串中包含值:以小括号来写值,并用反斜线("")放在小括号之前。例如:

let apples = 3
let oranges = 5     //by gashero
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."

Note

练习

使用 () 来包含一个浮点数计算到字符串,并包含某人的名字来问候。

创建一个数组和字典使用方括号 "[]" ,访问其元素则是通过方括号中的索引或键。

var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"

var occupations = [
   "Malcolm": "Captain",
   "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

要创建一个空的数组或字典,使用初始化语法:

let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()

如果类型信息无法推断,你可以写空的数组为 "[]" 和空的字典为 "[:]",例如你设置一个知道变量并传入参数到函数:

shoppingList = []   //去购物并买些东西 by gashero

4   控制流

使用 if 和 switch 作为条件控制。使用 for-in 、 for 、 while 、 do-while 作为循环。小括号不是必须的,但主体的大括号是必需的。

let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
    if score > 50 {
        teamScores += 3
    } else {
        teamScores += 1
    }
}
teamScore

在 if 语句中,条件必须是布尔表达式,这意味着 if score { ... } 是错误的,不能隐含的与0比较。

你可以一起使用 if 和 let 来防止值的丢失。这些值是可选的。可选值可以包含一个值或包含一个 nil 来指定值还不存在。写一个问号 "?" 在类型后表示值是可选的。

var optionalString: String? = "Hello"
optionalString == nil

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

Note

练习

改变 optionalName 为 nil 。在问候时会发生什么?添加一个 else 子句在 optionalName 为 nil 时设置一个不同的值。

如果可选值为 nil ,条件就是 false 大括号中的代码会被跳过。否则可选值未包装并赋值为一个常量,会是的未包装值的变量到代码块中。

switch 支持多种数据以及多种比较,不限制必须是整数和测试相等。

let vegetable = "red pepper"
switch vegetable {
case "celery":
    let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
    let vegetableComment = "That would make a good tea sandwich."
case let x where x.hasSuffix("pepper"):
    let vegetableComment = "Is it a spicy \(x)?"
default:    //by gashero
    let vegetableComment = "Everything tastes good in soup."
}

Note

练习

尝试去掉 default ,看看得到什么错误。

在执行匹配的情况后,程序会从 switch 跳出,而不是继续执行下一个情况。所以不再需要 break 跳出 switch 。

可使用 for-in 来迭代字典中的每个元素,提供一对名字来使用每个键值对。

let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}

Note

练习

添加另一个变量来跟踪哪个种类中的数字最大,也就是最大的数字所在的。

使用 while 来重复执行代码块直到条件改变。循环的条件可以放在末尾来确保循环至少执行一次。

var n = 2
while n < 100 {
    n = n * 2
}
n

var m = 2
do {
    m = m * 2
} while m < 100
m

你可以在循环中保持一个索引,通过 ".." 来表示索引范围或明确声明一个初始值、条件、增量。这两个循环做相同的事情:

var firstForLoop = 0
for i in 0..3 {
    firstForLoop += i
}
firstForLoop

var secondForLoop = 0
for var i = 0; i < 3; ++i {
    secondForLoop += 1
}
secondForLoop

使用 .. 构造范围忽略最高值,而用 ... 构造的范围则包含两个值。

5   函数与闭包

使用 func 声明一个函数。调用函数使用他的名字加上小括号中的参数列表。使用 -> 分隔参数的名字和返回值类型。

func greet(name: String, day: String) -> String {
    return "Hello \(name), today is \(day)."
}
greet("Bob", "Tuesday")

Note

练习

去掉 day 参数,添加一个参数包含今天的午餐选择。

使用元组(tuple)来返回多个值。

func getGasPrices() -> (Double, Double, Double) {
    return (3.59, 3.69, 3.79)
}
getGasPrices()

函数可以接受可变参数个数,收集到一个数组中。

func sumOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
sumOf()
sumOf(42, 597, 12)

Note

练习

编写一个函数计算其参数的平均值。

函数可以嵌套。内嵌函数可以访问其定义所在函数的变量。你可以使用内嵌函数来组织代码,避免过长和过于复杂。

func returnFifteen() -> Int {
    var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}   //by gashero
returnFifteen()

函数是第一类型的。这意味着函数可以返回另一个函数。

func makeIncrementer() -> (Int -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)

一个函数可以接受其他函数作为参数。

func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}

func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, lessThanTen)

函数实际是闭包的特殊情况。你可以写一个闭包而无需名字,只需要放在大括号中即可。使用 in 到特定参数和主体的返回值。

numbers.map({
    (number: Int) -> Int in
    let result = 3 * number
    return result
    })

Note

练习

重写一个闭包来对所有奇数返回0。

编写闭包时有多种选项。当一个闭包的类型是已知时,例如代表回调,你可以忽略其参数和返回值,或两者。单一语句的闭包可以直接返回值。

numbers.map({number in 3 * number})

你可以通过数字而不是名字来引用一个参数,这对于很短的闭包很有用。一个闭包传递其最后一个参数到函数作为返回值。

sort([1, 5, 3, 12, 2]) { $0 > $1 }

6   对象与类

使用 class 可以创建一个类。一个属性的声明则是在类里作为常量或变量声明的,除了是在类的上下文中。方法和函数也是这么写的。

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

Note

练习

通过 "let" 添加一个常量属性,以及添加另一个方法能接受参数。

通过在类名后加小括号来创建类的实例。使用点语法来访问实例的属性和方法。

var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

这个版本的 Shape 类有些重要的东西不在:一个构造器来在创建实例时设置类。使用 init 来创建一个。

class NamedShape {
    var numberOfSides: Int = 0
    var name: String

    init(name: String) {
        self.name = name
    }   //by gashero

    func simpleDescription() -> String {
        return "A Shape with \(numberOfSides) sides."
    }
}

注意 self 用来区分 name 属性和 name 参数。构造器的生命跟函数一样,除了会创建类的实例。每个属性都需要赋值,无论在声明里还是在构造器里。

使用 deinit 来创建一个析构器,来执行对象销毁时的清理工作。

子类包括其超类的名字,以冒号分隔。在继承标准根类时无需声明,所以你可以忽略超类。

子类的方法可以通过标记 override 重载超类中的实现,而没有 override 的会被编译器看作是错误。编译器也会检查那些没有被重载的方法。

class Square: NamedShape {
    var sideLength: Double

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }

    func area() -> Double {
        return sideLength * sideLength
    }

    override func simpleDescription() -> String {
        return "A square with sides of length \(sideLength)."
    }
}

let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()

Note

练习

编写另一个 NamedShape 的子类叫做 Circle ,接受半径和名字到其构造器。实现 area 和 describe 方法。

属性可以有 getter 和 setter 。

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }

    var perimeter: Double {
    get {
        return 3.0 * sideLength
    }
    set {
        sideLength = newValue / 3.0
    }
    }

    override func simpleDescription() -> String {
        return "An equilateral triangle with sides of length \(sideLength)."
    }
}

var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength

在 perimeter 的 setter 中,新的值的名字就是 newValue 。你可以提供一个在 set 之后提供一个不冲突的名字。

注意 EquilateralTriangle 的构造器有3个不同的步骤:

  1. 设置属性的值
  2. 调用超类的构造器
  3. 改变超类定义的属性的值,添加附加的工作来使用方法、getter、setter也可以在这里

如果你不需要计算属性,但是仍然要提供在设置值之后执行工作,使用 willSet 和 didSet 。例如,下面的类要保证其三角的边长等于矩形的变长。

class TriangleAndSquare {
    var triangle: EquilaterTriangle {
    willSet {
        square.sideLength = newValue.sideLength
    }
    }

    var square: Square {
    willSet {
        triangle.sideLength = newValue.sideLength
    }
    }

    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EquilaterTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength

类的方法与函数有个重要的区别。函数的参数名仅用与函数,但方法的参数名也可以用于调用方法(除了第一个参数)。缺省时,一个方法有一个同名的参数,调用时就是参数本身。你可以指定第二个名字,在方法内部使用。

class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes times: Int) {
        count += amount * times
    }
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)

当与可选值一起工作时,你可以写 "?" 到操作符之前类似于方法属性。如果值在"?"之前就已经是 nil ,所有在 "?" 之后的都会自动忽略,而整个表达式是 nil 。另外,可选值是未包装的,所有 "?" 之后的都作为未包装的值。在两种情况中,整个表达式的值是可选值。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength


7   枚举与结构

使用 enum 来创建枚举。有如类和其他命名类型,枚举可以有方法。

enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King
    func simpleDescrition() -> String {
        switch self {
        case .Ace:
            return "ace"
        case .Jack:
            return "jack"
        case .Queen:
            return "queen"
        case .King:
            return "king"
        default:
            return String(self.toRaw())
        }
    }
}
let ace = Rank.Ace  //by gashero
let aceRawValue = ace.toRaw()

Note

练习

编写一个函数比较两个 Rank 的值,通过比较其原始值。

在如上例子中,原始值的类型是 Int 所以可以只指定第一个原始值。其后的原始值都是按照顺序赋值的。也可以使用字符串或浮点数作为枚举的原始值。

使用 toRaw 和 fromRaw 函数可以转换原始值和枚举值。

if let convertedRank = Rank.fromRaw(3) {
    let threeDescription = convertedRank.simpleDescription()
}

枚举的成员值就是实际值,而不是其他方式写的原始值。实际上,有些情况是原始值,就是你不提供的时候。

enum Suit {
    case Spades, Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
        case .Spades:
            return "spades"
        case .Hearts:
            return "hearts"
        case .Diamonds:
            return "dismonds"
        case .Clubs:
            return "clubs"
        }
    }
}
let hearts = Suit.Hearts    //by gashero
let heartsDescription = hearts.simpleDescription()

Note

练习

添加一个 color 方法到 Suit 并在 spades 和 clubs 时返回 "black" ,并且给 hearts 和 diamounds 返回 "red" 。

注意上面引用Hearts成员的两种方法:当赋值到 hearts 常量时,枚举成员 Suit.Hearts 通过全名引用,因为常量没有明确的类型。在 switch 中,枚举通过 .Hearts 引用,因为 self 的值是已知的。你可以在任何时候使用方便的方法。

使用 struct 创建结构体。结构体支持多个与类相同的行为,包括方法和构造器。一大重要的区别是代码之间的传递总是用拷贝(值传递),而类则是传递引用。

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \
        (suit.simpleDescription())"
    }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

Note

练习

添加方法到 Card 类来创建一桌的纸牌,每个纸牌都有合并的rank和suit。(就是个打字员的活二,by gashero)。

一个枚举的实例成员可以拥有实例的值。相同枚举成员实例可以有不同的值。你在创建实例时赋值。指定值和原始值的区别:枚举的原始值与其实例相同,你在定义枚举时提供原始值。

例如,假设情况需要从服务器获取太阳升起和降落时间。服务器可以响应相同的信息或一些错误信息。

enum ServerResponse {
    case Result(String, String)
    case Error(String)
}

let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")

switch success {
case let .Result(sunrise, sunset):
    let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
case let .Error(error):
    let serverResponse = "Failure... \(error)"
}

Note

练习

给 ServerResponse 添加第三种情况来选择。

注意日出和日落时间实际上来自于对 ServerResponse 的部分匹配来选择的。

官方的教程在这里,大家也可以看英文的官方教程:
2018-04-12 23:56:40 weixin_40840896 阅读数 5507

该文章翻译自apple官方文档:The Swift Programming Language(Swift 5.0)

 

原文:

This book describes Swift 5, the default version of Swift that’s included in Xcode 10.2. You can use Xcode 10.2 to build targets that are written in either Swift 5, Swift 4.2, or Swift 4.

When you use Xcode 10.2 to build Swift 4 and Swift 4.2 code, most Swift 5 functionality is available. That said, the following changes are available only to Swift 5 code:

  • The try? expression doesn’t introduce an extra level of optionality to expressions that already return optionals.
  • Large integer literal initialization expressions are inferred to be of the correct integer type. For example, UInt64(0xffff_ffff_ffff_ffff) evaluates to the correct value rather than overflowing.

A target written in Swift 5 can depend on a target that’s written in Swift 4.2 or Swift 4, and vice versa. This means, if you have a large project that’s divided into multiple frameworks, you can migrate your code from Swift 4 to Swift 5 one framework at a time.

译文:

这本书描述Swift 5.0, 这默认版本被收录在Xcode 10.2 内。你可以用Xcode 10.2 去构建一个项目,这项目可以用Swift 5,Swift 4.2 或 Swift 4 写程序.

当你用Xcode 10.2 运行Swift 4 和 Swift 4.2 的代码时,大多数Swift 5的功能是可用的,这就是说,下面的改变只有在 Swift 5 上可用.

  • try?表达式不会为已经返回选项的表达式引入额外级别的可选性。
  • 推断大整数文字初始化表达式是正确的整数类型。例如,UInt64(0xffff_ffff_ffff_ffff)计算为正确的值而不是溢出。

一个用Swift 5 的项目是依赖于一个用Swift 4或者 Swift 4.2写的反之亦然。这就意味着,如果你有一个可以被分为多个framework的大型项目,你可以一次性将你的代码从 Swift 3 迁移到 Swift 4 一个框架。 

***************************************************************************************************************************************************

4.1 原文:

This book describes Swift 4.1, the default version of Swift that’s included in Xcode 9.2. You can use Xcode 9.2 to build targets that are written in either Swift 4 or Swift 3.

S

NOTE

When the Swift 4 compiler is working with Swift 3 code, it identifies its language version as 3.2. As a result, you can use conditional compilation blocks like #if swift(>=3.2) to write code that’s compatible with multiple versions of the Swift compiler.

When you use Xcode 9.2 to build Swift 3 code, most of the new Swift 4 functionality is available. That said, the following features are available only to Swift 4 code:

  • Substring operations return an instance of the Substring type, instead of String.

  • The @objc attribute is implicitly added in fewer places.

  • Extensions to a type in the same file can access that type’s private members.

A target written in Swift 4 can depend on a target that’s written in Swift 3, and vice versa. This means, if you have a large project that’s divided into multiple frameworks, you can migrate your code from Swift 3 to Swift 4 one framework at a time.

 

译文:

这本书描述Swift 4.1, 这默认版本被收录在Xcode 9.2 内。你可以用Xcode 9.2 去构建一个项目,然后用Swift 4 或 Swift 3 写程序.

 

注意:当你用Swift 4编译器去编译 Swift 3的代码时,它能辨认出3.2 的语言版本。因此,你可以用有条件的汇编代码块像#if swift(>=3.2)去写能够被多个编译器编译通过的代码。

当你用Xcode 9.2 去运行 Swift 3 的代码,大多数的新 Swift 4的功能都是可用的。需要说的是,下面的功能只能在 Swift 4上才能用:

 

Substring(子字符串)操作返回一个 Substring(子字符串)类型的实例,而不是String.

这个@objc 属性被私下里添加到更少的地方.

在同一个文件里,类型扩展可以访问该类型的私有成员。

一个用Swift 4 的项目可以依赖于一个用Swift 3写的反之亦然。这就意味着,如果你有一个可以被分为多个framework的大型项目,你可以一次性将你的代码从 Swift 3 迁移到 Swift 4 一个框架。 

 

 

 

 

 

 

 

 

Apple Swift学习教程

阅读数 7514