摘要:Swift 学习 Tips。
OS: macOS Sierra 10.12.1
IDE: Xcode
Language: Swift 3.0
备注:相近但是又不尽然。
Playground:就像一个可交互的文档,在其中你可以输入 Swift 代码让它们立即编译执行。Playground 就是包含 .swift 文件的包。
理解:Playground 的意义在于简单快速的实践 Swift 基本语法和代码编写、实时运行结果显示。
Playground Page:可以被串联的交互文档页面。在 Playground 中可以创建多个 Page (包含 .swift 文件)。
理解:Playground Page 的意义是为了建立多个 Playground 之间的联系。
Swift Playgrounds:用来在 iPad 上学习开发 Swift 的应用。这个应用比较有趣味性,学习样例中有各种游戏、无人机、机器人、物联网设备等的操作。
理解:Swift Playgrounds 的意义是为了让趣味性的实践引领大家入门 Swift,降低入门门槛和编程开发语言的枯燥性。
参考资料:
Playground 快速原型制作
Swift Playgrounds
Swift Playgrounds Developer
备注:尽量简化代码。简洁明了是现代化编程语言的特征之一。
如果每一行一句代码,那就不用在代码结束的时候加分号,如果每一行多句代码,那就需要添加上分号了。但是不太建议一行多句代码,这样不好看。
//以下两句代码均可 let value = 3 let value = 3; //这句代码不行 var valueA = 3 let valueB = 4 //需要这样写 var valueA = 3; let valueB = 4 //最好这样写 var valueA = 3 var valueB = 4
备注:类比 C/Java/Objective-C 语言的常量值不可修改。
很多时候,各个语言的基础定义都差不多,我们通过类比,就可以很快理解各个语言之间的相同点,也可以加深对于编程语言的认知。
let value = 3 //以下代码会报错 value = 4 //类比 C const int value = 3; //以下代码会报错 value = 4; //类比 Java final int value = 3; //以下代码会报错 value = 4; //类比 Objective-C NSString * const value = @"Google"; //以下代码会报错 value = @"ifeegoo";
备注:类比 C/Java/Objective-C 语言的变量/常量声明都是一样的。
个人感觉,虽然可以在一行中声明多个变量/常量,但是这样的代码并不是很好看。这个给人感觉是之前的 C 语言的风格。
//Swift var x = 0.0, y = 0.0, z = 0.0 //C/Java int a = 3, b = 4, c = 5; //Objective-C NSString *a = "www", *b = "ifeegoo", *c = "com";
备注:一般用在没有赋初始值的语句中。
我认为类型标注一般用在没有赋初始值的语句中之外,还应该会用到那种不能用字面量表示的一些赋值。另外一般不用加类型标注,因为 Swift 会自动识别,这种就使得代码变得简单。另外如果要加上这个类型标注的话,也可以使代码更加清晰明了。个人认为如果没有必要加类型标注的话,就不要加了,保持代码的整洁。C/Java/Objective-C 代码中,在进行声明的时候,就已经有类型标注了。
var value: String value = "ifeegoo" let string: String = "ifeegoo"
备注:没有特别情况,不建议这样命名。
我们只需要知道有这样的允许即可,没有什么特殊情况,不建议使用这样的命名,除非你是想参加《国际 C 语言混乱代码大赛》,否则知道有这个情况即可,不要这么做。
let π = 3.14159 let 你好 = "你好世界" let 🐶🐮 = "dogcow"
备注:需要进行特殊处理,没有特别情况,不建议这样命名。
我们使用保留关键字作为常量/变量的命名的时候,需要使用 “`” 符号包裹起来,在很多别的编程语言中是不允许这么做的,Swift 之所以这么做,我猜测是为了增加灵活度。
let `let` = 13 `let` = 14
备注:这种方式有点类似字符串拼接的形式。
我们需要使用 “\(常量/变量)” 格式来处理。
let value = 13 print("The value is \(value)")
备注:尽量不要使用 UInt ,除非你真的需要存储一个与当前平台原生字长相等的无符号整数,即使你知道你所需要存储的是无符号整数。
在 32 位平台上,Int 和 Int32 长度相同。
在 64 位平台上,Int 和 Int64 长度相同。
备注:既可以被推断成 Float,又可以被推断成 Double ,Swift 将会推断成精度更高的 Double。
这个也是比较好理解,尽量保证数值的精度,而不是丢失精度。
//以下 pi 会被自动推断成 Double。 let pi = 3.1415926
备注:有些时候,我们写成 2进制/16进制,更加方便易懂。
早期在做 Android 开发(基于 JavaSE 6)的时候,是不支持 2 进制字面量的。感觉特别头痛。后来在 JavaSE 7 中支持 2 进制字面量。现在开发 Android ,建议大家启用最新的 Build Tool,然后就可以使用 JavaSE 7 了,里面还支持 switch 中 case 字符串。这个对于减少 if/else 代码还是比较有用的。
let value1 = 0b101111, value2 = 0B101111 let value3 = 0372706 let value4 = 0o131313 let value5 = 0xAF16FA, value6 = 0X30FAFB
以上代码中 value2 和 value6 的赋值是会报错的,表示二进制、八进制和十六进制中的字幕 b/o/x 必须小写,大写会报错:expected a digit after integer literal prefix。
备注:可使用在科学计数中。
10 进制/16 进制指数表示方法如下:
let value4 = 0x10e2 = 0x10 × 10^2//不仅限于 16 进制 let value5 = 0x10p2 = 0x10 × 2^2//只有 16 进制才可以使用 p
e 表示 10 × exp,p 表示 2 × exp。p 只有 16 进制可以使用。
备注:感觉有一点点奇怪。
Swift 里面的确没有 Byte/Short/Long,但是有 C 字头的 CShort/CLong。
备注:C 语言中可以在数字后面添加字母标记数据类型。
是不是因为 Swift 有类型自动判断,不需要这样的语法,还是什么原因呢?
var value1 = 3.14f,value2 = 3.14F var value3 = 3.1415d,value4 = 3.1415D var value5 = 3l,value6 = 3L
以上代码中的数据追加类型标记是不行的。
备注:这种格式的好处和用处还在领悟中。
这种格式感觉怪怪的,目前还不理解它的好处。
let name = "ifeegoo" print("\(name)") print(name) print("ifeegoo") print("\("ifeegoo")")
以上对于字符串的输出,都是可行的,当然,括号里面也可以是普通数据类型。
备注:这种小细节可以更好的直观看到类型。
有的时候,小细节可以带来大收获。
let name = "ifeegoo" //按住 option 键,对着未声明类型的变量/常量点击鼠标左键,会有以下显示。 //Declaration let name: String //Declared **.xcodeplaygroundpage
备注:Swift 中不能写成 (Float)13。
//以下写法是错误的 let value = (Float)13 //以下写法是正确的 let value = Float(13)
Float(13):可以理解成 Float 类,调用构造方法,传入参数 13。
备注:布尔值只有 true 和 false。
不能被 C 语言中的布尔值的表达方式所迷惑。
if 1 //错误的表达方式 if true //正确的表达方式
备注:非 10 进制的小数也不好阅读和理解。
以下代码中,非 10 进制的小数,如果写成指数形式,是可以存在的。如果不写成指数形式,就会报错。
let value = 0xC.3 //这种赋值报错 let value = 0xC.3p0 //这种赋值不报错
备注:除非赋值的时候,有特别的指定。
看以下代码你就明白了。
let value = UInt64.max //result 的推断类型为 UInt64 let result = value //直接声明成 UInt64,赋值没有超过 UInt64,不报错。 let test:UInt64 = 18446744073709551615 //默认推断类型为 Int,赋一个超过 Int 值范围的数值,报错。 let result = 18446744073709551615
备注:小数点左右不能加下划线。
加 0 和下划线的意义:便于更好的阅读、比对,或者可视化计算。
let value1 = 001313 let value2 = 000013 let value3 = 0000_1111_0000.0000_0001
备注:通常来讲,即使代码中的整数常量和变量已知非负,也请使用 Int 类型。总是使用默认的整数类型可以保证你的整数常量和变量可以直接被复用并且可以匹配整数类字面量的类型推断。只有在必要的时候才使用其他整数类型,比如要处理外部的长度明确的数据或者为了优化性能、内存占用等等。使用显式指定长度的类型可以及时发现值溢出并且可以暗示正在处理特殊数据。
请在适当的时候,不要去想 8/16/32/64,有 U 还是没有 U。
备注:有的时候你刚写的代码,缺少了代码结束标记,可能前面的代码也会报错。
备注:感觉目前用不到。
是不是感觉以下代码有点怪怪的?
typealias Zifuchuan = String let value: Zifuchuan = "ifeegoo"
备注:Swift 中的 nil 和 Objective-C 中的 nil 不太一样。
Swift 的 nil 和 Objective-C 中的 nil 并不一样。在 Objective-C 中,nil 是一个指向不存在对象的指针。在 Swift 中,nil 不是指针——它是一个确定的值,用来表示值缺失。任何类型的可选状态都可以被设置为 nil,不只是对象类型。
备注:Optional 是 Swift 重要创新。? 表示可选类型。! 表示隐式解析可选类型。
以下的代码理解非常重要。
//value1 是非可选类型,不能赋 nil 值 var value1: Int = 13 //value1 = nil 会报错 //value2 的默认值是 nil var value2: Int? value2 = 13 //value3 的默认值是 nil var value3: Int! value3 = 14 //var value4:Int = value2 value2需要强制解析才能赋值给 value4,如果 value2 为 nil,强制解析会报错。 //var value4:Int = value3 value2不需要强制解析才能赋值给 value4,但是如果 value2 为 nil,强制解析会报错。 var value4: Int = value3 //可以将类型后面的 ! 理解为可以自动强制解析的 ? 类型。 //空合运算符。a 不为空的话,就将 a 强制解封。a 为空的话,就返回默认值 b。 a ?? b 等同于 a != nil ? a! : b var value //会报错。 var value:Int //不会报错,但是使用的时候,会提示没有初始化。 var value:Int? //不会报错,默认初始值为 nil。 var value:Int! //不会报错,默认初始值为 nil。 //可选绑定,走 if。 if let firstNumber = Int("4") //可选绑定,不走 if。 if let firstNumber = Int("ifeegoo")
并不是说类型之后加上 !,就不能设 nil 值。目前 ! 的理解就是:可以自动强制解析的 ? 类型。
备注:不要给自己或者给别人造成困恼。
这个问题让我们去思考那种考试还考运算符优先级的,这种问题考起来没有太大意义,我们平时用括号就可以避免这些问题,也不太会有人去“创造”那么复杂的运算符优先级的困境。
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword //建议写成 if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword
备注:Java 里面有 && || 和 & |。
&& 和 || 这种运算符是短路运算,而 & 和 | 却不是。
不断更新中!