(一)简介程序员
(1)优于OC,快速,安全json
(2)取消了预编译指令包括宏定义(OC用的太多了)swift
(3)取消了OC指针和不安全访问的使用(看不到星星了)api
(4)所有点语法数组
(5)3.0中对Foundation框架作了不少改变,去除了NS,将绝大部分class转换成struct结构体(为了考虑性能和安全性,绝大部分使用结构体来代替之前的类,可是在实际使用感受不到)安全
(6)之前是OC调UIKit,如今就是Swift调UIKit,这点事没问题的闭包
(7)swift由于语法的严谨性可让不少错误提早遇到,这样不多出现bug让程序停在main致使没法找到app
(8)@UIApplicationMain是程序的入口框架
(9)只有.h没有.m异步
(10)全部的代码都包括在{}里,默认方法func都有缩进!
(11)语法的allocinit替换成()
(二)PlayGround
(1)能够看苹果官方自带的tips和100个tips,都在Placground来使用
(三)基础
(1)不适用self. 在闭包或者编译器提示的时候再使用
(2)分号是用来分割语句的,若是一行洗不少,就能够加分号,通常时候能够不加
(3)#function打印执行的函数
(4)添加标记用到// MARK: - 选择,若是是接下来要作的能够用// TODO:和// FIXME:这些很是有用
(四)变量和常量
(1)let:常量,若是从没被修改过,那就用let,不可变的更安全,因此尽可能使用let,须要变化时候改var
(2)var:变量
(3)能够自动推导类型(Option + Click)整数默认Int,小数默认Double
(4)Swift对类型要求异常严格,任何不一样类型的数据不能直接运算(哪怕是Int和Double),不会作一些自动的转换来转换成Double。Swift不存在基本数据类型,Int和Double都是结构体其实,强转用Double(x)完成,或者在定义的时候直接指定变量的类型let x : Double = 10;(不多使用)
(五)可选项(Optional)
(1)定义变量时,若是是可选的,表示能够有值,也能够是nil,用“?”
(2)强行解包 “!”,程序员来注意!,而且要少用,可能会崩
(3)最多见的错误:解包的时候发现nil。fatal error: unexpectedly found nil while unwrapping an Optional value
(4)let可选的话,没有默认值,须要赋值。var可选的话,默认值为nil
(5)可选项在参与计算时候必须解包
(六)逻辑分支(if)
(1)三目运算符:Int(x!) > 5 ? print("dayu5") : print("xiaoyu5") 或者 Int(x!) > 5 ? print("dayu5") : () 这样就对后面的不做处理。()表示空执行。
(七)不强行解包的方法
(1)强行解包的写法:"??"一个简单的三目,这样无需作不少判断,是否是xy都不得0了。注意?? 必须加个(),由于??操做符号的优先级低,是最后判断的,因此不加()可能后面的都当作判断不执行了。??写法不须要解包了
func demo(x: Int? , y : Int?) {
print( (x ?? 0) + (y ?? 0) )
}
(2)if let的写法:iflet/ifvar连用就能够进行判断,这个let的x1和y1做用于只在循环里,iflet/var也不须要解包了
if let x1 = x , let y1 = y {
print(x1 + y1)
}
(3)guard let else的写法:和iflet相反,else里面通常是没值return,以后才执行须要的代码。guard能够下降分支层次,若是要执行的代码不少,原本在if里执行,{}就多了一层,若是用guard守卫必定有值才执行,这样层次就少了一层。guardLet很重要,也能够省略不少解包
guard let x1 = x , let y1 = y else {
print("x&y没值")
return
}
print(x1 + y1)
(4)guardlet和iflet能够用同名变量接收。由于总会取名字,if let name = name这样就能够,注意后面使用的时候用非空的那个!而且iflet和guardlet能够依次判断,先判断是一个字典,再拿字典的数组,在判断数组的值,能够一条线判断出来。
(八)循环
(1)switch:
*(C中分支必须是整数,每个语句都须要break,若是要定义局部变量须要{}
* Swift能够任意判断,通常不须要break,多值判断用逗号,全部分支都至少须要一条指令,若是什么都不干,才要写break
func demo(name : String) {
switch name {
case "guoguo","aixin":
print("guoguo")
default:
print("shit")
}
}
(2)for:swift取消了i++和++i和传统的for循环
for i in 0...5 {
}
for i in 0..<5 {
}
(3)反序遍历:
for i in (0..<10).reversed() {
}
(九)字符串:用String,是一个结构体,具备绝大多数NSString功能,支持直接遍历
(1)遍历:
func demo3() {
// 字符串遍历(NSString不支持这么遍历)
let str = "wowosnshi是"
for s in str.characters {
print(s)
}
}
(2)长度:
// 返回指定编码对应的字节数,每一个汉字三个字节
print(str.lengthOfBytes(using: .utf8))
// 返回真正字符串长度
print(str.characters.count)
(3)拼接:要注意可选项拼接不解决会带上Optional,剩下的均可以拼接,不再用看StringWithFormat了
let name = "AA"
let age = 19
let title : String? = "sss"
print("\(name)\(age)\(title ?? "")")
(4)格式化:
*格式化成日期
let h = 8 , m = 10, s = 44
// OC中用stringWithFormat格式化日期,Swift中能够
let strDate = String(format: "%02d-%02d-%02d", h,m,s)
print(strDate)
(5)截取字符串:建议用NSStrin做中转,由于swift取串方法一直在改变
*NSString方法
let str = "红红火火恍恍惚惚"
let strOC = str as NSString
strOC .substring(to: 1)
strOC.substring(with: NSMakeRange(0, 2))
*3.0方法
(十)数组:
(1)就是中括号,注意数组的类型,而且基本数据类型不须要包装,能够直接方数组里,若是类型不同(混合数组,可是基本不用),自动推导[NSObject]。在Swift中还有一个[AnyObject类型],标示任意对象,由于在Swift中一个类能够没有任何父类。
(2)遍历:
let array = ["张三","李四","王五"]
// 遍历1(按照下标遍历)
for i in 0..<array.count {
}
// 遍历2(遍历元素)
for s in array {
}
// 遍历3(同时遍历下标和元素)
for e in array.enumerated() {
// let e: (offset: Int, element: String) e是一个元组
print("\(e.offset), \(e.element)")
}
// 遍历4(同时遍历下标和元素)
for (n,s) in array.enumerated() {
print("\(n),\(s)")
}
// 反序遍历
for s in array.reversed() {
}
// 反序索引下标(这样写才对,先枚举再反序)
for (n,s) in array.enumerated().reversed() {
}
(3)增删改:
array.append("AA")
array[1] = "BBB"
array.remove(at: 2)
(4)合并:用“+”号。可是要合并的数组的两个类型必须一致。
(十一)字典:通常是[String:NSObject],对应键值对.因为3.0后大部分都是结构体了,AnyObject很差用了,Any范围更大
(1)字典数组:
(2)增删改:和数组都相似,就是两个字典合并不像数组直接相加,而是须要遍历
(十二)SWift的类,结构体,枚举三种都有构造函数,均可以有方法,就像OC的类。枚举再swift变化很大,通常开发不会用到过高级语法。
(十三)函数:
(1)外部参数,当外部参数用_替代的时候,会在外部调用的时候忽略形参名
(2)函数的默认值(OC不具有),这个使Swift比OC灵活不少不少,一个方法能够作不少事,由于OC会有各类参数和组合,Swift只需写一个最多的参数,而后不须要的设定默认值就是了
3)无返回值 :直接省略 () Void均可以
(4)闭包:相似Block,比Block还普遍。OC中Block是匿名函数,Swift中函数是特殊的闭包。闭包在整个开发中和Block的应用场景同样。用于控制器/自定义视图/异步执行完成的回调。这些回调的特色就是都是以参数回调处理结果,返回值为Void。
*定义:
let biBao = { (x: Int) -> Int in
return x + 100
}
print(biBao(10))
*GCD:将任务添加到队列,指定执行任务的函数。任务就是Block/闭包,队列以同步/异步的方式执行。
func loadData(compeletion:@escaping ( _ result: [String])->()) -> Void {
DispatchQueue.global().async {
print("耗时操做会得到一些结果 \(Thread.current)")
Thread.sleep(forTimeInterval: 1.0)
let json = ["天气","不错","刮大风"]
// 主线程回调
DispatchQueue.main.async(execute: {
print("主线程更新UI \(Thread.current)")
// 回调 -> 经过参数传递 执行闭包
compeletion(json)
})
}
}
调用:
// 执行的适合我就拿到了值
loadData { (result) in
print("获取的新闻数据 \(result)")
}
*尾随闭包:若是函数的最后一个参数是闭包,那么参数就省略了,最后一个参数直接{}大括号包装
*闭包的循环引用:
方法1
方法2
(5)面向对象(各类构造函数):()就是allocInit,在Swift中对应init()。在swift中一个项目全部类都是共享的,能够直接访问,每个类都默认有一个命名空间。A.name B.name God.name Dog.name。同一个类能够从属于不一样的命名空间(假若有一个框架有Person类,作用户,还有一个框架作后台,也用Person。在OC中就只能靠前缀解决,HouTaiPerson,KuangJiaPerson。而Swift中的命名空间就是项目名。AAA项目有一个Person,那么AAA.Person就是AAA的Person类,此时再导入框架,那也是框架的.Person)
*在自定义的Nsobjiect类中,has no initalizers 标示没有初始化器,初始化器能够有多个,默认是init。当这个类有属性的时候,属性要分配内存空间,就是说要有初始值。那么其实就是先给本身的属性分配,而后给父初始。其实这么一看,Swift和OC是相反的!
思路:OC是先调用爸爸。就是Person,Person会再调用NSObject,就是先跑上去什么都无论,先初始化了NSObject,而后才往下走挨个初始化。Swift是把本身彻底初始化,再上去初始化爸爸,这么看比OC快了一圈,性能要好。
*重载构造函数:(重写是父类有这个方法,override。重载是函数名相同,参数和个数不一样。init就重写,init+参数就重载。OC是没有重载的!都是initWithXXXXX)。重载实际上是最基本的方式,OC没有其实很low,可是Swift有。
注意:若是重载了构造函数而且没有实现父类的init,那么系统再也不提供init构造函数了(默认是有的),由于默认的构造函数不能给本类的属性分配空间(你不本身写name = ,系统就没办法分配)
nsobject类的isa属性就是为了记录当前状态的对象是什么的,就是一个student对象,云云。在swift中打p能够打印类内容
*KVC构造函数:只需记住下面4点
****因此通常在模型中加个? 而后用KVC实现(先调用init由于是运行时机制)
*模型中属性定义:基本数据类型 = 0,对象设置?
运行时中,基本类型设置? 属性设置私有都会让运行时拿不到,此时kvc就会出错。
*若是子类没有重写父类方法,调用的时候就会直接调用父类的方法。当继承一个类,就继承全部属性和方法,包括KVC。当PERSON写好了KVC后,
*总体
(6)便利构造函数:关键字Convenience(开发用的不多,由于模型都是框架转,UI不须要便利)
*目的:条件判断,只有知足条件才实例化对象,防止没必要要的内存开销,简化对象建立。自己是不负责属性的建立和初始化的。
说白了就是有些函数 带个? 返回值能够返回空,这就是便利构造函数的功劳。
* 主要用于条件检查和控件建立。
在控件建立的时候,就不用?了,由于我就是为了建立控件的。
(7)deinit:相似OC的Dealloc
(十四)分类:extension
便利构造函数 + 分类能够省略抽取不少代码。例如给UITextField/UIButton写分类,而后写便利构造函数,方便。
(十五): 运行时能够获取到一个对象的全部属性方法等等,获取到了属性能够KVC进行字典转模型,这是全部第三方转模型插件的基础,获取到了方法,能够动态的发送各类方法。在swift中,若是一个基本变量Int什么的用?修饰了,可选了。此时运行时是找不到的,因此KVC会崩溃,同时,若是修饰了private属性,运行时也是找不到,KVC也会崩溃。其实在OC中,private是基本不用的,并且存不住任何私有,均可以被运行时找出来。可是swift就是真的藏起来了,找不到这个属性和方法了外界。