本篇文章给大家谈谈喵神 Swift 编程学习心得分享,以及对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。
不需要随机数种子
arc4random()%N + begin: 生成从begin到begin+N的随机数
arc4random_uniform(endIndex-startIndex)+startIndex: 生成从startIndex到endIndex的随机数
arc4random_uniform(N): 生成0 到N-1 之间的随机数
2、自动关闭;如何实施?操作员
1)关闭
封闭标准定义
{[捕获列表](参数)- 语句returnxxx 中的返回类型}
//自动闭包,闭包的标准定义
testClusure { (s, s2) - 字符串
返回“1”
}
//根据上下文:推断类型,推断类型指的是1)返回类型,2)参数类型
测试聚类(){
s1, s2in
返回“123”
}
//单个表达式:隐式返回,将表达式的值作为返回值
testClusure { s1, s2 中
"asdfasdfadsf"
}
//参数名称缩写
测试结论{
$0 + $1
}
测试Clusure(clusure: +)
//尾随闭包省略括号()
testClusure { (s1, s2)in
返回1 + s2
}
2)自动关闭
不接受任何参数!
将返回表达式的值
//自动关闭
testClusureAuto(adsf:"asdfasdfasdf")
func testClusureAuto(adsf clusure:@autoclosure () -String) {
}
省略花括号并使用普通表达式而不是显式闭包
表达、陈述
自动关闭的含义:延迟评估
?
||
()-T
时间
如果我们直接使用T,则意味着在?之前运算符接受一个值,我们必须准备一个默认值并将其传递给此方法。
如果这个值经过一系列复杂的运算,就会造成浪费,因为如果可选值有值的话,根本就不会使用默认值T。
相反,直接返回解压后的值。
通过将默认值的计算推迟到可选项被确定为nil 之后,可以完全避免这种开销。
逃脱
@转义
关闭
价值捕获
引用类型、值类型
让playClosure={
(child:Child) -()?在
child.Pet?toy?play()
}
函数播放(){
}
if let a:()=playClosure(xiaoming) {
}
让playClosure={
(child:Child) - 字符串?在
child.Pet?toy?play()
}
func play() - 字符串{
返回“adsf”
}
if let a=playClosure(xiaoming) {
}
child.Pet?toy?play()单个表达式闭包隐式返回,整个表达式的值作为闭包的返回值
这取决于游戏的定义
这样的调用会返回一个()吗?
事实上,它是一个可选的空元组:猫神不是万能的,这无法解释:“虽然看起来很奇怪,但这是事实。”
3. 操作员
1. 重载运算符
2.声明一个新的运算符
定义运算符的优先级
结合法、优先顺序
不能在本地字段中定义运算符。您必须能够在全球范围内使用您的操作员。
相邻运算符位于非关联优先级组tt 中
相邻相邻
联想组合
优先级优先
结构开发者{
静态函数测试() {
让t1=开发者()
让t2:Developer="a"
让t3="你好"
让_=t1~=t2~=t3
}
}
//文字表达
扩展Developer:ExpressibleByUnicodeScalarLiteral{
类型别名UnicodeScalarLiteralType=String
init(unicodeScalarLiteral value: String) {
logFlag("我什么也不做")
}
}
//运算符重载
优先组tt {
//指定关联性
协会:左
//指定优先级
高于:乘法优先级
}
中缀运算符~=:tt
func~=(left:Developer,right:Any)-Developer{
print("我为Developer类实现了一个自定义运算符:~=,你需要使用它吗?")
向左返回
}
//也可以重写而不指定优先级和关联性。
中缀运算符~+
func ~+(left:Developer,right:Developer){
print("我不会做任何事情,只是看看这些运算符是否被重写")
}
4.输入输出
:
inout原理:inout,修改变量。在函数内创建一个新值并将该值赋给原始变量
值类型:
inout 在函数内部创建一个新值,然后在函数返回时将此值赋予修改后的变量。
这与引用类型的inout机制不同。
如果是引用类型怎么办?
5. 文字表达
Literal Expression-《Literal Expression Protocol》协议中规定了哪些方法?
如果类型支持字面表达式赋值,则需要为相关类型自定义表达式协议并继承。
定制您自己的文字表达
隐式转换,使用文字
let a="asdfasdfafsd"//这是字符串文字
让一个=
["asdfafsd","asdfasdf"]//数组字面量
让一个=
["a":"asdfasdf","b":"1231321"]//字典字面量
如果类型实现了ExpressionByBooleanLiteral 系列协议,则此类将支持文字表达式。
文字表达了非常隐藏的属性。缺点是无法跳转到字面复制。我们不知道这个任务是在哪里执行的。
6. 下标
重写下标运算符
7. 嵌套
函数嵌套
8. 命名空间
默认是使用您所在的目标。编译系统会根据不同的目标自动添加命名空间。
如果它们在同一个目标中,如果定义的某些类是相互链接的,仍然会发生冲突。
应用程序:
第三方框架:
myframework.myclass
9. 类型别名
别名
场景1
类df{
}
//类型别名dff=df
类型别名dff=df
场景2--组合协议
协议Pro1{}
协议Pro2{}
类型别名Proall=Pro1 Pro2
10. AssociatedType: 关联类型
1)
在协议中声明一个关联类型,并在协议中指定的属性和方法中使用该关联类型
当一个类、结构体或枚举同意继承这个协议时,
在实现该协议的方法中,可以指定协议指定的关联类型,
这样,在实现这些协议方法和属性时,不同的类、结构体、枚举,虽然继承了同一个协议,
但运行的结果不同,不需要使用is as? 对类型进行类型判断。作为!方法!
2)有关联类型协议,不能单独使用
协议动物只能用作通用约束
因为它有self 或关联类型
要求
协议动物{
相关F型
功能吃(food:F)
}
结构跳跳虎:动物{
类型别名F=肉
func eat(food: 肉) {
print("老虎吃肉")
}
}
协议动物2{
函数eatFood()
}
扩展动物2{
函数吃食物(){
}
}
结构Chicekent:Animal2{}
结构Dogg:Animal2{}
func isDangerous(animal:Animal2)-Bool {
如果动物是狗狗{
返回真
}别的{
返回错误
}
}
//func isDangerous(animal:Animal)-Bool {
//如果动物是老虎{
//返回真
//} 别的{
//返回假
//}
//}
11.可变参数
只能有一个参数可变
变量参数的类型全部相同,但可以使用Any
12、init、deinit序列
先初始化子类,再初始化父类
先deinit子类,然后deinit父类
不需要写super.init,系统会自动添加。如果要修改父类的值,需要显式调用super.init,然后访问父类的变量来修改。
要在init中调用init,需要在init前面加上方便。
当父类中带参数的init在子类中被重载时,系统不会自动将其添加到子类的init实现中,需要手动添加。
父类的便捷构造函数。子类调用父类的便捷构造函数实现的init方法。子类不需要编写便利构造函数,也可以使用便利构造函数。
13、可选初始化
求x 的y 次幂
14、类、静态
1)非类类型、struct、enum:使用static
2) Class 专门用于类类型。如果使用static,则意味着不能重写。
3)协议中使用static
至于为什么?
Class可以重写,static不能重写
struct和enum值类型的数据类型中,变量存储属性、常量存储属性、计算属性、方法类属性、类方法不能被子类覆盖,所以使用static。
struct和enum值类型不允许子类实现,因此不存在重写的问题。使用静态意味着它们不能被重写。
struct、enum 不允许继承:从非协议类型“StructA1”继承
协议中指定的属性和方法不能在子协议中重写,所以使用static
在类class中使用类属性:只能是计算属性,可以使用class、static
在protocol协议中,添加static、类属性、类方法
结构体A1{
函数printHello(){}
}
//结构体A2:A1 {
//函数printHello(){}
//}
类A1类{
函数printHello(){}
类函数printHello2(){}
静态函数printHello3(){}
静态变量s1:String="123"
类var s2:String {get{return "123"}}
静态让s3:String="1212"
}
类ClassB1:ClassA1{
覆盖fun printHello(){}
重写类fun printHello2(){}
//覆盖静态函数printHello3(){}
}
协议协议A1 {
静态函数printHello()
静态变量s3:String{get}
//类函数printHello2()
//Protocol协议,实例属性可以实现为计算类型或者存储类型
var s4:String{获取}
var s5:String{设置}
var s6:String{获取}
}
类ClassA2:ProtocolA1{
静态函数printHello() {
}
静态变量s3: 字符串{return "asdfasf"}
var s6: 字符串{return "asdfasd232"}
var s4: String={return "asdfasdfa"}()
var s5: 字符串="1234123"
}
15. 收藏
1)字典、数组、集合类型都相同,或者都是any
2)如何实现多类型集合?巧妙地使用枚举来存储多种不同类型的值
枚举关联值
类函数testAnyCollection(){
让a=[strOrInt.getInt(123),strOrInt.getStr("asdfa"), strOrInt.getBlock({(hell) in
打印(地狱)
})]
对于我在一个{
开关我{
案例.getBlock(let a):
一个("1341234123")
案例.getStr(let s):
印刷)
案例.getInt(let n):
打印(n)
//case .getIntAndStr(let s, let n):
//印刷)
//打印(n)
案例.getIntAndStr(let s, 1):
印刷)
案例.getIntAndStr(让s,让a):
打印(一个或多个)
}
}
}
枚举strOrInt{
案例getStr(字符串)
案例getInt(Int)
case getBlock((字符串)-())
case getIntAndStr(字符串,Int)
}
16. 正则表达式
如何构建正则表达式工具
该工具使用结构体进行组织
1)提供模式变量,提供初始化方法,提供匹配方法
2)更高级的方法是:实现一个运算符,
func=~(left:String, right:String) -Bool {
}
17. 模式匹配
开关,for,如果,尝试.捕获.
1)等待
2)判断可选类型是否为nil
3)判断范围
底层是如何实现的?
事实上,系统实现了~=运算符。
18……还有……
事实上,这就是范围运算符
对于这个算子,系统有一系列算子范式函数的定义
.开始=结束
.
范围运算符返回一个:通用闭开区间或通用范围
半开间隔
范围
闭区间
应用场景:
1)对于声明
2)首先创建一个封闭或范围,然后使用封闭或范围的堂兄弟方法来判断某个字符是否属于这个封闭或范围。
例如判断是否是小写字母
19.self 和.Type
任何类别
.Type 存储type的类型
有Int 类型:存储整数值,String 类型:存储字符串,AnyObject.Type 类型存储Anyobject 类型。
ClassA.self:类型实例
如何调用存储类型的类型?元型
意义:
调用类方法:调用类方法时,可以使用此元类型的实例来调用其类方法。
.self 类型实例
.Type 类型实例类型
.self协议实例
.Protocol协议类型实例的类型
//协议元类型,它有什么作用?
让s11:ProtocolA1.Protocol=ProtocolA1.self
//用法1、使用模式匹配
//显然:系统没有实现这种模式匹配操作~=,那么我们就做一个
让e:[Any.Type]=[NSString.self,NSDictionary.self,NSArray.self,ClassA3.self,String.self,(()-()).self]
对于e 中的i {
开关我{
案例NSString.self:
print("这里存储了一个nsstring类型,保存这个类型")
案例字符串.self:
print("字符串类型")
案例(()-()).self:
print("明白了")
默认:
打印("asdfa")
}
}
func ~=(left:Any.Type,right:Any.Type)-Bool{
如果左==右{
返回真
}
返回错误
}
//用法2、使用if语句
让arr:[AnyObject.Type]=[ClassA3.self,ClassA1.self]
对于我在arr {
如果我是ClassA1.Type {
让=我作为! A1类.类型
d.printHello2()
}
如果我==ClassA3.self {
让d=i 作为! A3类.类型
d.print2()
}
}
20.自我
复制方法示例
//定义一个协议:使用Self
协议可复制{
func copy()-Self
}
类MyClass:Copyable{
func copy()-Self{
让r=type(of:self).init()
返回r
}
需要初始化(){
}
}
21.动态型
多种方法
Swift,编译器在编译时决定使用哪种方法; Swift 默认不使用动态调度。
方法调用是在编译时确定的。
如果不希望系统自动调度,可以修改代码,使用as?判断类型并调用对应类型的方法。
22. 财产观察员
1)可以添加willset和didset存储属性,但计算属性不允许观察者。
由于计算了属性,因此可以监视属性的变化。
2)如果你想向现有类型添加观察者,该怎么做?
使用子类继承。继承后,可以为父类的任意属性添加观察者:存储类型或计算类型。我们不需要担心它。
存储类型或计算类型。
3)唯一需要注意的是:
因为子类重写了父类的计算属性观察器,所以didset方法会先读取oldvalue,这会导致父类的get方法被调用。
23. 何时使用final
1)md5算法和des加解密工具非常稳定,可以最后添加。
2)将某些决定系统正确运行的属性或方法,如数字生成方法,添加到final中,防止子类重写时给系统带来错误。
3)添加final后,子类不能做一些它能做的事情。怎么解决呢?
我们可以在final方法中调用一个方法,并在当前类定义中实现这个方法。在这个方法中,我们断言子类必须重写它。
这样我们就放心了,在调用final方法的过程中,我们不能做我们想做的事情了。
类ClassB3:ClassB2{
覆盖fun getConfigValue() -String {
return "来自b3 班!"
}
}
类B2{
最终函数printHello(){
print("加载开始")
让a=getConfigValue()
print("加载结束"+a)
}
func getConfigValue()-字符串{
fatalError("子类必须实现此方法")
}
}
24. 懒惰
延迟属性、延迟方法
1)延迟,与oc相比,延迟存储属性和延迟计算属性
延迟存储变量、延迟计算变量
2)如果没有猫神,确实我只知道1的应用场景
swift提供了几种全局方法
//Sequence : 惰性方法名,泛型列表,参数:泛型参数,符合协议SequenceType的实例,返回LazySequence泛型类实例
func 惰性(s:S) -LazySequence
//乱序
func 惰性(s:S) -LazyRandomAccessCollection
//双向
惰性函数(s:S) -
惰性双向集合
//向前
func lazy(s:S)-LazyForwardCollection
给定一个集合,返回一个集合
这个比较难
arr.lazy.map
25. 快速运行时
反射和镜子
类函数testRuntime(){
让a=PersonA(name: "asdf",age: 12)
letmirror=Mirror(reflecting: a) //MirrorType
对于mirror.children 中的孩子{
打印(子标签,子值)
}
}
类PersonA{
var name:字符串
变量age:Int
初始化(名称:字符串,年龄:Int){
self.name=姓名
自我年龄=年龄
}
}
应用场景:
1)运行时,通过Mirror获知Swift类型实例的属性信息
我们可以通过镜子传递某个swift 实例来获取孩子,
label、value设置值,找到我们要找的目标键值
2)限制:Swift的镜像只能读取,不能修改。我们最好不要在应用程序中使用这个镜像,
相反,探索游乐场和repl 中的类层次结构。
26. 隐式拆包
可选型
?
!
选修的
1)可选类型,是什么类型?
它是结构体、枚举、类、闭包、元组、函数吗?
当然是一个枚举
枚举可选{
//没有什么
案例无
//关联类型:关联T类型的实例
案例一些(T)
}
2)
多个Optional到底是什么?
这样理解,
var a:字符串?=零
让b:字符串?=一个盒子?盒子?放一根绳子
让c:String?=零框?空盒子或非空盒子
3) 可选地图
扩展集合类型{
//输入参数:一个闭包: 1)参数是采用协议本身的元素实例2)返回值是返回任意类型
//返回值:返回任意类型
的数组 publicfunc map (transform:@noescape ((Self.Generator.Element) ->T))->[T]{ //Swift标准库具体的实现 } } public enum Optinal:_Reflectable,NilLiteralConvertible { //入參:一个闭包:1)参数是一个任意类型,2)返回值是任意类型的这么一个闭包 //返回值:任意类型 publicfunc map(f:@noescape((T)->U))->U? { //Swift标准库实现 } } Int?=>Optional String? =>Optional Array? =>Optional 函数式编程的思想,他是一种思想,写一个函数,约定一个规则,在这个规则下写这个函数,不要乱搞。 我们因此又称他为范式。 函数式编程的范式又是什么呢? 1,函数是第一等公民 2,只用表达式,不用语句 表达式:单纯的运算过程。总是有返回值 语句:执行某种操作,没有返回值 函数式编程的出发点动机,就是处理运算。 3,没有副作用 函数内部与外部互动,产生表达式运算以外的结果。 函数式编程强调:函数要保持独立, 所有功能就是返回一个新的值,没有其他的行为,尤其是不得修改外部变量的值。 4,不修改状态 变量往往用来保存“状态”,不修改变量,意味着状态不能保存在变量中。 函数式编程使用参数保存状态的一个特例就是递归。 5,引用透明 只要传入什么参数相同,返回的结果永远都是相同 Optional可选实例的map方法 结合类型的map方法 let arr= [1,2,3,4] let arr2 = arr.map{$0 * 2} print(arr2) let b:Int? = 1 let c = b.map { t in return"12341"} print(c) 27、协议扩展 应用场景: 1)提供一个协议方法的默认实现,=》变相实现了可选协议 2)如果一个协议的扩展中提供了一个默认实现,然后这个协议并没有对这个默认函数进行声明。 继承这协议的类的实例调用这个方法时,还是可以调这个默认实现的。如果这个类中自己实现了这个协议方法,他会调用自己类里面实现的。 这正是按照我们所想的方法执行的。 3)扩展一个协议的时候,加上where限定条件,可以指定1)、继承这个协议的2)并且满足条件的类、结构体、枚举Self,需要实现这个扩展 中的方法。 28,where在哪里使用 //报错:where clasuecannot be attached to a protocol declaration protocol ProtoclA18 where Self:String { func method2() } 协议不能像class一样在名称后面加来定义范型,但是可以使用关联类型associated来定义一个引入的范型类型。 如何定义个一个协议,只能要求被某些特定类来实现呢?? //Perfect 定义一个空协议,然后扩展这个协议,在扩展中指定这个协议,只能由某些特定类型来继承 protocol ProtocolA18{ } extension ProtocolA18 whereSelf:ProtocolOther{ func method() } @objc protocol ProtocolA18{ } extension ProtocolA18 whereSelf:ProtocolA19 { func method2(){} } extension ProtocolA18 where Self:ClassTest{ func method3(){} } protocol ProtocolA19 { func method2() } @objc protocol ProtocolA17 { func method() } //这个类不继承那个协议,交给它所属的实例类来实现协议 class ClassA17:ProtocolA18 { //协议类型 weakvar protocolObj:ProtocolA18? //method2, method3都不需要实现。 func method2(){ } } class ClassTest:ProtocolA18 { var a:ClassA17! func viewDidLoad(){ //let a = ClassA17() a = ClassA17() a.protocolObj = self } func method() { print("helloworld") } deinit { logFlag() } func method3() { } } //if else let arr = ["123413","胡asdf","胡阿水淀粉","李思思"] arr.forEach { (a:String) in if a.hasPrefix("胡") ,a.characters.count >4 { print(a ,"是老师") }else { print(a, "是学生") } } //switch case arr.forEach { (a) in switch a { //这where只能加一个条件啊 case let x where x.hasPrefix("胡"): print(a ,"是老师") default: print(a, "是学生") } } //for in for i in arr where i.hasPrefix("胡") { print(i ,"是老师") } //用在协议扩展里:扩展协议中,对扩展的协议增加限定:关联类型继承某个协议 let c2 = ClassC2() let c1 = ClassC1() c1.printBBB() //报错 c2.printBBB() extension ProtocolC1 whereSelf.TT:Comparable { func printBBB(){ print("bbb") } } extension ProtocolC1 { //func printAAA() func printhello(){ print("扩展协议,提供了方法的默认实现,但是这个方法,并没有在协议中定义") } } class ClassC2:ProtocolC1{ var name="asdfasdf" typealias TT = Any? func printhello() { print("AAA") } } class ClassC1:ProtocolC1{ typealias TT = Int var name = "asdfasf" func printhello() { print("我们自己来实现这个协议,那么扩展协议中的默认实现的方法还会被调用吗") } } 29、使用枚举而不是class或者struct来定义一个链表 不加indirect,编译报错! 嵌套定义枚举的时候,必须加上indirect关键字 class func testIndirectEnum(){ let a1 = E.n(1) let a2 = E.n(3) let a3 = E.add(a1, a2) let r = E.eval(l: a3) print(r) } indirect enum E { case n(Int) case add(E, E) //需要一个嵌套函数 static func eval(l:E)->Int{ switch l { case .n(let t): return t case .add(let l1, let l2): returneval(l: l1) + eval(l: l2) } } } class C1{ classfunc a() { let c = E.add(E.add(E.n(1), E.n(3)), E.n(3)) let d = E.eval(l: c) print(d) let _ = LinkedList.node(1, LinkedList.node(2, LinkedList.empty)) } } 30, Swift -》》selector 2种表现形式Selector and#selector selector是一个关键字,返回一个类型 -(void)callMe{} SEL method = @selector(callMe) -(void)callMe:(id)obj{} SEL method2 = @selector(callMe:) swift=> 定义一个selector 挂一个方法:@objc class AA { @objc func printhello(){} func print(){ #selecotor(printhello) } } @objc(BB) class BB { func printHello() func print(){ #selecotor(printhello) } } 执行一个selector Selector("method")警告:不要显示调用,需要改为#selector关键字 #selector(method(parm1:param2:)) #selector(method(param1:)) #selector(method2) 如果同名子的方法只有一个,没有参数、标签不同的同名函数,则可以省略参数列表 func method2(a:String,b:String){} func method(param1:String,param2:String){} func method(param1:String){} #selector(method2)//这种调用也是可以的。因为他的方法没有同名 但是可以将方法进行强制转换 #selector(method as (string,string)->()) #selector(method as (string)->()) 31,实例方法的动态调用 实例方法 实例属性不可以 class ClassA10{ func printHello(){ logFlag("hello") } } //字面量取值 f = ClassA10.pringHello { //参数ClassA10 (obj:ClassA10) in //返回值:是一个函数 return obj.printHello } f1(ClassA10())() 原理: (Xcode8_swift3_iOS8_10.ClassA10)->()->() (Xcode8_swift3_iOS8_10.ClassA10)->(String)->() (Xcode8_swift3_iOS8_10.ClassA10)->(String,String)->(String) (Xcode8_swift3_iOS8_10.ClassA10)->(String)->(String) 柯里化方法 (String)->()-() //动态调用 let f1 = ClassA10.printHello f1(ClassA10())() //ClassA10.printHello的字面量表达 let a = { (obj:ClassA10) ->()->() in return obj.printHello } a(ClassA10())() 32,单例 实例属性:存储型常量,存储型变量,计算型变量 类属性:存储型常量,存储型变量,计算型变量 由于swift1.2之前版本的属性特性,类属性不能有存储型变量、存储型常量。所以单例的实现方式就要借助于全局变量, 然后在计算型变量中,返回这个全局变量。 那么1.2开始以后,就会有更简单的单例实现版本了。 class Manager{ //存储型常量来保存单例 static let shared = Manager() private init(){} } 33,条件编译 1)条件的语法怎么写? 还是c语言语法格式的写法,只不过对条件加了指定 #if XXX #elseif XXX #else #endif //省略else,elseif #if XXX #endif //省略elseif #if XXXX #else XXX #endif 2)什么情况用到条件编译? 指定的条件如下: os() os(macOS) os(iOS) os(tvOS) os(watchOS)os(Linux) os(FreeBSD) os(Windows) os(Android) arch() arch(x86_64) arch(arm) arch(arm64) arch(i386) swift() swift(1.2) swift(2.3) swift(3.0) #if FREE_VERSION #else #endif build settings->swift compiler -》custom flags-》other swift flags加上-D FREE_VERSION 34、Xcode标记 // MARK: // MARK:- // TODO: // FIXME: oc中有的: #warning #param 35、@UIApplicationMain 生成模版代码 36、 动态派发 @objc修饰 @dynamic oc中的协议里存在关键字: @optional //swift不支持可选协议 protocol OptionalProtocol{ optional func optionalMethod() } //支持可选协议, @objc protocol OptionalProtocol { @objc optional func optionalMethod() } 使用@objc修饰的协议,只能被class实现,不能被struct,enum实现 37、内存管理 引用计数 arc 当实例的引用为nil的时候,系统就会释放内存 什么时候实例的引用为nil? 1)超过作用域,2)手动设置为nil 产生循环引用的条件: 1)引用类型实例产生循环引用 2)闭包引起循环应用,其实闭包也是一个引用类型。还是可以归属为1 一个class有一个闭包属性。闭包属性里面又使用了self,就产生循环 在方法内部初始化的生成的对象在被返回后别人还能使用,而不是立即释放掉 延迟释放 func autoreleasepool(code:()->()) 每次超过作用域后,自动内存管理都会为我们处理好内存相关的事情??? //每次获得一个产生一个data func loadBigData() { if let path =nsbundle.mainbundle().pathForResource("big",ofType:"jpg") { for i in 1...10000 { autoreleasepool{ //方法1: let data =nsdata.datawithContentsOfFile(path,options:nil,error:nil) //方法2:工厂方法-》》初始化方法 let data =NSData(contentsOfFile:path) nsthread.sleepfortimeInterval(0.5) } } } } 整个线程一个自动释放池,每个主runloop结束时候进行drain操作。 drain的作用: 1)把池子里面的引用类型的实例,实例的引用为nil的时候,或者说引用计数为0的实例,进行释放。 所以,即使一个实例没有强引用了,或者引用计数为0了,只要释放池没有执行drain操作,他就不会得到释放 2)把引用计数-1 值类型 传递、赋值=》复制 引用类型 传递、赋值=》引用对象的一个指向 String,Dictionary,Array,值类型,少量数据用此。如果数据大,就用cocoa中的NSDictionary,NSArray 值类型:内存是在栈上。 引用类型:堆上。 String or NSString ? //String let a = "ABCDE" let range =a.characters.index(a.startIndex, offsetBy:1).. let b = a.replacingCharacters(in: range,with: "A") print(b) //NSString let c = (a asNSString).replacingCharacters(in: NSMakeRange(1, 4), with: "A") print(c) 38、Swift和C Swift和C指针 Swift如何处理指针? C的识别特点就是指针 OC -》C? Swift-》C? Unsafe开头的, void * -》UnsafePoint const Type * ->UnsafePointer Type * ->UnsafeMutablePointer unsafeBitCast(CFArrayGetValueAtIndex(arr,0),to:CFString.self) C开头的; int -》CInt array ->CFArray string ->CFString COpaquePointer UnsafeMutablePointer并不会自动进行内存管理,因此把某一个pointer = nil,并不能自动释放内存 deinitialize-》释放指针指向的内存的对象 deallocate -》释放指针自己本身 指向函数的指针-》C打交道,1)直接用闭包2)@convention(c)标注 allocate initialize deinitialize deallocate var a:UnsafeMutablePointer! a =UnsafeMutablePointer.allocate(capacity: 1) a.initialize(to: ClassA12()) print(a.pointee.name) a.deinitialize() a.deallocate(capacity: 1) a = nil opaquepointer 39、怎么封装一个漂亮的gcd调用? 嵌套函数好复杂!!! 40、Swift类型操作 1)获取类型的类型 xx.self和Type 类型,XXX.self 类型的类型,XXX.Type AnyClass = AnyObject.Type 2)获取实例的类型 实例=》》》》类型 type(of:obj) object_getClass(obj) 3)Self class MyClass:Copyable { funccopy()->Self { letr = type(of:self).init() returnr } requiredinit(){ } } 4)swift类型判断 isKindOfClass:属于某个类或者继承自这个类 isMemberOfClass:属于某个类 适用于NSObject类型或其子类型 isKind isMemeber 用is:is相当于原来的isKindOfClass,可以检查属于某个类或者继承自这个类 他不仅可以用class引用类型上,还可以用于struct,enum类型 在范型中使用类型判断:提前约束是何种类型,在编译期间就可以确定类型要求 41、花括号的演变 1、 c语言中利用{} 1)代码块,看着清晰一点 2)利用作用域,释放内存 2、 swift 2.0以前 用尾随闭包 func do(b:()-()){ b() } do{ 。。。。。 } 3、 那么2.0以后呢? 就用do,加入了do关键字,捕获异常的作用区域 do { } 4、 使用匿名闭包----用闭包赋初始化值 let label:UILabel = {return UILabel()}() 42、 swift判等 NSObject子类:看是否重写了父类isEqual方法,默认的是用父类的isEqual方法判等 Swift类型,不继承NSObject的类:判等==,需要把类继承Equatable协议,然后实现操作符==方法,否则编译报错 如果是Swift的原生类型,如String,Dictionary,系统自动实现了Equtable协议了,我们不需要自己去重写啥的。 let a1 = ClassA13(name: "huchu") let a2 = ClassA13(name:"study") if a1 == a2 { print("重写的判断生效了") } let a3 = ClassA14(name: "huchu") let a4 = ClassA14(name:"study") //报错,无法编译:没有重写判断操作符== if a3 == a4 { print("无法判等的") } let a5 = ClassA15(name: "huchu") let a6 = ClassA15(name: "study") if a5 == a6 { print("NSObject的子类,默认调用NSObject父类的判等方法:isEqual") } let a7 = ClassA16(name: "huchu") let a8 = ClassA16(name: "study") if a7 == a8 { } class ClassA13:Equatable { var name:String init(name:String) { self.name = name } public static func ==(lhs: ClassA13, rhs: ClassA13) ->Bool { return true } } class ClassA14 { var name:String init(name:String) { self.name = name } } class ClassA15:NSObject { var name:String init(name:String) { self.name = name } } //Redundant conformance of classa16 toprotocol equatable class ClassA16:NSObject,Equatable { var name:String init(name:String) { self.name = name } override func isEqual(_ object: Any?) ->Bool { print("NSObject的子类,默认调用NSObject父类的判等方法:isEqual") if object is ClassA16 { let j = object as! ClassA16 return j.name == self.name } return false } public static func ==(lhs: ClassA16 , rhs: ClassA16) ->Bool { print("NSObject的子类,优先看有没有实现Equatable协议方法==判等操作符:优先调用了") if lhs.name == rhs.name { return true } return false } } 43、swift日志输出 print NSLog 占位: %d,%@,%02d,%f let t = String(format: "%.02f",b) print(t) print("\(t)") let t2 = String(format: "%.02f",1.234567) print(t2) print("\(t2)") let t3 = String(format: "%.02f",1234567) print(t3) print("\(t3)") NSLog("%.02f", 1234567) NSLog("%.02f", 1234567.1) 输出如下 1.23 1.23 1.23 1.23 0.00 0.00 0.00 1234567.10 在oc中输出 NSLog(@"%.02f", 1234567); 0.00 44、Options选项 原来的选项Option值-》满足OptionSetType协议的struct类型,以及一组静态的get属性。 想一想,why? OptionSetType是实现了SetAlgebraType的 Algebra:代数学 set algebra:集合代数 用集合来代替逻辑运算符&、|位运算 //这里太复杂:OptionSet struct SexOptions : OptionSet { //可以省略 typealias RawValue = UInt let rawValue:UInt static let none = SexOptions(rawValue: 0) static let optionMale = SexOptions(rawValue: 1) static let optionFemale = SexOptions(rawValue: 1<<1) static let optionGmale = SexOptions(rawValue: 33) } public protocol OptionSet : SetAlgebra,RawRepresentable { } public protocol RawRepresentable { } public protocol SetAlgebra : Equatable,ExpressibleByArrayLiteral { } public protocol Equatable {} public protocol ExpressibleByArrayLiteral{} 字面量。 45、列举 enumerate:列举元素的同时,也需要下标 // OC的用法 func addf() { var arr:NSArray = [1,2,3,4,5,6] var r = 0 //ambiguous use of enumerateObjects为什么报错? arr.enumerateObjects { (value, idx, stop) ->Void in r += num as! Int if idx == 2 { stop.pointee = true } } print(r) } //Swift var arr = [1,2,3,4,5,6] func addfSwift() { var r = 0 //没有要求在闭包中操作,我还想测试一下循环引用的 for (idx, value) in arr.enumerated() { r += value if idx == 2 { break } } print(r) } let arr = [(1,2),(3,4)] for i in arr { print(i.0, i.1) } for i in arr.enumerated() { print(i.0,i.1) } for (a,b) in arr.enumerated() { print(a, b.0,b.1) } 输出如下: 1 2 3 4 0 (1, 2) 1 (3, 4) 0 1 2 1 3 4 EnumerateGenerator:包含元素索引下标,以及元素本身的多元组 EnumeratedSequence> EnumeratedSequence分析: EnumeratedSequence是一个结构体,范型结构体,范型要求为符合协议--Sequece协议 并且自身也符合协议--Sequece协议 怎么就跟元组挂上钩了呢??? 难道又是模式匹配吗,又或是字面量表达 字面量表达-》字面量表达协议-》协议规定了哪些方法?? switch,for,if,try..catch.., 1)判等 2)判可选类型是否为nil 3)判范围 底层如何实现的呢? 其实就是系统实现了~=操作符。 [(1,2),(12,312),(1234,1234)] 确实是啊!! public static func ~=(pattern:CountableClosedRange, value: Bound) ->Bool Sequece协议规定了一个~=模式匹配的方法 EnumeratedSequence<[(Int,Int)]> EnumeratedSequece<[Int]> 46、通过类型获取对应的编码?这又是个什么鬼 OC中的用法: @encode Swift中的用法: Metatype 不能获取任意类型的类型编码了。 但是在Cocoa中,即继承自NSObject类型的类,可以通过NSValue的objcType来获取对应值的类型指针。 如果需要获取Swift类型的类型编码,可以将他转换为NSNumber,NSNbumer是NSValue的子类,然后再获取类型 objCType let t1 = 1 as NSNumber print(String(validatingUTF8: t1.objCType)) let t2 = NSValue(cgPoint:CGPoint(x: 3, y:3)) print(String(validatingUTF8: t2.objCType)) let t3 =NSValue(cgAffineTransform:.identity) print(String(validatingUTF8:t3.objCType)) 输出如下: Optional("q") Optional("{CGPoint=dd}") Optional("{CGAffineTransform=dddddd}") //这有个毛的意思? Swift语言参考 类型、 Swift类型:string,dictionry,array,Int,Double。。。。 Swift中保留的C类型:CInt,CFArray.... Swift中保留的OC类型:NSDictionary... 函数类型,闭包类型,协议类型。。。。 表达式、 3+4, let a = 3 , somefunciton() 语句、 if else, while, for, do{try...}catch模式1{}catch模式2{}catch {} switch-case 模式匹配、 i in 1...10, case模式 where Self:SomeProtocol where i >10 声明、 特性、 范型 47、@asmname使用c的标准库 48、weak 1)协议前面加上@objc 2)协议后面加上class applied:应用 weak may only be applied to classand class-bound protocol types protocol ProtocolA17 { func method() } protocol ProtcolA18 where //这个类不继承那个协议,交给它所属的实例类来实现协议 class ClassA17{ //协议类型,这是一个成员属性,这个属性必须要求实现协议 weak var protocolObj:ProtocolA17? } class ClassTest:ProtocolA17 { var a:ClassA17! func viewDidLoad(){ //let a = ClassA17() a = ClassA17() a.protocolObj = self } func method() { print("helloworld") } deinit { logFlag() } } swift中的protocol协议: 值类型,引用类型都可以继承某一个协议,struct,enum虽然可以用protocol,但是不存在引用计数这样的内存管理问题,所以就无需用到weak @objc protocol ProtocolA17 { func method() } protocol ProtocolA20:class{ func method() } //这个类不继承那个协议,交给它所属的实例类来实现协议 class ClassA17:ProtocolA18 { //协议类型 weak var protocolObj:ProtocolA18? //method2, method3都不需要实现。 func method2(){ } } class ClassA20{ weak var obj:ProtocolA20? } class ClassTest:ProtocolA18,ProtocolA20 { var a:ClassA17! var b:ClassA20! func viewDidLoad(){ //let a = ClassA17() a = ClassA17() a.protocolObj = self b = ClassA20() b.obj = self } func method() { print("helloworld") } deinit { logFlag() } func method3() { } } 49、关联对象 public struct UnsafeRawPointer :Strideable, Hashable { } static var key:Void? &key=>>UnsafeRawPointer这样就可以转了吗? //key这个参数,为什么是要传入一个可变的指针 public func objc_getAssociatedObject(_object: Any!, _ key: UnsafeRawPointer!) ->Any! public func objc_setAssociatedObject(_object: Any!, _ key: UnsafeRawPointer!, _ value: Any!, _ policy: objc_AssociationPolicy) extension ClassA20{ static var title:()? static var key2 = "adfs" static let key3 = "123123" var title:String{ get{ return objc_getAssociatedObject(self, &ClassA20.title) as! String } set{ objc_setAssociatedObject(self, &ClassA20.title, newValue,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } var title2:String{ get{ return objc_getAssociatedObject(self, &ClassA20.key2) as! String } set{ objc_setAssociatedObject(self, &ClassA20.key2, newValue,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } //cannot pas immutable value as inout argument:key3 is a let constant var title3:String{ get{ return objc_getAssociatedObject(self, &ClassA20.key3) as! String } set{ objc_setAssociatedObject(self, &ClassA20.key3, newValue,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } } let a = ClassA20() print(ClassA20.key2) print(ClassA20.title) a.title = "hello" a.title2 = "world" print(ClassA20.key2) print(ClassA20.title) 输出如下 adfs nil adfs nil 50、线程同步 objc_sync_enter objc_sync_exit 怎么在swift中在封装一下,更加好用? class func lockSafe(lock:Any,l:()->()){ objc_sync_enter(lock) l() objc_sync_enter(lock) } class func testLock(){ let obj = ClassA20() objc_sync_enter(obj) print(obj) objc_sync_exit(obj) Test.lockSafe(lock: obj) { print(obj) } } 59、CF*****Swift自带的CF系列,内存管理自动管理的。不需要release等 60、 swift命令 repl:swift repl环境read eval printloop 可以进行简单的交互式编程,每输入一句语句,就立即执行到我们眼前 xcrun swift swift 如何写一个swift脚本,就像shell脚本一样? vi 1.swift #!/usr/bin/env swift print("hello") chmod +x 1.swift ./1.swift swift文件如何编译 vi 2.swift print("hello") swiftc 2.swift 3.swift other.swift.... ./main swift生成汇编代码 vi 3.swift print("hello") swiftc -O 3.swift -o 3.asm 61、print和debugPrint 结论, 1)实现了custom和customdebug其中的任何一个,print,debugPring打印的都是一样的结果 2)如果都实现了,pring调用custom,debugPrint调用customDebug 3)如果都没有实现,那就只能系统默认打一个ClassX.self的类型了 print是执行CustomStringConvertible协议规定的方法 printDebug是执行CustomDebugStringConvertible协议规定的方法 对于一个普通的对象,只能打印出它的类型。 struct可以打印出成员的名称和值 如何实现一个CustomStringConvertible协议? extension ClassA20:CustomStringConvertible{ var description: String { return "helll" } } extensionClassA20:CustomDebugStringConvertible { var debugDescription: String { return "world" } } 1)实现CustomStringConvertible,不实现CustomDebugStringConvertible: helll helll 2)不实现CustomStringConvertible,实现CustomDebugStringConvertible: world world 3)实现CustomStringConvertible,实现CustomDebugStringConvertible: helll world 4)不实现CustomStringConvertible,不实现CustomDebugStringConvertible: Xcode8_swift3_ios8_10.ClassA20 Xcode8_swift3_ios8_10.ClassA20 print(ClassA20.self) debugPrint(ClassA20.self) 输出 ClassA20 Xcode8_swift3_ios8_10.ClassA20 62、断言 断言:它是一个开发时的特性,只有在debug编译的时候有效。而在运行时是不能被编译执行的。 所以,在代码发布的时候,我们不用刻意去将这些断言手动清理掉。 这是默认的断言特性 target, build settings swift compiler-custom flags中 other swift flags中添加 -assert-config Debug来强制启用断言, -assert-config Release来强制禁用断言 貌似不管用啊!!! 在release中,如何强制终止程序呢,我们最好不要修改断言的配置选项。 而是使用另外一个函数。 fatalError 调用这个方法,不需要返回值 func asd()->Int{ fatalError("asdf") } 断言只会在Debug环境中有效,而在Release编译中所有的断言都将被禁用。在遇到确实因为输入的错误无法使程序继续运行的时候,我们一般考虑以产生致命错误(fatalError)的方式来终止程序。 63、面向协议编程和模拟的抽象函数的方式 64、错误和异常 异常 1)为什么要用异常? 调用某些方法,我们开发时候很容易忽略的时候,就用异常,避免我们忽略nserror 同步调用中用异常 异步调用不用异常,用error 2)怎样使用异常 do try catch try? try! throws 实现一个继承Error枚举的枚举类。抛出这个新的枚举类型。 class func someMethodTrhows2 (b:Bool)throws->Int? { if b { throw myError.value } return nil } //返回的是nil还能执行if。因为是optional套一个optional if let a = try?someMethodTrhows2(b: false){ print(a) } else { print("err") } rethrows : 在方法中加rethrows,表示这个方法的型參列表中,有一个参数,也可能抛出异常,即是一个能抛出异常的闭包类型或者函数类型, 然后呢,这个方法本身自己不会抛出任何异常,除了型參的方法被调用抛出异常外。 如果这个方法,仍然用throws来修饰:表明,型參闭包被调用时,抛出异常;自己的处理过程中,也允许抛出异常。 凡是调用了抛出异常的方法,在调用它时,都必须加上try的形式来调用。 这表明啊:加rethrows的方法,只要它的参数,我们给他传递进去的时候,虽然在型參中我们声明了这个函数可能抛出异常,但是 我们在实參的定义中,如果作为实參的闭包,并没有抛出异常,既没有写throw Error.XXX时,我们是可以不用try来调用的!! 既可以接受普通函数,也可以接受一个普通函数,虽然这个参数是throw的 //报错 someMethodTrhows1(b: true) //报错 someMethodTrhows3(b:true) { (b) ->Int in if b {throw myError.value} } //不报错,可以这样用 someMethodTrhows3(b: true) { (b) ->Intin return 1 } //必须要加try调用 try!someMethodTrhows4(b: true) { (b) ->Int in return 100 } a function declared rethrows may only throwif its parameter does class func someMethodTrhows3(b:Bool,f:(Bool)throws->Int) rethrows->Int { let _ = try f(true) //a function declared rethrows may only throw if its parameter does //if b { //throw myError.value //} return 100 } class func someMethodTrhows4(b:Bool,f:(Bool)throws->Int) throws->Int { let _ = try f(true) if b { throw myError.value } return 100 } let _ = try?someMethodTrhows3(b: true, f: {(b:Bool) ->Int in if b { throw myError.value } return 100 }) let _ = try?someMethodTrhows4(b: true, f: {(b:Bool) ->Int in if b { throw myError.value } return 100 }) 65、framework orextension 框架or扩展? 1)单独为swift制作框架-》专门生成框架的项目 将整个框架项目,包括源代码,以项目依赖的方式添加到自己的项目中,并一起编译使用。 shift+cmd+i release版本 cmd+b debug版本 2)制作的框架只能嵌入到自己的app中 3)用纯Swift制作可用的第三方库 66、字符串=》使用原始值为String的enum类 然后通过扩展类的extension,来引用这些enum。 R.swift SwiftGen,扫描所有文件-》提取字符串-》自动生成enum或者struct文件 67、 @dynamic:告诉编译器,我们不会再编译时就确定这个属性的行为实现 不需要在编译期间对这个属性的getter或setter做检查和关心。 表示我们将在运行时来提供这个属性的存取方法,如果在运行时,没有对这个属性提供存取方法,就会crash CoreDataModel, 使用xcode工具,自动生成NSManagedObject子类 Swift,不保证一切都走动态派发。 CoreData专用:@NSManaged 68、KVO、KVC 动态派发 观察的对象标记为dynamic 在oc中,KVC的属性,进行监听。而现在,需要NSObject的,dynamic修饰的,可以监听【喵神 Swift 编程学习心得分享】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
终于有人分享 swifter 学习笔记了!
有8位网友表示赞同!
期待看看喵神的理解和总结
有19位网友表示赞同!
我一直想学习Python爬虫,swifter看起来很简单上手就打算试试看!
有13位网友表示赞同!
看到喵神这个名字,感觉这应该会是一份非常棒的笔记
有20位网友表示赞同!
我正在学习自然语言处理, swifter 可以帮到我很大的忙啊!
有9位网友表示赞同!
分享这份学习笔记真是太感谢了!
有18位网友表示赞同!
之前一直用别的爬虫框架,看来 swifter 更适合我的需求!
有19位网友表示赞同!
希望喵神也分享一些实战案例吧!
有10位网友表示赞同!
这篇文章一定能帮我更快地入门Python爬虫!
有17位网友表示赞同!
我感觉 Python 的学习资源越来越多了!
有8位网友表示赞同!
喵神太牛了,居然把 Swifter 写成笔记还公开了分享!
有12位网友表示赞同!
以后遇到 Python 爬虫问题就来看一下这篇笔记吧!
有16位网友表示赞同!
这篇文章是不是可以放到 Github 上去?方便大家一起查看和学习
有9位网友表示赞同!
我喜欢使用简洁高效的工具,swifter 看起来很不错!
有10位网友表示赞同!
终于找到一份适合初学者学习 swifter 的笔记了!
有10位网友表示赞同!
我要分享这个笔记给我的 Python 学习伙伴们!
有6位网友表示赞同!
Python爬虫真是很有用啊!期待能学到更多有关 swifter 的知识!
有15位网友表示赞同!
学习 swifter 肯定能让我更快更轻松地完成项目!
有12位网友表示赞同!
喵神写的笔记一定很详细易懂,太感谢了!
有18位网友表示赞同!