简单掌握Swift基本数据类型

1. Swift中定义常量和变量

1.1 声明常量和变量

1.使用关键字 let 来声明常量,常量声明之后就不能再修改了。
2.使用关键字 var 来声明变量。

let maxCount = 10
var currentCount = 0

maxCount = 9 //这句代码会报错,let声明的常量不能被修改
currentCount = 1

在OC里面,没有特殊的说明,我们声明的都是变量,要在OC里面声明常量,我们一般使用
1.宏定义
2.const修饰词
可以在一行中声明多个变量或常量,用逗号分隔

var x=0, y=0, z=0

1.2 类型标注

1.在声明一个变量或常量的时候提供类型标注,来明确变量或常量能够存储值的类型
2.添加类型标注的方法是在变量或常量的名字后边加一个冒号,再跟一个空格(空格必须的),最后加上要使用的类型名称
3.可以在一行中定义多个相关的变量为相同的类型,用逗号分隔,只要在最后的变量名字后边加上类型标注

var str: String
str = "hello"
str = 10 //这句代码会报错,声明类型是 String,不能赋数字类型
var str1, str2 str3: String
str1 = "111"
str2 = "222"
str3 = "333"

1.3 变量和常量的命名

1.常量和变量的名字几乎可以使用任何字符,甚至包括Unicode字符
2.常量和变量的名字不能包含 空白字符、数学符号、箭头、保留的Unicode码位、连线和制表符。也不能以数字开头,尽管数字几乎可以使用在名字其他的任何地方。

swift虽然命名可以使用的字符很多,但是大家平常写代码最好还是规范命名,尽量做到 看其名,知其意。正确并形象地给变量命名,不仅可以增加程序的可读性,也是程序员编程风格的一种反映

1.4 打印常量和变量

1.print方法
2.字符串插值方法

let str = "world"
print("hello, world")
print("hello, \(str)")

2. Swift中的数值类型

2.1 整数

1.Swift提供了8、16、32、64位编码的有符号和无符号整数
2.命名方式:例如8位无符号整数的类型是Uint8,32位有符号整数的类型是Int32
3.通过 min 和 max 属性来访问每个整数类型的最小值和最大值
4.Swift提供了一个额外的整数类型:Int,它拥有与当前平台的原生字相同的长度,假如 当前平台是32位的,Int 就是32位的,假如当前平台是64位的,Int 就是64位的
5.同时Swift也提供 Uint 类型,来表示平台长度相关的无符号整数
6.建议在用到整数的地方都使用 Int

2.2 浮点类型

1.Double:64位浮点数,至少有15位数字的精度
2.Float:32位浮点数,至少有6位数字的精度
3.在两种类型都可以的情况下,推荐使用 Double 类型

2.3 Bool

1.Bool:true 和 false
2.Swift 的类型安全机制会阻止你用一个非布尔量的值替换掉 Bool

//编译错误
let i = 1
if i {
    print(i)
}

//正确写法
let i = 1
if i==1 {
    print(i)
}

2.4 类型别名

1.类型别名是一个为已存在的类型定义的一个可选择的名字
2.可以用关键字 typealias 定义一个类型的别名

typealias AudioSample = UInt8
let sample: AudioSample = 32

3. Swift的 Tuple(元组) 类型

3.1 元组定义

1.元组把多个值合并成单一的复合型的值,多个值统一放在小括号里面,之间用逗号分隔
2.元组内的值可以是任何类型,而且可以不必是同一类型

let error = (404, "没找到网络地址")
print(error.0) //404
print(error.1) //没找到网络地址

3.元组中的每一个元素可以指定对应的元素名称
4.如果没有指定名称的元素也可以使用下标的方式来引用

let error = (errCode: 404, errMsg: "没找到网络地址")
print(error.errCode) //404
print(error.errMsg) //没找到网络地址

3.2 元组修改

1.用 var 定义的元组是可变元组,let 定义的就是不可变元组
2.不管是可变还是不可变元组,元组在创建后就不能增加和删除元素
3.可以对可变元组的元素进行修改,但是不能改变其类型
4.any 类型可以改为任何类型

var error: (Any, String) = (404, "没找到网络地址")
error.0 = 500
print(error) //(500, "没找到网络地址")
error.0 = "abc"
error.1 = "未知错误"
print(error) //("abc", "未知错误")

3.3 元组分解

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

let error = (404, "没找到网络地址")
let (_, errMsg) = error
print(errMsg) //没找到网络地址

3.4 作为函数返回值

1.使用元组为函数返回多个值
2.返回值的元组可以在函数的返回类型部分被命名

func requestData(url: String) -> (errCode: Int, errMsg: String) {
    return (404, "没找到网络地址");
}

4. Swift字符串

4.1 初始化字符串

