当前位置:   article > 正文

swift笔记_weak' must not be applied to non-class-bound 'any

weak' must not be applied to non-class-bound 'any redundant conformance of

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博客】

推荐阅读
相关标签