随着Swift UI的发布,学习和使用Swift已经是必然的选择,这里是一份Swift教程(基于Swift5.0+)。
1. 分号
Swift不需要分号,每一行都是一句表达式,例如
print(1)
print(2)
如果需要在同一行写多条表达式,则需要添加分号,例如
print(1); print(2)
2. 注释
在C、Objective-C、C++中注释有//
和/**/
,在Swift中同样支持,Swift中解释性注释可以使用///
作为前缀
标记有: //MARK :
和 //MARK :
,对应OC中的#pagra mark
和#pagra mark -
3. 命名空间
Swift支持命名空间,并且是无限命名空间。
class Life {
class Person {
class Student {
/*
class ... {
}
*/
}
}
}
let student = Life.Person.Student()
- 对于一个target来说,target name就是最外层的命名空间,例如ASDK中有一个Person类,那么该类全名为ASDK.Person。
- 在同作用域中前缀可省略,例如ASDK中可直接使用Person, 而在ASDK包外需要使用ASDK.Person。
- 在Swift5之前,如果某命名空间下的类型名和系统重复,系统可以优先无包名使用,例如UIKit.URL,而Swift5里自己优先,即Network.URL省略Network直接使用URL时,当前作用域下的URL会受到影响,如果你想用的就是系统URL,则需要添加对应的包名,例如UIKit.URL。
4.关键字
Swift中id
不在是关键字,load
被取消,dealloc
更换为deinit
.
如果仍然想用被占用的关键字来命名,我们需要使用重音符号(`)将其括起来。例如
let `class` = "Pikachu"
// `class` is a string
常见的关键字有以下4种。
与声明有关的关键字 | |||
---|---|---|---|
class | deinit | enum | extension |
func | import | init | internal |
let | operator | private | protocol |
public | static | struct | subscript |
typealias | var |
与语句有关的关键字 | |||
---|---|---|---|
break | case | continue | default |
do | else | fallthrough | for |
if | in | return | switch |
where | while |
表达式和类型关键字 | |||
---|---|---|---|
as | dynamicType | false | is |
nil | self | Self | super |
true | COLUMN | FILE | FUNCTION |
LINE |
在特定上下文中使用的关键字 | |||
---|---|---|---|
associativity | convenience | dynamic | didSet |
final | get | infix | inout |
lazy | left | mutating | none |
nonmutating | optional | override | postfix |
precedence | prefix | Protocol | required |
right | set | Type | unowned |
weak | willSet |
一些常用的新增关键字解析
关键字 | 作用 | 示例 |
---|---|---|
final |
当你不希望某个类、函数、属性被重写时,可以添加该关键字. |
final class Person { }
|
defer |
当函数返回之前被调用,如果代码在defer 代码块之前返回则无法执行,一旦注册完毕则无法取消,多个defer 顺序是LIFO
|
func test() { defer { } }
|
guard |
它是if 的翻版,当条件满足时执行后续语句,否则执行代码块语句并返回,很好的解决了某些条件判断不满足需要返回的情况。 |
guard view is UIImageView else { return }
|
typealias |
类型别名 | typealias A Int |
5. 空格
Swift语言并不是像C/C++,Java那样完全忽视空格,Swift对空格的使用有一定的要求,但是又不像Python对缩进的要求那么严格。
在Swift中,运算符不能直接跟在变量或常量的后面。例如下面的代码会报错:
let a= 1 + 2
错误信息是: error: prefix/postfix '=' is reserved, 意思大概是等号直接跟在前面或后面这种用法是保留的。
只有这样写才不会报错:
let a = 1 + 2; // 编码规范推荐使用这种写法
let b = 3+4 // 这样也是OK的
6. 字面量
所谓字面量,就是指像特定的数字,字符串或者是布尔值这样,能够直接了当地指出自己的类型并为变量进行赋值的值, Swift是可以自行推断变量类型的。
。比如在下面:
42 // 整型字面量
3.14159 // 浮点型字面量
"Hello, world!" // 字符串型字面量
true // 布尔型字面量
7. 语法糖
在自己作用域下,访问自己的属性可以直接使用属性名,不再拥有下划线变量,函数同理。
Objective-C:
_label;
self.label;
self.view;
[self.view addSubview:self.label];
Swift:
label
self.label
view
view.addSubView(label)
如果在闭包中,则必须加上
self.
Objective-C:
void(^block)(void) = ^{
NSLog(@"%@",_label.text); // Block implicitly retains 'self'; explicitly mention 'self' to indicate this is intended behavior
NSLog(@"%@",self.label.text);
};
Swift:
let block = {
print(label.text) // Reference to property 'label' in closure requires explicit 'self.' to make capture semantics explicit
print(self.label.text)
}
在Swift中你经常可以看到这种用法
class Person {
static func person() -> Person {
return Person()
}
}
let p: Person = .person()
let color: UIColor = .red
当一个变量的类型已经确定时,我们可以省略该类型的命名前缀
8.闭包
为了防止在闭包中发生引用循环,采取以下两种方式:
unowned
:无主引用,该方式引用的对象是有值的,如果该对象被释放,调用时会抛出异常
weak
:弱引用,该方式引用的对象是可选值,对象被释放后无影响,但是使用时略微麻烦,需要添加?
let block1 = { [unowned self] in
print(self.label.text)
}
let block2 = { [weak self] in
print(self?.label.text)
}
9. 初始化
Swift限制所有的初始化方法均为init()
,该方法无返回值,需要将所有属性初始化完毕才可调用super.init()
可选值可以不初始化,默认为`nil,也可以直接在属性上将其初始化,或懒加载对应属性
class ViewController: UIViewController {
lazy var label: UILabel = {
let view = UILabel()
return view
}()
let fps: UInt
init(fps: UInt) {
self.fps = fps
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
return nil
}
}
10. 动态性
Swift是静态语言,但同时也支持OC的动态性
- 一个Swift类需要添加
@objc
并且集成NSObject
才有使用runtime
的能力,其属性仍然需要依次添加@objc
才能被runtime
捕获,如果希望整个类都能够使用@objc
,在类前添加@objcMember
即可。 - 通过
#selector()
方式调用的方法需要添加@objc
前缀。
11. 版本适配
随着新的版本发布,新提供的Api越来越多,为了适配低版本,Swift使用available
关键字来控制版本
@available(iOS 10.3, *) class Person {
static func person() -> Person {
return Person()
}
}
if #available(iOS 10.3, *) {
let p: Person = .person()
}
注意:在全局处需要使用@
前缀,非全局使用#
前缀
12. 宏定义
Swift没有宏定义,如果需要你只能使用全局函数或全局变量
但是编译宏仍然支持
#if DEBUG
// ....
#else
// ....
#endif
13. 忽略返回值
如果一个值仅写却未读,编译器会发出警告。
我们可以通过@discardableResult
来标记忽略该返回值的提示
class Person {
@discardableResult static func person() -> Person {
return Person()
}
}
let p: Person = .person()
也可以赋值给_
来忽略返回值
let p: Person = .person() // Immutable value 'p' was never used; consider replacing with '_' or removing it
let _ = Person.person()
14. 自动释放池
Swift的自动释放池为autoreleasepool
函数
autoreleasepool { () -> Result in
}
网友评论