Swift学习之旅

基本语法

  • 不要求每一行结束都有分号
  • 运算符不能直接跟在变量或常量后面
  • 可自动识别属性类别
  • 可选属性声明后没有提供初始值,那么默认值是nil
  • 使用操作符!去获取值为nil的可选变量会有运行时错误
    而可选类型对所有的类型都可用,并且更安全

Swift和Objective-C对比,新出现关键字

deinit
extension
inout
internal
operator
subscript
typealias

类型别名

typealias Feet = Int
var distance:Feet = 13

类型安全,在编译期间就进行类型检查

变量和常量定义

var 表示是变量,可以修改指针指向
let 表示是常量。

0b 二进制
0o八进制
0x十六进制

var age : Int?
表示age变量默认值是nil

switch

  • 这里我们需要注意 case 语句中如果没有使用 fallthrough 语句,则在执行当前的 case 语句后,switch 会终止,控制流将跳转到 switch 语句后的下一行。
    如果使用了fallthrough 语句,则会继续执行之后的 case 或 default 语句,不论条件是否满足都会执行。

字符串

var test = String("Hello world")
if test.isEmpty { //todo } 判断字符串是否为空

let stringA = String("haha")
stringA += "wawa" // 编译出错,let标识常量,不能修改
  • 字符串长度使用 String.characters.count 属性来计算
  • Int(String),转换字符串数字为整型

字符Character

  • let char: Character = "AB" // 会报错
  • let char1: Character = "" // 同样报错

数组

  • Array
    用var 修饰的数组时可变数组,反之用let声明的则是不可变数组。
var mutableArray : Array = ["xixi", "haha", "hoho"];
var mutableArray1 : [String] = ["xixi", "haha", "hoho"];
var emptyArray = [String]();
let unMutableArray = Array = ["xixi", "haha", "hoho"];
  • 初始化数组
    var someInts = [Int](repeating: 0, count: 3)
    var someInts[Int] = [1,2,3]
  • 添加元素,append或+=
  • 遍历
for (index, item) in someStrs.enumerated() {
    print("在 index = \(index) 位置上的值为 \(item)")
}
  • 合并 +
  • 数组个数 count

元组

  • 返回一个元组类型 func minMax(array:[Int])->(min:Int,max:Int)
  • 可选元组类型如(Int, Int)?与元组包含可选类型如(Int?, Int?)是不同的.可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。

字典

  • 定义
var someDict:[String:Int] = ["A":1,"B":2]
var someDict = [String:Int]()
  • 更新 someDict.updateValue(3, forKey: "A")
  • 删除 someDict.removeValue(forKey: 2)

函数

  • 如果为函数的参数指定默认值,则在调用函数时可以不传对应的参数
func makeCoffee(type : String = "卡布奇诺") {
    print(type);
}

makeCoffee() // 打印结果 卡布奇诺
makeCoffee(type: "拿铁") // 打印结果 拿铁
  • 内部参数
    func test(name:String, age:Int)->String {}
  • 外部参数,如果你提供了外部参数名,那么函数在被调用时,必须使用外部参数名
    func test(myName name:String,myAge age:Int)->String {}
  • inout 参数标识 和 c的指针一样
func swap(_ a:inout Int, _ b:inout Int) { }
var x = 1; var y = 5
swap(&x, &y) 
  • 函数类型(什么?!这是js吗)
func add(a:Int, b:Int)->Int {
    return a + b
}
var addition:((Int, Int)->Int) = add
print(addition(1,2))

Swift 中的类并不是从一个通用的基类继承而来。如果你不为你定义的类指定一个超类的话,这个类就自动成为基类。

可选链

可以通过连接多个可选链式调用在更深的模型层级中访问属性、方法以及下标。然而,多层可选链式调用不会增加返回值的可选层级。

如果你访问的值不是可选的,可选链式调用将会返回可选值。
如果你访问的值就是可选的,可选链式调用不会让可选返回值变得“更可选”。
因此:

通过可选链式调用访问一个Int值,将会返回Int?,无论使用了多少层可选链式调用。
类似的,通过可选链式调用访问Int?值,依旧会返回Int?值,并不会返回Int??。

扩展

添加计算型属性和计算型类型属性
定义实例方法和类型方法
提供新的构造器
定义下标
定义和使用新的嵌套类型
使一个已有类型符合某个协议

可选的协议要求

协议可以定义可选要求,遵循协议的类型可以选择是否实现这些要求。在协议中使用 optional 关键字作为前缀来定义可选要求。可选要求用在你需要和 Objective-C 打交道的代码中。协议和可选要求都必须带上@objc属性。标记 @objc 特性的协议只能被继承自 Objective-C 类的类或者 @objc 类遵循,其他类以及结构体和枚举均不能遵循这种协议。

使用可选要求时(例如,可选的方法或者属性),它们的类型会自动变成可选的。比如,一个类型为 (Int) -> String 的方法会变成 ((Int) -> String)?。需要注意的是整个函数类型是可选的,而不是函数的返回值。

协议中的可选要求可通过可选链式调用来使用,因为遵循协议的类型可能没有实现这些可选要求。类似 someOptionalMethod?(someArgument) 这样,你可以在可选方法名称后加上 ? 来调用可选方法。详细内容可在可选链式调用章节中查看。

下面的例子定义了一个名为 Counter 的用于整数计数的类,它使用外部的数据源来提供每次的增量。数据源由 CounterDataSource 协议定义,包含两个可选要求:

@objc protocol CounterDataSource {
    @objc optional func incrementForCount(count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

访问控制

模块和源文件

  • 在 Swift 中,Xcode 的每个 target(例如框架或应用程序)都被当作独立的模块处理。如果你是为了实现某个通用的功能,或者是为了封装一些常用方法而将代码打包成独立的框架,这个框架就是 Swift 中的一个模块。当它被导入到某个应用程序或者其他框架时,框架内容都将属于这个独立的模块。
  • 源文件就是 Swift 中的源代码文件,它通常属于一个模块,即一个应用程序或者框架。尽管我们一般会将不同的类型分别定义在不同的源文件中,但是同一个源文件也可以包含多个类型、函数之类的定义。
  • 一个 public 类型的所有成员的访问级别默认为 internal 级别,而不是 public 级别。如果你想将某个成员指定为 public 级别,那么你必须显式指定。这样做的好处是,在你定义公共接口的时候,可以明确地选择哪些接口是需要公开的,哪些是内部使用的,避免不小心将内部使用的接口公开。
  • 我们甚至可以在子类中,用子类成员去访问访问级别更低的父类成员,只要这一操作在相应访问级别的限制范围内(也就是说,在同一源文件中访问父类 private 级别的成员,在同一模块内访问父类 internal 级别的成员)

自定义运算符

当使用自定义运算时, 传入的参数至少要有一个当前对象, 否则编译不会通过。定义前缀或后缀运算符时,不要指定优先级。但是,如果将前缀和后缀运算符应用于相同的操作时,则首先进行后缀运算。

你可能感兴趣的:(Swift学习之旅)