swift学习总结
语言基础
程序:指令的集合写。写程序就是写一系列的指令去实现我们想做的事情
编译:将程序语言转换成计算机能够理解的机器语言或者中间代码的过程
冯洛伊曼体系结构计算机:
1.使用二进制
2.程序存储执行
变量和常量
定义变量和常量是为了保存数据。变量和常量就是某种类型值得存储空间。
var a:Int = 10
a=100
var b:10
b=100
var c=1000
let d:Int = 10 //常量只能一次赋值
//d=100 //compiler error
let e=100
说明:swift有强大的类型推断,所以定义变量或者常量时尽量用类型推断而不用手动指定类型,如果可以的话应该尽量使用常量而不是变量
语言元素
var a:Int = 10
关键字:有特殊含义的单词
标识符:给变量,常量,函数,类,结构,协议,方法,属性,等起名字
标识符命名规则:
1.字母数字下划线组成,数字不能开头
2.大小写敏感
3.不能使用关键字做标识符
4.使用驼峰命名法(命名变量常量函数方法属性第一个单词小写,从第二个单词开始每个单词首字母大写;命名类,结构,协议,枚举每个单词首字母都要大写)
5.见名知意
6.命名私有的属性和方法时以下划线开头
运算符:swift中的运算符其实都是函数
赋值运算符= , +=,-=,
算数运算符:+ - * / %
关系运算符:=,!= ,<,<=,>,>= 产生bool值
逻辑运算符&& , || , !(与,或,非)
三元条件运算符:? :
其他运算符:[]下标运算符 , . , ?? 可空类型 有值取前面的 没值取后面的, ? ,!
字面(常)量:
整数字面量:10、1_123_567、0x10、0o10、0b10
小数字面量:123.45、1.245e2、0xab.cdp2
字符字面量:“o”、“\n”"\u{41}" "\u{e9}"
字符串字面量:“hello”
布尔字面量:true,false
空值字面量:nil
类型字面量:String.self、
分隔符:将不同的语言元素符号分开
swift中每个语句后面不用分号,写代码时尽量保证一行只有一条语句这样就可以省略掉分号。
循环和分支结构
循环
说明:在循环中可以使用break关键词来提前终止循环,也可以使用continue关键词循环直接进入下一轮,但是应该尽量减少岁break和continue的使用,因为他们不会使你的程序变得更好。
var sum=0
for i in 0...9{
sum +=i
}
var sum = 0
var i=0
while i<10{
sum += i
i += 1
}
var sum = 0
var i=0
repeat {
sum += i
i += 1
}while i<10
综合案列Craps赌博游戏。
第一轮如果为7或11玩家胜2,3,12庄家胜 其他下一轮
第二轮如果为7 庄家胜 如果为第一轮出现的点 玩家胜否则继续直到分出胜负
funk roll()->Int{
return Int(rac4drandom_uniform(6)+1)
}
let firstPoint=roll()+roll()
print("玩家摇出了\(firstPoint)")
var needsFoOn = false
swich firstPoint{
case 7,11:
print("玩家胜")
case 2,3,12:
print("庄家胜")
defalt:
needsGoOn=true
}
while needsGoOn{
let currentPoint = roll()+roll()
print("玩家摇出了\(currentPoint)")
if currentPoint==7{
print("庄家胜")
needsGoOn = false
}
else if firstPoint==currentPoint{
print("玩家胜")
needsGoOn = false
}
else{
neesdGoOn = true
}
}
穷举法:穷尽所有可能性直到找到正确答案
下面的程序实现了百钱买百鸡问题;问题的求解。
for i in 0...20{
for j in 0...33{
let k=100-j-i
if 5*i+3*j+k/3==100 &&k%3==0{
print("母鸡\(i)公鸡\(j)小鸡\(k)")
}
}
}
分支
let sales = 700000
if sales <100000 {
print("去找财务领工资")
}
else if sales<300000 {
print("还需要加油啊")
}
else if sales <500000 {
print("升值加薪不是梦")
}
else{
print("老板娘就是你啦!")
}
let score = 90
let msg:String
swich score{
case 100...90: msg="A"
case 80...89:msg="B"
case 60...79:msg="C"
defalt: msg="D"
}
print(msg)
容器
数组
数组使用连续空间保存
-创建数组
let array:[Int]=[]
let array:Arrat<Int>=[]
let array1 = [1,2,3,4,5]
let array2 = [Int](count:5),repeatedValue:0)
var array3 = Array<Int>(count:5,repeatedValue:0)
-添加元素
array1.append(3)
array1.insert(1,atIndex:0)
array1.insert(4,atIndex:array,count)
array1 +=[5,6,7]
-删除元素
array1.removeFirst()
array1.removeAtIndex(2)
array1.removeLast()
array1.removeRange(1...2)
array1.removeAll()
-修改元素
array1[0]=100
array1[array1.count-1]=500
-遍历数组
//1.
for i in 0..<array1.count{
print(array1[i])
}
//2.
for x in array1{
print(x)
}
for x in array1[1..3]{
print(x)
}
>**for..in循环是一个只读循环,这也就意味着在循环过程中不能对其元素进行修改**
//3.
for(i,temp)in array1.enumerate(){
if i ==0 {
array[i]=5
}
print("\(i).\(temp)")
}
说明操作数组时最重要的是不要越界访问元素。数组对象的count属性表明了数组中有多少个元素,那么有效的小标是0...count-1.
数组中的元素也可以是数组,因此我们可以构造多维数组。最常见的是二维数组,它相当于是一个有行有列的数组,数组中的每个元素代表一行,该数组中的每个元素代表行里面的列。二维数组可以模拟现实世界中的表格,数学上的矩阵。棋类游戏的棋盘·2D游戏中的地图,所以实际开发中使用非常广泛。
func randomInt(min: UInt32, max: UInt32) -> Int {
return Int(arc4random_uniform(max - min + 1) + min)
}
let namesArray = ["关羽", "张飞", "赵云", "马超", "黄忠"]
let coursesArray = ["语文", "数学", "英语"]
var scoresArray = [[Double]](count: namesArray.count, repeatedValue: [Double](count: coursesArray.count, repeatedValue: 0))
for i in 0..<scoresArray.count {
for j in 0..<scoresArray[i].count {
scoresArray[i][j] = Double(randomInt(50, max: 100))
}
}
for (index, array) in scoresArray.enumerate() {
var sum = 0.0
for score in array {
sum += score
}
let avg = sum / Double(coursesArray.count)
print("\(namesArray[index])的平均成绩为: \(avg)")
}
for i in 0..<coursesArray.count {
var sum = 0.0
for row in 0..<scoresArray.count {
sum += scoresArray[row][i]
}
let avg = sum / Double(namesArray.count)
print("\(coursesArray[i])课的平均成绩为: \(avg)")
}
集合
集合在内存中是离散的,集合中的元素通过计算HashCode来决定放在哪个位置,集合中不允许有重复元素
-创建集合
let a:Set<Int>=[1,2,3,4,5]
-添加元素
a.insert()
-删除元素
a.remove(具体的一个元素)
a.removeAll()
-集合运算(交集、并集、差集)
交集
set1.intersect(set2)
并集
set1.union(set2)
差集
set1.subtract(set2)
字典
字典是以键值对组合的方式保存数据的容器,字典中的每个元素都是键值对组合,通过键可以找到对应的值,字典里面的键也是采用哈希存储的
-创建字典
let dict = [
1:"hello",
2:"good",
3:"meili",
4:"laaa"
]
-添加元素
dict[5]="didida"
-删除元素
dict[5]=nil
dict.removeValueForKey[5]
-修改元素
dict[3]="nice"
-字典的遍历
for key in dict.keys{
print("\(key)-->\(dict[key]!)")
}
for value indivt.value{
print(value)
}
for (index,value) in dict.enumerate(){
print("\(index).\(value.0)-->\(value.1)")
}
重要操作
1.排序
.sort
.sortInPlance
2.过滤()
array.filter{ 过滤条件 }
//筛选掉不满足条件的元素
3.映射
//对数据按照一定条件进行变换处理
array.map{映射条件}
4.归约
array.reduce(初始值,combine:归约方式比如加减乘除什么的)
函数和闭包
函数是独立的可重复使用的模块,如果程序中出现了大量重复代码,通常都可以把这部分代码封装成一个独立函数。在swift中,函数是一个“一等公民” 函数可以作为类型来使用,也就是说函数可以赋值给变量或参量,也可以将函数作为函数的参数或者返回值使用,还可以使用高阶函数
func 函数名([参数1:类型,参数2:类型])[throws||rethrows]->[返回值]{
函数执行体
[return]
}
-外部参数名
-inout参数
func swap (inout x:Int,inout y:Int)->Void{
let temp = x
x = y
y = temp
}
var x=5,y=6
swap(&x, y: &y)
print("x=\(x)")
print("y=\(y)")
//inout - 输入输出参数(不仅将数据传入函数还要从函数中取出数据)
-可变参数列表
func sum(nums:Int...)->Int{
var total = 0
for num in nums {
total += num
}
return total
}
print(sum(15,25,35,77,88,99,58,60,120))
print(sum(25,33))
闭包就是没有名字的函数或者称之为函数表达式,在Oc中叫block。如果一个函数的参数类型是函数我们可以传入一个闭包;如果一个函数的返回类型是函数我们可以返回闭包;如果一个类的某个属性是函数我们也可以将一个闭包表达式赋值给它。
{([参数列表])[->返回类型] in 代码}
面向对象编程(oop)
基本概念
对象:接收消息的单元,是一个具体的概念
类:对象的蓝图和模板 类是一个抽象概念
消息:对象之间通信的方式,通过给对象发消息可以让对象执行对应的操作来解决问题
四大支柱
抽象:定义类的过程就是一个抽象的过程,需要做数据抽象和行为抽象,数据抽象找到对象的属性(保存对象状态的存储属性),行为抽象找到对象的方法(可以给对象发的消息)
封装:观点一:我们在类中写的方法其实就是在封装API,方法的内部实现可能会很复杂,但是这些对调用者来说是不可见的,调用者只能看到方法有一个简单清晰的接口,这就是封装
观点二:将对象的属性和操作这些属性的方法绑定在一起。
观点三:隐藏一切可以隐藏的实现细节,只提供简单的界面或接口
继承:得到被继承方的方法、属性
多态:同样的对象接收同样的消息实现不同的结果
三个步骤
1.定义类
-数据抽象
-存储属性
-行为抽象
--方法(写到类里面的函数就是方法)
-对象方法:给对象发消息
-类方法:给类发的消息,与对象的状态无关
--计算属性
-构造器
-指派构造器
-便利构造器
-必要构造器
2.创建对象
3.给对象发消息
相关内容
-枚举
-结构体
总结类和结构的区别到底有哪些?什么时候该使用类什么时候该使用结构
-拓展(extension)
.类的拓展
extension String {
var length: UInt32 {
get { return UInt32(self.characters.count) }
}
subscript(index: Int) -> Character {
get { return self[self.startIndex.advancedBy(index)] }
}
}
.协议的拓展相当于是默认执行
-运算符重载
-下标运算(subscript)
-访问修饰符
-private
-internal
-public
面向协议编程(pop)
protocol 协议名[:父协议]{
//方法的集合
}
1.能力:遵循了协议就意味着具备了某种能力
2.约定:遵循了协议就一定要实现协议中的方法
3.角色:一个类可以遵循多个协议, 一个协议可以被多个类遵循, 遵循协议就意味着扮演了某种角色, 遵循多个协议就意味着可以扮演多种角色
设计模式
-代理模式
-委托回调
-设计一个协议,被委托方遵循协议并实现协议方法
-委托方有一个属性是协议类型的,通过该属性可以调用协议中的方法
-委托方的协议类型通常是可空类型,因为要写成weak引用
依赖倒转原则
其他
-协议组合:protocol<协议1,协议2,...>
-可选方法
-协议拓展:对协议中的方法给出默认实现
泛型
让类型不再是程序中的硬代码
-泛型函数
-泛型类,结构,枚举
相关知识
-泛型限定
-where子句
异常处理
enum Myerror:ErrorTYpe{
case A
case B
case C
}
-throw(抛出错误)
-rethrows、throws(提醒这里可能出错)
-do(执行)
-catch(捕捉错误)
-try(尝试执行)
边角知识
-ARC
—正则表达式
-嵌套类型