1.字面量--被双引号("")包裹的固定顺序文本字符
2.初始化器语法
3.isEmpty 检查是否为空串

var emptyStr = ""
var emptyStr2 = String()
if emptyStr.isEmpty {
    print("emptyStr is empty")
}

var someStr = "some string"
var someStr2 = String("some string")
if !someStr2.isEmpty {
    print(someStr2);
}

4.多行字面量
多行字符串字面量是用三个双引号引起来的一系列字符;把所有行包括在引号内,开始和结束默认不会有换行符;当你的代码中在多行字符串字面量里包含了换行,那个换行符同样会成为字符串里的值,如果你想要使用换行符来让你的代码易读,却不想让换行符成为字符串的值,那就在那些行的末尾使用反斜杠(\)

let multiLineStr = """
Q: What's your name?
A: my name is joke.
Q: What's your job?
A: I'm an iOS developer.
Q: You have a very good job.
"""
print(multiLineStr)

4.2 字符串的常见操作

1.let 指定的字符串是不可以修改的,var 指定的字符串可以修改,可以使用“+”来拼接字符串

let letString = "hello"
letString += " world!" //编译报错

var varString = "hello"
varString += " world!"
print(varString) //hello world!

2.字符串是值类型,String 值在传递给方法或者函数的时候会被复制过去,赋值给常量或者变量的时候也是一样,Swift 编译器优化了字符串使用的资源,实际上拷贝只会在确实需要的时候才进行

var str: String = "abc"
var str1 = str
print(str==str1) //true
str += "def"
print(str) //abcdef
print(str1) //abc
print(str==str1) //false

3.操作字符,可以通过 for-in 循环遍历 String 中的每一个独立的 Character,String 值可以通过传入 Character 数组来构造

for character in "I'm an ios developer" {
    print(character)
}
let iosCharacter: [Character] = ["i", "O", "S"]
let iosString = String(iosCharacter)
print(iosString) //iOS

4.字符串拼接
使用加运算符(+)创建新的字符串
使用加赋值符号(+=)在已经存在的 String 值末尾追加一个 String 值
使用 String 类型的 append() 方法来可以给一个 String 变量的末尾追加 Character 值

var str = "hello"
var newStr = str + " oc"
print(newStr) //hello oc
str += " swift"
print(str) //hello swift
str.append(" world") //hello swift world
print(str)

5.字符串插值,是一种字符串字面量构造新 String 值的方法,混合了 常量、变量、字面量、表达式;每一个插入到字符串字面量的元素都要被一对圆括号包裹,然后使用反斜杠前缀;字符串插值类似于 NSString 的 stringWithFormat 方法

let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
print(message) //3 times 2.5 is 7.5

6.字符串索引
每一个 String 值都有相关的索引类型,String.Index,是个结构体类型, 它相当于每个 Character 在字符串中的位置;startIndex 属性来访问 String 中第一个 Character 的位置,endIndex 属性就是 String 中最后一个字符后的位置;如果 String 为空,则 startIndex 与 endIndex 相等

let str = "hello world!"
print(str[str.startIndex]) //h
print(str[0]) //编译报错

使用 index(before:) 和 index(after:) 方法来访问给定索引的前后
要访问给定索引更远的索引,你可以使用 index(_:offsetBy:)

let str = "hi world"
let index1 = str.index(after: str.startIndex)
let index2 = str.index(before: str.endIndex)
let index3 = str.index(str.startIndex, offsetBy: 3)
print(str[index1]) //i
print(str[index2]) //d
print(str[index3]) //w

7.字符串插入
插入字符,使用 insert(_:at:) 方法
插入字符串,使用 insert(contentsOf:at:) 方法

var welcome1 = "hello"
welcome1.insert("!", at: welcome1.endIndex)
print(welcome1) //hello!

var welcome2 = "hello"
welcome2.insert(contentsOf: " there", at: welcome2.endIndex)
print(welcome2) //hello there

8.字符串删除
移除字符,使用 remove(at:) 方法
移除一小段特定范围的字符串,使用 removeSubrange(_:) 方法

var welcome1 = "hello there!"
welcome1.remove(at: welcome1.index(before: welcome1.endIndex))
print(welcome1) //hello there

var welcome2 = "hello there!"
let range = welcome2.index(welcome2.endIndex, offsetBy: -5) ..< welcome2.endIndex
welcome2.removeSubrange(range)
print(welcome2) //hello t

9.子字符串
使用下标或者类似 prefix(_:) 的方法得到的子字符串是 Substring 类型
Substring 拥有 String 的大部分方法
Substring 可以转成 String 类型

let welcome = "hello,there!"
let index = welcome.firstIndex(of: ",") ?? welcome.endIndex
let subString = welcome[..<index]
print(subString) //hello
let newString = String(subString)
print(newString) //hello

