Swift从零开始 - 基本数据类型

139 阅读6分钟

变量和常量

使用关键字let 声明常量
使用关键字var 声明变量

let hoursOneday = 24
var currentHour = 10

hoursOneday = 25 // error
curentHour = 12

var x = 0, y = 0, z = 0, des = "trangle"

标注变量或常量的类型

var personName : String 

personName = "davin" 
personName = 18 // error

Swift是类型安全的语言, 明确变量或常量存储的值类型之后, 不可以赋值其他类型的值,会导致编译报错。

变量和常量的命名

Swift可以使用更多的字符来给变量和常量命名, 如:Unicode字符,表情符,制表符等。

但不能包含空白字符,箭头等,也不能以数字开头

let 🐶 = “dog”
var 你好 = “hello”

print("\(你好)\(🐶) ,欢迎你") //字符串插值: \()

数值类型

整数

Swift 提供了8, 16, 32, 64位编码的有符号和无符号整数
命名方式: UInt8, Int32 ... ... Int, UInt
Int 和 UInt 拥有与当前平台的原生字相同的字节长度
通过 max 和 min 属性可以访问每个整数类型的最小值 和 最大值

let a : UInt8 = 256 //error overflow 超出取值范围
print("UInt8 最小值:\(a.min), 最大值: \(a.max)) => Uint8 最小值: 0, 最大值: 255

浮点数

Double : 64位浮点数, 精度 至少有15位
Float: 32位浮点数, 精度至少有6位

Screenshot 2023-11-29 at 22.02.37.png

Bool

取值范围为:true & false
Swift的类型安全机制会阻止使用一个非布尔量的值替换掉Bool

let i = 1
if i { // error
}

需修改成

if i==1 {
}

类型别名

使用关键字 typealias , 为已存在的类型定义别名, 以更符合业务场景

typealias Age = UInt8
let age: Age = 18

Tuple

元组可以将多个值 合并成 单一的复合值 类型, 元组内的值可以是任意类型, 且不必是同一类型

let error = (401, "客户端错误")
print(error)

元组内的元素可以指定对应的名称 (如果没有对应的元素名, 也可以使用下标访问)

let error = (errorCode: 401, errorMessage: "客户端错误")
print(error.errorCode)
print(error.errorMessage)

Tuple的修改

  • 使用 var 声明的 元组 就是可变元组, let 定义的 就是 不可变元组\
  • 不管是可变 还是 不可变, 元组在创建后,就不能增加 和 删除 元素\
  • 可以对可变元组的元素进行修改, 但是不能改变其元素类型\
  • 如果元组的元素类型是Any类型, 可以改为任意类型
var error = (errorCode: 401, errorMessage: "客户端错误")
error.errorCode = 502
error.errorMessage = "服务端错误"

error.erroMessage = 502 //error 类型不匹配,也可以通过下面的解法处理

var error : (errorCode: Int, errorMessage: Any) = (errorCode : 401, errorMessage: "客户端错误")

error.errorCode = 502
error.errorMessage = 502

Tuple的分解

将一个元组的内容分解成单独的常量或变量
如果只使用其中的一部分数据, 不需要的数据可以用下划线(_)替代

let error = (401, "客户端错误")
let (errorCode, errorMessage) = error
print(errorCode)
print(errorMessage)


let (_, errorMessage2) = error
print(errorMessage2)

Tuple作为函数返回值

使用Tuple为函数 返回 多个返回值
返回值的 Tuple 可以在函数的返回类型部分被命名

func httpRquest(url:String) -> (errorCode : Int, errorMessage : Any) {
    return (401, "客户端错误")
}

Optional

为什么需要Optional?

OC中的 nil 是无类型的指针(如果想表示 某一个具体类型的nil, 无法区分, 因为都是nil)
OC中的 数组, 字典, 集合等 不允许传入nil(无法将空置作为占位符放在集合里)
OC中 所有对象的变量都可以为nil (需要很多空值判断, 来进行下一步的操作)
OC中 nil 只能用在对象上,而在其他地方又有其他特殊值, 如 NSNotFound, 表示值的缺失

所以 Swift 引入了 Optinal,通过在变量后面加 ?来表示, 他有两层含义:

  • 这里有一个值, 值为x
  • 这里根本没有值

可以将 可选变量 赋值为nil 来将其设置为没有值

OC 中的nil 是 一个指向不存在对象的指针
Swift中, nil 不是指针, 而是一个值缺失的特殊类型, 任何类型的可选项都可以设为nil(不仅是对象) Swift中, 只有可选项 才可设为nil

var str:String? = "abc"
let strCount = str.count  //error 

可选项 是无法直接使用的,需要用!展开后才可使用(意思是我清楚可选项的内容有值, 可以展开)

Optional-if 展开

// Optional - if 展开
var str:String? = "abc"

if str!=nil {
   let count = str!.count
}

Optional 强制展开

// Optional 强制展开, 需保证可选值非空
var str:String? = "abc"
let count = str!.count

var str:String? = nil
let count = str!.count //error

Optional Binding

可以使用可选项绑定 来 判断可选项是否包含值, 如果包含就把值赋给一个临时的常量或变量
可选绑定可以与 if 和 while 的语句使用来检查可选项内部的值, 并赋值给一个常量或变量
同一个if 语句中可以包含多个 可选项绑定,用逗号分隔, 如果任一可选绑定结果是nil 或者 布尔值为false, 那么整个if 判断会被看作false

var str:String? = "abc"
if let actualstr = str {  // 判断str是否为nil, 如果不为nil 则赋值给actualstr
    let count = actualstr.count
    print(count)
}

Optional 隐式展开

有些可选项一旦被设定值后, 就会一直拥有值,在这种情况下, 就可以去掉检查,也不必每次访问的时候都进行展开
通过在声明的类型后加叹号(String!)而非问好(String?)来书写隐式展开可选项
隐式展开可选项主要被用在Swift的初始化过程中

var str:String! = "abc"
let count = str.count
print(count)

Optional Chaining

可选项后面加问号? 如果可选项不为nil, 返回一个可选项结果, 否则返回nil

var str:String? = "abc"
let count = str?.count

let count2 = count - 1 // error, 因为count 此时还是一个可选项, 需要对count进行 强制展开 或 判断展开,绑定等才可以使用

Nil-Coalescing Operator

使用空合运算符 ?? 来提供默认值


let imagePaths = ["star": "/glyphs/star.png",                  "portrait": "/images/content/portrait.jpg",                  "spacer": "/images/shared/spacer.gif"]
                  
let defaultImagePath = "/images/default.png"
let heartPath = imagePaths["heart"] ?? defaultImagePath
print(heartPath)
// Prints "/images/default.png"

?? 操作符还可以与右边的另一个' Optional '实例一起使用。因此,您可以链接多个?? 操作符在一起。

let shapePath = imagePaths["cir"] ?? imagePaths["squ"] ?? defaultImagePath
print(shapePath)
// Prints "/images/default.png"

Optional 的原理

A type that represents either a wrapped value or the absence of a value.


@frozen public enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none
    case some(Wrapped)
    
    public init(_ some: Wrapped)
    
    @inlinable public func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U?
    
    @inlinable public func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?
    
    public init(nilLiteral: ())
    
    @inlinable public var unsafelyUnwrapped: Wrapped { get }

Optional 类型实际是标准库里的一个 enum 类型, 它包含两个可选值: Optional.none & Optional.some(Wrapper)

Optional.none : 代表没有值
Optional.some(Wrapper) : 代表有值,且值是x

 let str : String? = “abc”
 等价于 
 let str : Optional<String> = “abc”  
 Int? 相当于简写
 
 let number: Int? = Optional.some(42)
 let noNumber: Int? = Optional.none
 print(noNumber == nil)
 // Prints "true"

unsafelyUnwrapped 函数 相当于存储的是 Optional 包装的值, 等价于 !操作符, 如果使用此函数展开, 要确保包装值不为nil!!

let number: Int? = Optional.some(42)
let noNumber: Int? = Optional.none
 
let num1 = number.unsafelyUnwrapped //42
let num2 = noNumber.unsafelyUnwrapped // error