赞
踩
Swift5.1 https://docs.swift.org/swift-book/LanguageGuide/Subscripts.html
1、swift没有隐式转化
Swift中没有隐式转化,不会将整形自动转成浮点型
let m = 32
let n = 3.14
let result = m + n 错误写法
2、省略; 省的是变量后的类型,可以类型推导
3、类型推导 option+鼠标左键
4、
//1、if的使用
//if后的()可略
//判断句不再有非0即真.必须有明确bool值 true/false
5、guard的用法
07示例代码写的什么玩意
guard只能用在函数中,不能像if一样用在函数外;和if用法相似,后边都加条件表达式;和else连用,有guard必会带else;与if不同的是紧跟if的大括号是条件语句成立时,而guard后紧跟的大括号里的大括号是条件语句不成立才走,条件语句成立时则走大括号外边;guard最近的大括号里需要和return,break,continue,throw联用
6、08-switch特出用法
Switch
Switch后的小括号可以省
默认每个case是包含break,如果想case穿透用fallthrough
default不能写在最上边,只能写在最下边
switch 后边的变量不仅可以是整型,也可以是double,字符串,对象类型;
可以用区间 let range = 0…10 [] 可计数 0.01…0.5 不可计数 0..<10 [) 可计数才能遍历;元组做条件;where;case后可以写两个;
//fallthrough case穿透
//case后跟多个条件
//不可以不写default
//default不能随便放
//能判断对象,浮点型,字符串等
元组;
区间;
//switch
//一、区间匹配
//二、元组匹配 即一对数据
//三、值绑定
//四、根据条件绑定,where,只有where后的条件表达式为真才赋值并执行case后的语句
7、Swift下划线的作用:_忽略 https://www.jianshu.com/p/fcdfc8306a94
//1、格式化数字,增加阅读性
//2、忽略元组的元素值;使用元组时,如果有元素不需要使用,可以使用下划线将元素忽略
//3、忽略区间值
//4、忽略外部参数名
//1》忽略外部参数名
//方法(类或实例)中,方法的第二个参数名及后续参数名,默认既是内部参数名又是外部参数名,如果不想提供外部参数名,可以在参数前加下划线来忽略外部参数名
//2》忽略具有默认值的参数的外部参数名
//当函数的参数有默认值时,swift自动为参数提供与参数名一致的默认外部参数名,因此在进行参数调用时,要提供默认参数名,可以使用下滑线进行忽略默认外部参数名
//从for循环开始,用qq课堂的小码哥视频,视频代码地址:/Users/yangyangzi/Desktop/yangyangzi/2019/swift(五部分)
11、while循环:
While i < 10 {
}
pepeat{
}while i < 10
repeat {
i += 1
print(i)
} while i < 10
12、字符串基本使用
string不是类而是结构体,性能更高,没有存储地址类似于int等,是一个值类型而oc的nsstring为指针类型
类,存储的字符串在堆里,有寻址操作
let len = str.lengthOfBytes(using: String.Encoding.utf8)
let ff = str.lengthOfBytes(using: .utf8)//枚举前边的类型是可以省略掉
1》字符串拼接
字符串间拼接:+ ; "\()"
字符串和其它进行拼接,例如和数字:+ ; "\()" ; String()
字符串格式化:String(format:"% “)和oc的%拼接相似
2》字符串长度
字符串长度:str.count
字符串字节长度:str.lengthOfBytes(using: .utf8)
13、
Oc有可变和不可变string
Swift的字符串可变就是var,不可变就是let;let 和 var相当于有无const
字符串截取:注index类型不是int了变成String.index了
//替换字符串会改变原字符串
//截取不会改变原字符串
//把字符串换成let看那个报错就说明此处会改变原字符串
15、
1》创建数组时设立某元素的重复次数
2》count与capacity不是同一概念,数值不一定相同
3》遍历数组:
便利索引而遍历元素
遍历元素:for value in arr {
数组迭代器::相当于遍历元组组成的数组 for (i,v) in arr.enumerated() { //arr.enumerated()相当于遍历元组组成的数组
遍历某区间元素:for v in arr[1...3] {
4》数组间操作:数组的合并
数组的加(注意:不存在减法);
数组的价只能在数组元素类型相同的情况才可相加;
//一、count与capacity
arr2.count//数组真正的元素个数
arr2.capacity//数组的容量,一般情况是2的个数,如果在存元素时超过了容量,容量值capacity就会 * 2(翻倍)
//二、遍历
//便利索引而遍历元素
//遍历元素
//迭代器;相当于遍历元组组成的数组:[(1,””),(2,””)]
//区间;arr[1...3]
//三、数组间操作
加法://arr + arr3 //不同种类型不能件单加,都变成Any类型即可相加;数组间没有系统减法
16、
17、
18、可选类型
1》oc与swift的nil不同,oc的nil指的空指针特殊的地址;swift的nil就是一个特殊含义的字符,表示没有值
2》swift中只有可选类型才能赋值为nil,nil是个特殊的字符
3》可选代表的含义是有可能有值也可能没有值;非可选代表无论在什么时候,在哪里都有值
let num:Optional<Int> = 2//num的是Optional类型的,不是Int
var num2:Int? = 2//num2是可选类型,此可选类型里包装了Int类型;?说明是可选类型
var num3:Int! = 2//num3是可选类型,此可选类型里包装了Int类型;!说明是可选类型;
//加?和!都表示是可选类型,?和!的区别:
//?表示可选类型:在任何时候有可能有值也有可能没值
//!标示可选类型:能保证在用到时候不为nil
/**
1、何为可选类型?
一个变量要么有值,要么没值
2、为何产生可选类型?
比如:oc中基本数据类型,如果不赋值,都会存在默认值;所以不会产生没有值的情况
但是:没有值和默认值是完全不同的两概念
所以在swift中引入了可选类型
区分了“有值”和“没有值”两种状态
*/
var n:Int = 0//n是一个非可选值
//n = nil //❌ 因为只有可选类型才能赋值为nil
n += 1
var m:Int? = 0
m = nil//m可以为nil,因为m为可选类型
//print(m) //报错
//m += 1 optional类型不能直接运算
m! += 1
var p:Int! = 0
//p += 1
p = nil;
//p += 1;
var q:Int? = 0
q = 1//可选类型可以直接赋值 ***
q
// ! :一个含义:强制解包
// ? 表示可选类型(包装了其它类型) 例如:Int?表示包装了Int类型;String?表示包装了String类型
//================== !也可以表示可选类型
var a:Int! = 12
print(a)//能正常打印
a = nil
print(a)//报错:原因:上边提到的?和!表示可选类型的区别即!表示可选类型必须能保证在用是时候有值,不用再判断ji
a = 1
print(a)//这时候又能正常打印了,因为上行赋值了,满足!表示可选类型的要求
//想要使用可选类型的值需要怎么做:1、直接判断+强制解包;2、可选绑定;3、guard守护 4、使用空合运算符??
//1、直接判断+强制解包
if q != nil {
var r = q!
r += 1
}
//2、可选绑定
//首先判断 q是否为nil,如果是,那么 if 后面的值为false
//如果发现q != nil,if后面的值为true,还会把q强制解包,并把解包后的值,赋值给result
//
if let r = q {
r + 1
}
//3、guard守护(注意guard只能用在函数里边,因此此处要写个函数)
func test(num:Int?){
guard let r = num else {
return
}
r + 1
}
//4、使用空合运算符??
var a:Int?
var b = a ?? 2 //如果a为nil则赋默认值为2
19、类型转换
/**
is :用于判断一个实例是否是一种类型
as :将实例转化为某一种类型,比如子类转父类(即很合理正常的类型间的转换)
as? :将某个类型转换为可选类型,通过判断可选类型是否有值,来决定是否转化成功
as! :将某个类型转化成具体的类型,但是注意:如过不是该类型,会崩溃,所以尽量少用
*/
// is ========
var a = 8.8
let bool = a is Int
// as ========
var sdd:String = "123"
sdd as String
// as! ======== 肯定可以转化成功,转换的结果是非可选类型 不能为nil
var str:Any = "1d24"
let ss = str as! String
ss + "adb"
// as? ====== 系统尝试进行转换,如果转换失败则为nil,转换结果是可选类型(这里用的是直接判断+强制解包)
let sadde = str as? String
if sadde != nil {
let cfg = sadde! + "ssd"
print(cfg)
}
20、空合运算符
//空合运算符用法
//可选类型的变量 ?? “为空时的代替值”
//代表,如果可选类型为nil,则使用默认值,如果有值,直接解包使用
//类似于使用三目运算符判断一个变量是否为空
//空合运算符 ??
//如果a可选类型的值为nil,那么,取??后面的值,如果,a不等于nil,则a取强制解包后的值
所以使用可选类型现在变成了五种处理方法如下:
//使用可选类型的值
//直接判断+强制解包
//可选绑定
//guard守护
//空合运算符给默认值(处理可选类型为nil的情况,即为nil给个默认值)
第二天
1、函数的基本使用
//有参,有返回值
//无参,无返回
//有参,无返回
//无参,有返回
//特例,返回多个参数(即返回一个元组)func five() ->(String,Int,Double{}
//函数 类型方法:类调用的方法,用static修饰的方法,而且不能直接写在外边
//函数 实例方法:对象调用的方法
2、函数使用注意一
//一:内部参数;外部参数 函数
//内部参数:在内部能看到能用的参数
//外部参数:在外边看到的参数叫外部参数
//3.0开始,第一个参数开始,既是内部又是外部
func one(num1:Int,num2:Int)//num1和num2都是内部和外部参数
func two(_ num1:Int,_ num2:Int)//_ 省略外部参数,num1 num2 是内部参数
func three(as num1:Int,cc num2:Int)//as cc 外部参数 //num1 num2 内存参数
//二、默认参数函数
//必填参数和可填参数混合
//作用:可以写兼容性很强的接口
func four(num1:Int,dis:Int = 0,disd:Int = 0) -> Int{} //num1必填 dis为可填 disd为可填
//三、可变参数函数
//可变参数类型: 类型...
//函数内部当数组处理
//函数外部,直接可以穿多个值
func five(nums:Int...) -> Int
func six(_ nums:Int...) -> Int
3、函数使用注意二
//1、函数内部,默认接收到的参数被赋值给一个常量,在swift3.0中,如果想改变,需要在函数内部,使用var修饰
func changeNum(a:Int){ var a = a a = 666}// 使用var进行修饰,尽量少用这种方式 ;注:这里是值传递
//2、将值传递转换为指针传递 inout关键字 //inout 地址
func oneOne(a: inout Int) 调用传地址 oneOne(a: &b)
//3、函数嵌套(oc是不能进行函数嵌套的)
func testA(){
print("a")
func testB(){
print("b")
}
testB()
print("c")
}
4、函数的类型
//函数是有类型的
//函数类型:由参数类型和返回值类型共同组成
查看函数类型:
func add(a:Int,b:Int) ->Int {
return a + b
}
let a = add//选中a,option+左键看函数类型为 (Int,Int) -> Int
//1、函数是有类型的,函数作为另一个函数的参数
func execute(num1:Int,num2:Int,fun:(Int,Int) -> Int){
fun(num1,num2)
}
execute(num1: 9, num2: 3, fun: cheng)
//2、函数是有类型的,函数作为另一个函数的返回值
func getFun(ff:String) -> (Int,Int)->Int{
if ff == "add" {
return add
}
return cheng
}
//系统如何区分不同的函数
//1、靠函数名称
//2、靠外部参数名称
//3、参数的类型 + 返回值类型 = 函数类型
//swift支持函数重载,而oc不支持,因为swift可以通过函数类型区分不同函数
5、枚举
Oc的枚举
//NS_ENUM表示状态,同一时刻只能取一个
typedef NS_ENUM(NSUInteger, Direction) {
DirectionA,
DirectionB,
DirectionC,
};
//NS_OPTIONS表示选项,同一时刻能取多个
typedef NS_OPTIONS(NSUInteger, DirectionDirection) {
DirectionDirectionA = 1 << 0,
DirectionDirectionB = 1 << 1,
DirectionDirectionC = 1 << 2,
};
//oc的枚举值只能是整型值
//swift中枚举值可以是字符串、字符、整型值、浮点值;swift枚举类型,默认不表示任何类型,就是一个标识;如果想绑定原始数据,需要在枚举定义时设置,并指定枚举类型
//枚举定义:如下;
//注意:开头字母小写
enum Direction{//此枚举值是没有类型的,默认不表示任何类型
case east
case sourth
case west
case north
}
enum DirectionTwo: Int{case east = 1 case sourth}//此枚举是Int类型的
enum DirectionThree: String{case east = "east" case sourth = "sourth"}//此枚举是String类型的
//枚举的元素值rawvalue
//枚举值-》原始值
//原始值-》枚举值
let z = DirectionThree(rawValue: "east")//z是可选类型
//枚举中可以写方法
//实例方法
//类型方法
6、结构体
是由一组相同或不同类型的数据组成的集合,是值类型,值传递
//实例属性
//类型属性,必须赋值
//实例方法,调实例属性和类型属性
//类型方法,调类型属性
7、结构体构造函数扩充
扩充构造函数
init,不能func
一旦扩充(无论扩充的是几个参数的构造器),结构体存在的系统自带的 逐一构造器,就没了
****** 一定要注意:在构造体内部,一定要保证,所有非可选属性,必须被初始化 ******
****** 且在调用构造器时,一定要保证所有非可选属性,必须有值 ******
//结构体中系统默认的构造函数,此构造函数默认以所有非可选类型为构造器参数,保证了所有非可选类型在结构体初始化后都有值,即 也叫 逐一构造器
//逐一构造器:在构造体内部,才能保证,所有非可选属性,必须被初始化
8、结构体函数的扩充
Swif叫类型扩展
Oc叫类扩展
//swift的static类型属性和java类似,在内存中是唯一的,是该类所有实例对象所共享的存储单元
(自总结)
mutating func shiliFunc() {//在实例方法中是不能修改实例属性值个,除非在实例函数前加mutating关键字,把self可以改变
print("在x轴上移动了",x+=1)
}
//类型扩展
//扩充系统结构体进行扩展
//oc中扩展只能用于类(int等非类的类型就不支持扩展了)
//swift中的扩展可以用于任何类型,比oc中的扩展范围广
extension CGPoint{
mutating func shiliFunc(xD:CGFloat){
self.x += xD
}
}
var pc = CGPoint(x: 3, y: 4)
pc.shiliFunc(xD: 3)
9、类的基本使用
//一、类的非可选属性注意点 =====================
//逐一构造器:保证非可选有值
/**
类的非可选属性注意点:
类和结构体看似一样,但结构体有 逐一构造器,而类没有逐一构造器;但是类和结构体一样在实例对象被创建好之后,保证,里面所有的非可选属性,必须有值,因此可以通过以下方法打到目的
1、把所有的非可选,改成可选
2、在构造函数里面,给所有非可选属性赋值
3、给非可选属性,赋值默认值
*/
// 属性:对象属性,类属性
// 方法:对象方法,类方法
//二、类可以不继承其他类,他本身就是根类 =====================
//如果,想用NSObject里的方法,则需要继承NSObject
10、字典转模型
kvc
和oc差不多用模型类
setValuesForKeys(dic)
override func setValue(_ value: Any?, forUndefinedKey key: String) { }//防止不存在的数据导致崩溃
11、类的析构函数,deinit相当于dealloc
deinit {//相当于oc的delloc方法
print("对象被释放了")
}
var p:Person? = Person()
p = nil
12、类的属性和方法
/**
属性:实例属性: 存储属性
计算属性(重写get方法)
类型属性: (static修饰的)
方法:实例方法: (可以被重写)
static类方法:(不能被重写)
class类方法: (可以被重写)
*/
//属性===========================
// 存储属性
//计算属性:需要重写get方法;不用重写set方法
//类型属性 static修饰
//方法===========================
//实例方法(可以被重写)
//类方法(类型方法,不能被子类重写) static
//类方法(能被子类重写)class
14、监听属性改变
/**
oc中通过重写set方法监听属性改变
swift中可以通过属性观察者来监听和响应属性值的变化
通常是监听存储属性和类属性的改变 willSet方法(newValue) didSet方法(oldValue)
计算属性不需要定义属性观察者,可以在计算属性的get方法中监听属性变化
*/
15、swift中自动引用计数
weak
//swift是ARC,没有MRC一说;
//swift循环引用
16、三大特性
1》注意swift的重载,当根类继承自NSObject,则重载的方法可能会报错,因为继承自NSObject后,说明这个类有可能和oc进行混编,而oc是不支持重载的某些情况例如:方法名相同+参数个数相同 + 参数类型不同+返回值相同的情况,此时需要在此重载的函数上加 @(newMethodName:) 即在混编为oc时此方法变为newMethodName:
// 重载
func chongzai(a:Int) -> Int {//1
return a
}
@objc(chongzaiTwo:)
func chongzai(a:Int) -> Double {//返回值不同 2
return 0.2
}
@objc(chongzaiThree:)
func chongzai(a:Double) -> Int {//参数类型不同 3
return 1
}
@objc(chongzaiFour::)
func chongzai(a:Int,b:Int) -> Int {//参数个数不同 4
return 1
}
//根类Person继承自NSObject后,说明此类及此类相关类以后可能会混编成oc,故2和3都要加通过@objc()为函数添加别名,注意参数,4处没必要加,这里只是看下俩参数的情况是两个冒号
2》注意swift的重载,当两个重载的函数 函数名相同+参数数目相同+参数类型相同+参数名相同+返回值类型不同的情况,在调用这种类型的函数时,一定要标明变量的类型
let b:Double = s1.chongzai(a: 2)//需要加类型 :Double
let c:Int = s1.chongzai(a: 3)//需要加类型 :Int
16、三大特性-多态
17、结构体和类的区别
1》结构体有逐一构造器,类没有
结构体和类都有static类型方法,结构体没有class类方法而类有;
2》结构体是值类型,类是引用类型
3》结构体不能继承(即没有多态)
枚举结构体都可以遵守协议,但不能继承
18、Any,NSObject,AnyObject区别
/**
public typealias Any = protocol<> //一个协议声明
@objc public protocol AnyObject{} //一个具体的协议,协议里面没有内容;默认情况下,所有的类,都遵守这个协议;注意所有的类
open class NSObject : NSObjectProtocol //所有继承自NSObject的类及NSObject类
范围从大到小:Any > AnyObject > NSObject
*/
//注意Int,Double,String在swift中都是结构体类型
20、可选链的使用和练习
//以下就是一个可选链,即在包含有多个可选类型的表达式中的任意一个可选类型的值为nil,则会导致整个表达式为nil
//反之,如果可选链的结果是nil,就代表,调用失败(说明链条中至少有一环节,断了,即表达式中的任意一个可选类型的值为nil)
// () == Void != nil void类型的函数
let res = per.dog?.toy?.price()
21、APP讲解
架构:
MVVM + RAC
MVP
VIPPER
组件化
数据结构:二叉树
第三天
05、协议的基本使用
/**
swift的类,枚举,结构体都能遵守协议;oc只能类遵守协议
*/
//1=========类遵守协议
swift中的协议被遵守后,协议方法必须实现
class Graduate:Animal,Work{//继承父类,并遵守协议,swift的类不支持多继承
//2============枚举遵守协议
//3============结构体遵守协议
//5============协议之间的继承
protocol momanwork:Work {
//类中使用协议方法:一般设置代理使用
//枚举中使用协议方法:直接用枚举中的实例调用 One.left.run()
//结构体中使用协议方法:直接用结构体的实例调用 let tw:Two = Two() tw.run()
06、协议中代理的使用
//协议在类中的使用:(注:05中介绍了枚举和结构体中协议的使用,而类以代理的方式使用协议)
delegate用weak修饰防止死循环:
// 1、这样写会造成死循环,故要加weak修饰
// 2、加weak修饰后报错(weak只能修饰类): 'weak' must not be applied to non-class-bound 'Work'; consider adding a protocol conformance that has a class bound
// 3、weak解决方案一:让Work继承自class类
// 4、weak解决方案二:让Work继承自NSObjectProtocol协议,由于swift中必须实现协议的所有方法,因为NSObject已经遵守了NSObjectProtocol协议,因此让遵守此协议的所有类都继承自NSObject类即可
// 还是觉得方案一比较好
07、协议中的可选
//协议的可选,仅仅是oc的特性,swift不支持
//解决方案:让swift协议,拥有oc特性
@objc
protocol Work{
@objc optional func work()
}
08、泛型
Swift强类型语言,必须类型匹配
/**
泛型:泛泛的类型,不是一个具体的类型
一旦函数内部,确定泛型的具体类型,那么所有的泛型都是该类型
*/
//应改为地址交换
func exchangeNum(a: inout Int,b:inout Int){
let temp = a
a = b
b = temp
}
var a1 = 1212
var b1 = 3223
exchangeNum(a: &a1, b: &b1)
func exchangeFanXing<T>(a:inout T,b:inout T){//一般用T表示泛型//一般用T表示泛型,写其他任意的代号都行
let temp = a
a = b
b = temp
}
//var dd = 1.3
//var ff = 3
//exchangeFanXing(a: &dd, b: &ff)//a和b类型不一致时就会报错,因为使用泛型时,当第一个泛型类型的值的类型确定后,则所有使用此泛型类型的值都和第一个值相同;即当此处第一个参数的类型为1.3,则默认后边的b也为Double类型,故不能传其他类型的值
08、泛型二
/**
泛型的使用
1、与结构体集合
struct Point<T>{
var x:T
var y:T
}
2、与类结合
class Stack<T>{
var nums:[T] = []
var nud:Array<String> = []
func push(value:T) {
print("进栈")
nums.append(value)
}
func pop() -> T{
print("出栈")
return nums.removeLast()
}
}
3、与协议结合
protocol work{
associatedtype T
func eat() -> T
func run() -> T
}
public protocol View : _View {
associatedtype Body : View
var body: Self.Body { get }
}
SwiftUI 的 View 实现成协议,使用 associatedtype 关联了一个 Body 类型。根据 Swift 的语法,带有 associatedtype 的协议不能直接返回,只能作为类型约束。
class Person:work{
func eat() -> Person {
print("人吃饭")
return self
}
func run() -> Person {
print("人跑步")
return self
}
}
class Dog:work{
func eat() -> Dog {
print(" 本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。