之所以会搞一个 Substring 类型,很大程度上是为了性能而考虑的。
子字符串重用一部分原字符串的内存
修改字符串或者子字符串之前都不需要花费拷贝内存的代价
String 和 Substring 都遵循 StringProtocol 协议,也就是说它基本上能很方便地兼容所有接受 StringProtocol 值的字符串操作函数

10.字符串比较
字符串和字符串相等性(==和!=)
前缀相等性 hasPrefix(:)
后缀相等性 hasSuffix(
:)

var welcome1 = "hello, world"
var welcome2 = "hello, world"
var welcome3 = "hello"
print(welcome1 == welcome2) //true
print(welcome1 == welcome3) //false
print(welcome2.hasPrefix("hello")) //true
print(welcome3.hasPrefix("hello")) //true

5. Optional(可选)类型

5.1 Optional 定义

1.通过在变量类型后面加 ? 表示:
这里有一个值,他等于 x
或者
这里根本没有值
2.你可以通过给可选变量赋值一个 nil 来将之设置为没有值
在 OC 中 nil 是一个指向不存在对象的指针
在 Swift 中,nil 不是指针,他是值缺失的一种特殊类型,任何类型的可选项都可以设置成 nil 而不仅仅是对象类型
3.可选项是没法直接使用的,需要用 ! 展开之后才能使用,使用 ! 来获取一个不存在的可选值会导致运行错误,在使用 ! 强制展开之前必须确保可选项中包含一个非 nil 的值

var str: String = nil; //编译报错 swift中 不是可选变量 不能赋值为nil
var str1: String? = nil

var str2: String? = "abc"
let count = str.count //编译报错 可选值不能直接使用

var str3: String? = "abc"
if str3 != nil {
    let count = str3!.count //通过 ! 展开可选值 使用
    print(count)// 3
}

5.2 Optional 绑定

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

var str: String? = "abc"
if let actualStr = str {
    let count = actualStr.count
    print(count)
}

5.2 Optional 隐式展开

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

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

5.3 Optional 可选链

1.可选项后面加问号来使用
2.可选链调用的结果一定是一个可选值

var str: String? = "abc"
let strCount = str?.count //使用可选链,可选链语句返回的值也是个可选值,所以 strCount 也是个可选值
if strCount != nil {
    let lastIndex = strCount! - 1
    print(lastIndex) //2
}

5.4 Optional 实现原理

1.Optional 其实是标准库里的一个 enum 类型
2.Optional 是用标准库实现语言特性的典型,下面是从标准库拷贝来的Optional源码

@frozen public enum Optional<Wrapped> : ExpressibleByNilLiteral {

    /// The absence of a value.
    ///
    /// In code, the absence of a value is typically written using the `nil`
    /// literal rather than the explicit `.none` enumeration case.
    case none

    /// The presence of a value, stored as `Wrapped`.
    case some(Wrapped)

    /// Creates an instance that stores the given value.
    public init(_ some: Wrapped)

    /// Evaluates the given closure when this `Optional` instance is not `nil`,
    /// passing the unwrapped value as a parameter.

Optional.none 就是 nil
Optional.some 则包装了实际的值

//下面用 Optional 枚举来定义一个可选值
var str: Optional<String> = "abc" //和语句 var str: String? = "abc" 一样
if let actualStr = str {
    let count = actualStr.count
    print(count) //3
}
  1. Optional 有个泛型属性 unsafelyUnwrapped,用来获取可选项实际的值。unsafelyUnwrapped 在标准库的说明如下。
    /// The wrapped value of this instance, unwrapped without checking whether
    /// the instance is `nil`.
    ///
    /// The `unsafelyUnwrapped` property provides the same value as the forced
    /// unwrap operator (postfix `!`). However, in optimized builds (`-O`), no
    /// check is performed to ensure that the current instance actually has a
    /// value. Accessing this property in the case of a `nil` value is a serious
    /// programming error and could lead to undefined behavior or a runtime
    /// error.
    ///
    /// In debug builds (`-Onone`), the `unsafelyUnwrapped` property has the same
    /// behavior as using the postfix `!` operator and triggers a runtime error
    /// if the instance is `nil`.
    ///
    /// The `unsafelyUnwrapped` property is recommended over calling the
    /// `unsafeBitCast(_:)` function because the property is more restrictive
    /// and because accessing the property still performs checking in debug
    /// builds.
    ///
    /// - Warning: This property trades safety for performance.  Use
    ///   `unsafelyUnwrapped` only when you are confident that this instance
    ///   will never be equal to `nil` and only after you've tried using the
    ///   postfix `!` operator.
    @inlinable public var unsafelyUnwrapped: Wrapped { get }

理论上我们可以直接调用 unsafelyUnwrapped 获取可选项的值

var str: String? = "abc"
let count = str.unsafelyUnwrapped.count
print(count) //3
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342