1、隨機數(shù)
不需要隨機數(shù)種子
arc4random()%N + begin:產(chǎn)生begin~begin+N的隨機數(shù)
arc4random_uniform(endIndex-startIndex)+startIndex:產(chǎn)生startIndex到endIndex的隨機數(shù)
arc4random_uniform(N):產(chǎn)生0~N-1之間的隨機數(shù)
2、自動閉包;??操作符如何實現(xiàn)
1)閉包
閉包標準定義
{[捕獲列表] (參數(shù)) ->返回類型in語句returnxxx}
//自動閉包,閉包標準定義
testClusure { (s, s2) -> String in
return "1"
}
//根據(jù)上下文:推斷類型,推斷類型指的是1)返回類型,2)參數(shù)類型
testClusure() {
s1, s2in
return "123"
}
//單表達式:隱式返回,表達式的值作為返回值
testClusure { s1, s2 in
"asdfasdfadsf"
}
//參數(shù)名稱縮寫
testClusure {
$0 + $1
}
testClusure(clusure: +)
//尾隨閉包省略括號()
testClusure { (s1, s2)in
returns1 + s2
}
2)自動閉包
不接受任何參數(shù)!!
表達式的值,會被返回
//自動閉包
testClusureAuto(adsf:"asdfasdfasdf")
func testClusureAuto(adsf clusure:@autoclosure () -> String) {
}
省略花括號,用一個普通的表達式來代替顯示的閉包
表達式、語句
自動閉包的意義:延遲求值
??
&&
||
()->T
T
如果我們直接使用T,意味著??操作符取值之前,我們就必須準備好一個默認值傳入到這個方法中。
如果這個值是經(jīng)過一系列的復(fù)雜運算,就會造成浪費,因為如果optinal值是有值的,根本就用不上T這個默認值
而是直接返回解包后的值。
這樣的開銷是可以完全避免的,就是將默認值的計算推遲到判斷optional為nil之后
逃逸
@escaping
閉包
值捕獲
引用類型,值類型
let playClosure = {
(child:Child) -> ()? in
child.Pet?.toy?.play()
}
func play() {
}
if let a:() =playClosure(xiaoming) {
}
let playClosure = {
(child:Child) -> String? in
child.Pet?.toy?.play()
}
func play() -> String {
return "adsf"
}
if let a =playClosure(xiaoming) {
}
child.Pet?.toy?.play()單表達式閉包隱式返回,整個表達式的值作為閉包的返回值
就看play的定義了
這樣的調(diào)用將會返回一個()?
其實就是一個可選的空元組:貓神也不是萬能的啊,這都說不明白:“雖然看起來挺奇怪的,但這就是事實”
3、操作符
1、重載操作符
2、聲明一個新的操作符
定義一個操作符的優(yōu)先級
結(jié)合律方式,優(yōu)先級順序
操作符不能定義在局部域中,要求能在全局返回使用你的操作符
adjacent operators are in non-associativeprecedence group tt
adjacent相鄰
associative組合
precedence優(yōu)先級
struct Developer{
static func test() {
let t1 = Developer()
let t2:Developer = "a"
let t3 = "helloooooo"
let _ = t1~=t2~=t3
}
}
//字面量表達
extensionDeveloper:ExpressibleByUnicodeScalarLiteral{
typealias UnicodeScalarLiteralType = String
init(unicodeScalarLiteral value: String) {
logFlag("我就啥也不干")
}
}
//操作符重載
precedencegroup tt {
//指定結(jié)合性
associativity:left
//指定優(yōu)先級
higherThan:MultiplicationPrecedence
}
infix operator ~=:tt
func~=(left:Developer,right:Any)->Developer{
print("我給Developer類實現(xiàn)了一個自定義的操作符:~=,有需要用的嗎?")
return left
}
//不指定優(yōu)先級和結(jié)合性也可以重寫啊
infix operator ~+
func ~+(left:Developer,right:Developer){
print("我就啥也不干,就看看操作符是這些重寫嗎")
}
4、inout
&:
inout原理:inout,修改變量。在函數(shù)內(nèi)部創(chuàng)建了一個新的值,并把這個值賦值給原來的變量
值類型:
inout在函數(shù)內(nèi)部,創(chuàng)建了一個新的值,然后在函數(shù)返回的時候,把這個值符給了給&修飾的變量,
這與引用類型的inout機制是不同的。
如果是引用類型呢??
5、字面量表達
字面量表達-》字面量表達協(xié)議-》協(xié)議規(guī)定了哪些方法??
一個類型支持字面量表達賦值,則需要自定義一個相關(guān)類型的表達協(xié)議,并把這個類型繼承他
自定義一個自己的字面量表達
隱式轉(zhuǎn)換,使用字面量的方式進行
let a = "asdfasdfafsd"http://這就是字符串字面量
let a =
["asdfafsd","asdfasdf"]//數(shù)組字面量
let a =
["a":"asdfasdf","b":"1231321"]//字典字面量
把一個類型,實現(xiàn)ExpressionByBooleanLiteral系列的協(xié)議,這個類就支持字面量表達了
字面量表達很隱蔽的特性。缺點是,沒有辦法對字面量復(fù)制進行跳轉(zhuǎn)。我們不知道這個賦值到底是在哪里實現(xiàn)的
6、下標
重寫下標操作符
7、嵌套
函數(shù)嵌套
8、命名空間
默認是使用自己所在的target的.編譯系統(tǒng)會根據(jù)不同的targe自動加上命名空間。
如果在同一個target里面,如果定義的某個類是相通的,還是會產(chǎn)生沖突
app:
第三方framework:
myframework.myclass
9,typealias
別名
場景1
class df{
}
//typealias dff = df
typealias dff =df
場景2--組合協(xié)議
protocol Pro1{}
protocol Pro2{}
typealias Proall = Pro1 & Pro2
10、associatedtype:關(guān)聯(lián)類型
1)
協(xié)議中聲明一個關(guān)聯(lián)類型,在協(xié)議中規(guī)定的屬性、方法中使用這個關(guān)聯(lián)類型
當某個類、結(jié)構(gòu)體、枚舉約定為繼承這個協(xié)議時,
在實現(xiàn)這個協(xié)議規(guī)定的方法中,可以對協(xié)議規(guī)定的關(guān)聯(lián)類型進行指定,
這樣在實現(xiàn)這些協(xié)議方法、屬性時,不同的類、結(jié)構(gòu)體、枚舉,雖然繼承同樣一個協(xié)議,
但是,操作的結(jié)果就不一樣的,不需要對類型進行is as? as!方法進行類型判斷!
2)有associatedtype的協(xié)議,不能單獨使用
protocol animal can only be used as ageneric constraint
because it has self or associated type
requirements
protocol Animal{
associatedtype F
func eat(food:F)
}
struct Tigger:Animal{
typealias F = Meat
func eat(food: Meat) {
print("老虎吃肉")
}
}
protocol Animal2{
func eatFood()
}
extension Animal2{
func eatFood(){
}
}
struct Chicekent:Animal2{}
struct Dogg:Animal2{}
func isDangerous(animal:Animal2)->Bool {
if animal is Dogg {
return true
}else {
return false
}
}
//func isDangerous(animal:Animal)->Bool {
//if animal is Tiger {
//return true
//} else {
//return false
//}
//}
11,可變參數(shù)
只能有有一個參數(shù)是可變的
可變參數(shù)的類型都是相同的,但是可以用Any
12,init,deinit順序
init先子類,再父類
deinit先子類,再父類
super.init可以不用寫的,系統(tǒng)會自動加上,如果要修改父類的值,則需要顯示調(diào)用super.init,然后在訪問父類的變量,進行修改。
要在init中調(diào)用init,需要在init前面加convenience
父類中帶參數(shù)的init在子類中重載時,子類的這個init實現(xiàn)中系統(tǒng)不會自動加,需要手動添加
父類的便利構(gòu)造器,子類調(diào)用父類便利構(gòu)造器實現(xiàn)的init方法,子類不需要寫便利構(gòu)造器,同樣可以獲得便利構(gòu)造器的使用
13,optional init
求x的y次方pow
14,class,static
1)非class類型,struct,enum:使用static
2)class專門用在class類型中,如果用static,表示不可以重寫
3)協(xié)議中使用static
至于為什么?
class可以重寫,static不可以重寫
struct,enum值類型的數(shù)據(jù)類型中,可變存儲屬性,常量存儲屬性,計算屬性,方法類屬性,類方法都是子類不可以重寫的,因此用static
struct,enum值類型不允許實現(xiàn)子類,就不存在重寫的問題,所用static,表示不可以重寫
struct,enum不允許繼承:inheritancefrom non-protocol type 'StructA1'
協(xié)議中規(guī)定的屬性,方法,也是不可以在子協(xié)議中進行重寫的,因此用static
class類中用class類屬性:只能是計算屬性,可以用class,static
protocol協(xié)議中,加static,類屬性、類方法
struct A1{
func printHello(){}
}
//struct A2:A1 {
//func printHello(){}
//}
class ClassA1{
func printHello(){}
class func printHello2(){}
static func printHello3(){}
static var s1:String = "123"
class var s2:String {get{return "123"}}
static let s3:String = "1212"
}
class ClassB1:ClassA1{
override func printHello(){}
override class func printHello2(){}
//override static func printHello3(){}
}
protocol ProtocolA1 {
static func printHello()
static var s3:String{get}
//class func printHello2()
//protocol協(xié)議,實例屬性可以實現(xiàn)為計算型,也可以實現(xiàn)為存儲型
var s4:String{get}
var s5:String{get set}
var s6:String{get}
}
class ClassA2:ProtocolA1{
static func printHello() {
}
static var s3: String {return "asdfasf"}
var s6: String {return "asdfasd232"}
var s4: String = {return "asdfasdfa"}()
var s5: String = "1234123"
}
15、集合
1)Dictionary,array,set類型都是相同的,或者都為any
2)如何實現(xiàn)一個多類型集合呢?巧用枚舉來實現(xiàn),存儲多種不同類型的值
枚舉關(guān)聯(lián)值
class func testAnyCollection(){
let a =[strOrInt.getInt(123),strOrInt.getStr("asdfa"), strOrInt.getBlock({(hell) in
print(hell)
})]
for i in a {
switch i {
case .getBlock(let a):
a("1341234123")
case .getStr(let s):
print(s)
case .getInt(let n):
print(n)
//case .getIntAndStr(let s, let n):
//print(s)
//print(n)
case .getIntAndStr(let s, 1):
print(s)
case .getIntAndStr(let s, let a):
print(s, a)
}
}
}
enum strOrInt{
case getStr(String)
case getInt(Int)
case getBlock((String)->())
case getIntAndStr(String,Int)
}
16、正則表達式
如何構(gòu)建一個正則表達式工具
這個工具用一個struct來組織
1)提供pattern變量,提供一個初始化方法,提供一個匹配方法
2)更高級一點的方法是:實現(xiàn)一個操作符,
func =~(left:String, right:String) ->Bool {
}
17、模式匹配
switch,for,if,try..catch..,
1)判等
2)判可選類型是否為nil
3)判范圍
底層如何實現(xiàn)的呢?
其實就是系統(tǒng)實現(xiàn)了~=操作符。
18、...和..<
其實這就是range操作符
這個操作符,系統(tǒng)有一系列的操作符范型函數(shù)的定義
...start<=end
..
range操作符返回一個:范型閉開區(qū)間或者范型range
HalfOpenInterval
Range
ClosedInterval
應(yīng)用場景:
1)for語句
2)先創(chuàng)建一個閉開或者range,然后使用閉開或者range的coutains方法,判斷某個字符是否屬于這個閉開區(qū)間。
比如判斷是不是小寫字母
19、.self,和.Type
AnyClass
.Type存放類型的類型
有Int類型:存放的是整形值,String類型:存放的是字符串,AnyObject.Type類型存放的是Anyobject類型
ClassA.self:類型實例
一個存放類型的類型,怎么稱呼他?元類型
意義:
調(diào)用類方法:調(diào)用類方法的時候可以用這個元類型的實例來調(diào)用它的類方法
.self類型實例
.Type類型實例的類型
.self協(xié)議實例
.Protocol協(xié)議類型實例的類型
//協(xié)議元類型,有啥作用呢
let s11:ProtocolA1.Protocol = ProtocolA1.self
//用法1,用模式匹配
//很明顯:系統(tǒng)沒有實現(xiàn)這種類型的模式匹配操作~=,那我們來一個
let e:[Any.Type] =[NSString.self,NSDictionary.self,NSArray.self,ClassA3.self,String.self,(()->()).self]
for i in e {
switch i {
case NSString.self:
print("這里存放了一個nsstring類型,把這個類型存起來了")
case String.self:
print("string類型")
case (()->()).self:
print("得了")
default:
print("asdfa")
}
}
func ~=(left:Any.Type,right:Any.Type)->Bool{
if left == right {
return true
}
return false
}
//用法2,用if語句
let arr:[AnyObject.Type] = [ClassA3.self,ClassA1.self]
for i in arr {
if i is ClassA1.Type {
letd = i as! ClassA1.Type
d.printHello2()
}
if i == ClassA3.self {
let d = i as! ClassA3.Type
d.print2()
}
}
20、Self
copy方法舉例
//定義個一個協(xié)議:使用Self
protocol Copyable{
func copy()->Self
}
class MyClass:Copyable{
func copy()->Self{
let r = type(of:self).init()
return r
}
required init(){
}
}
21、動態(tài)類型
多方法
swift,編譯器編譯的時候,決定使用哪個方法;swift默認情況下,不采用動態(tài)派發(fā)。
方法的調(diào)用在編譯的時候決定。
如果不要系統(tǒng)自動派發(fā),可以修改代碼,用as?類型進行判決,調(diào)用對應(yīng)類型的方法
22、屬性觀察器
1)willset,didset存儲型屬性可以加,計算型屬性不允許加觀察器。
因為計算型屬性,本來就可以監(jiān)控到屬性的改變
2)如果偏要給已有的類型增加觀察器,怎么操作?
用子類來繼承。繼承了以后,給父類的任何屬性:存儲型,計算型都可以加觀察器,我們不用管他是
存儲型還是計算型。
3)唯一注意點是什么:
正因為子類重寫父類的計算型屬性的觀察器,didset方法會先讀oldvalue,這將導(dǎo)致父類的get方法被調(diào)用。
23、什么情況下使用final
1)md5算法、des加密解密的工具類,很穩(wěn)定了,可以加final。
2)某些類似編號的產(chǎn)生方法等對系統(tǒng)的正確運行決定作用的屬性或方法,加final,防止子類重寫時給系統(tǒng)造成錯誤
3)加了final,子類不能去做一些自己可以做的事情,怎么破解呢?
我們可以在final的這個方法中,調(diào)用一個方法,并在當前類定義中實現(xiàn)這個方法,在這個方法斷言,子類必須去重寫。
這樣,就解除了我們在調(diào)用final方法過程中不能做一些自己想做的事情。
class ClassB3:ClassB2{
override func getConfigValue() -> String {
return "come from b3 class !!"
}
}
class ClassB2{
final func printHello(){
print("load begin")
let a = getConfigValue()
print("load end"+a)
}
func getConfigValue()->String{
fatalError("子類必須要實現(xiàn)這個方法")
}
}
24、lazy
延遲屬性、延遲方法
1)延遲,相比于oc,延遲存儲屬性,延遲計算屬性
延遲存儲變量,延遲計算變量
2)如果沒有貓神,確實我僅知道1的應(yīng)用場景
swift提供了幾個全局方法
//序列: lazy方法名,范型列表,參數(shù):范型參數(shù),符合協(xié)議SequenceType的一個實例,返回一個LazySequence范型類實例
func lazy(s:S) ->LazySequence
//無序
func lazy(s:S) ->LazyRandomAccessCollection
//雙向
func lazy(s:S) ->
LazyBidrectionCollection
//前向
func lazy(s:S)->LazyForwardCollection
給一個集合,返回一個集合
這個比較難
arr.lazy.map
25、swift運行時
反射和mirror
class func testRuntime(){
let a = PersonA(name: "asdf", age: 12)
let mirror = Mirror(reflecting: a) // MirrorType
for child in mirror.children {
print(child.label , child.value)
}
}
class PersonA{
var name:String
var age:Int
init(name:String,age:Int){
self.name = name
self.age = age
}
}
應(yīng)用場景:
1)在運行的時候,通過Mirror的手段,了解一個Swift類型的實例的屬性信息
我們可以把某一個swift實例,通過mirror,得到children,
label,value集合值,找到我們要找的目標key value
2)局限:swift的mirror只能讀取,不能修改。我們最好不要在app中用這個mirror,
而是在playground和repl中對類的層次進行探索
26、隱式解包
可選類型
?
!
Optional
1)可選類型,是什么類型??
是結(jié)構(gòu)體,枚舉,類,閉包,元組,函數(shù)?
當然是枚舉
enum Optional {
//啥也沒有
case None
//關(guān)聯(lián)類型:關(guān)聯(lián)一個T類型的實例
case Some(T)
}
2)
多重Optional是個什么鬼?
這樣理解,
var a:String? = nil
let b:String?? = a盒子?盒子?放了一個字符串
let c:String?? = nil盒子?空盒子or不是空盒子
3)Optional Map
extension CollectionType {
//入?yún)ⅲ阂粋€閉包: 1)參數(shù)是采納本身這個協(xié)議的一個element實例2)返回值是返回一個任意類型
//返回值:返回一個任意類型的數(shù)組
publicfunc map (transform:@noescape ((Self.Generator.Element) -> T))-> [T]{
//Swift標準庫具體的實現(xiàn)
}
}
public enum Optinal:_Reflectable,NilLiteralConvertible {
//入?yún)ⅲ阂粋€閉包:1)參數(shù)是一個任意類型,2)返回值是任意類型的這么一個閉包
//返回值:任意類型
publicfunc map(f:@noescape((T)->U))-> U? {
//Swift標準庫實現(xiàn)
}
}
Int?=>Optional
String? =>Optional
Array? => Optional
函數(shù)式編程的思想,他是一種思想,寫一個函數(shù),約定一個規(guī)則,在這個規(guī)則下寫這個函數(shù),不要亂搞。
我們因此又稱他為范式。
函數(shù)式編程的范式又是什么呢?
1,函數(shù)是第一等公民
2,只用表達式,不用語句
表達式:單純的運算過程。總是有返回值
語句:執(zhí)行某種操作,沒有返回值
函數(shù)式編程的出發(fā)點動機,就是處理運算。
3,沒有副作用
函數(shù)內(nèi)部與外部互動,產(chǎn)生表達式運算以外的結(jié)果。
函數(shù)式編程強調(diào):函數(shù)要保持獨立,
所有功能就是返回一個新的值,沒有其他的行為,尤其是不得修改外部變量的值。
4,不修改狀態(tài)
變量往往用來保存“狀態(tài)”,不修改變量,意味著狀態(tài)不能保存在變量中。
函數(shù)式編程使用參數(shù)保存狀態(tài)的一個特例就是遞歸。
5,引用透明
只要傳入什么參數(shù)相同,返回的結(jié)果永遠都是相同
Optional可選實例的map方法
結(jié)合類型的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、協(xié)議擴展
應(yīng)用場景:
1)提供一個協(xié)議方法的默認實現(xiàn),=》變相實現(xiàn)了可選協(xié)議
2)如果一個協(xié)議的擴展中提供了一個默認實現(xiàn),然后這個協(xié)議并沒有對這個默認函數(shù)進行聲明。
繼承這協(xié)議的類的實例調(diào)用這個方法時,還是可以調(diào)這個默認實現(xiàn)的。如果這個類中自己實現(xiàn)了這個協(xié)議方法,他會調(diào)用自己類里面實現(xiàn)的。
這正是按照我們所想的方法執(zhí)行的。
3)擴展一個協(xié)議的時候,加上where限定條件,可以指定1)、繼承這個協(xié)議的2)并且滿足條件的類、結(jié)構(gòu)體、枚舉Self,需要實現(xiàn)這個擴展
中的方法。
28,where在哪里使用
//報錯:where clasuecannot be attached to a protocol declaration
protocol ProtoclA18 where Self:String {
func method2()
}
協(xié)議不能像class一樣在名稱后面加來定義范型,但是可以使用關(guān)聯(lián)類型associated來定義一個引入的范型類型。
如何定義個一個協(xié)議,只能要求被某些特定類來實現(xiàn)呢??
//Perfect
定義一個空協(xié)議,然后擴展這個協(xié)議,在擴展中指定這個協(xié)議,只能由某些特定類型來繼承
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()
}
//這個類不繼承那個協(xié)議,交給它所屬的實例類來實現(xiàn)協(xié)議
class ClassA17:ProtocolA18 {
//協(xié)議類型
weakvar protocolObj:ProtocolA18?
//method2, method3都不需要實現(xiàn)。
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, "是學(xué)生")
}
}
//switch case
arr.forEach { (a) in
switch a {
//這where只能加一個條件啊
case let x where x.hasPrefix("胡"):
print(a ,"是老師")
default:
print(a, "是學(xué)生")
}
}
//for in
for i in arr where i.hasPrefix("胡") {
print(i ,"是老師")
}
//用在協(xié)議擴展里:擴展協(xié)議中,對擴展的協(xié)議增加限定:關(guān)聯(lián)類型繼承某個協(xié)議
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("擴展協(xié)議,提供了方法的默認實現(xiàn),但是這個方法,并沒有在協(xié)議中定義")
}
}
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("我們自己來實現(xiàn)這個協(xié)議,那么擴展協(xié)議中的默認實現(xiàn)的方法還會被調(diào)用嗎")
}
}
29、使用枚舉而不是class或者struct來定義一個鏈表
不加indirect,編譯報錯!
嵌套定義枚舉的時候,必須加上indirect關(guān)鍵字
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)
//需要一個嵌套函數(shù)
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種表現(xiàn)形式Selector and#selector
selector是一個關(guān)鍵字,返回一個類型
-(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)
}
}
執(zhí)行一個selector
Selector("method")警告:不要顯示調(diào)用,需要改為#selector關(guān)鍵字
#selector(method(parm1:param2:))
#selector(method(param1:))
#selector(method2)
如果同名子的方法只有一個,沒有參數(shù)、標簽不同的同名函數(shù),則可以省略參數(shù)列表
func method2(a:String,b:String){}
func method(param1:String,param2:String){}
func method(param1:String){}
#selector(method2)//這種調(diào)用也是可以的。因為他的方法沒有同名
但是可以將方法進行強制轉(zhuǎn)換
#selector(method as (string,string)->())
#selector(method as (string)->())
31,實例方法的動態(tài)調(diào)用
實例方法
實例屬性不可以
class ClassA10{
func printHello(){
logFlag("hello")
}
}
//字面量取值
f = ClassA10.pringHello
{
//參數(shù)ClassA10
(obj:ClassA10) in
//返回值:是一個函數(shù)
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)->()-()
//動態(tài)調(diào)用
let f1 = ClassA10.printHello
f1(ClassA10())()
//ClassA10.printHello的字面量表達
let a = {
(obj:ClassA10) -> ()->() in
return obj.printHello
}
a(ClassA10())()
32,單例
實例屬性:存儲型常量,存儲型變量,計算型變量
類屬性:存儲型常量,存儲型變量,計算型變量
由于swift1.2之前版本的屬性特性,類屬性不能有存儲型變量、存儲型常量。所以單例的實現(xiàn)方式就要借助于全局變量,
然后在計算型變量中,返回這個全局變量。
那么1.2開始以后,就會有更簡單的單例實現(xiàn)版本了。
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、
動態(tài)派發(fā)
@objc修飾
@dynamic
oc中的協(xié)議里存在關(guān)鍵字:
@optional
//swift不支持可選協(xié)議
protocol OptionalProtocol{
optional func optionalMethod()
}
//支持可選協(xié)議,
@objc protocol OptionalProtocol {
@objc optional func optionalMethod()
}
使用@objc修飾的協(xié)議,只能被class實現(xiàn),不能被struct,enum實現(xiàn)
37、內(nèi)存管理
引用計數(shù)
arc
當實例的引用為nil的時候,系統(tǒng)就會釋放內(nèi)存
什么時候?qū)嵗囊脼閚il?
1)超過作用域,2)手動設(shè)置為nil
產(chǎn)生循環(huán)引用的條件:
1)引用類型實例產(chǎn)生循環(huán)引用
2)閉包引起循環(huán)應(yīng)用,其實閉包也是一個引用類型。還是可以歸屬為1
一個class有一個閉包屬性。閉包屬性里面又使用了self,就產(chǎn)生循環(huán)
在方法內(nèi)部初始化的生成的對象在被返回后別人還能使用,而不是立即釋放掉
延遲釋放
func autoreleasepool(code:()->())
每次超過作用域后,自動內(nèi)存管理都會為我們處理好內(nèi)存相關(guān)的事情???
//每次獲得一個產(chǎn)生一個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結(jié)束時候進行drain操作。
drain的作用:
1)把池子里面的引用類型的實例,實例的引用為nil的時候,或者說引用計數(shù)為0的實例,進行釋放。
所以,即使一個實例沒有強引用了,或者引用計數(shù)為0了,只要釋放池沒有執(zhí)行drain操作,他就不會得到釋放
2)把引用計數(shù)-1
值類型
傳遞、賦值=》復(fù)制
引用類型
傳遞、賦值=》引用對象的一個指向
String,Dictionary,Array,值類型,少量數(shù)據(jù)用此。如果數(shù)據(jù)大,就用cocoa中的NSDictionary,NSArray
值類型:內(nèi)存是在棧上。
引用類型:堆上。
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并不會自動進行內(nèi)存管理,因此把某一個pointer = nil,并不能自動釋放內(nèi)存
deinitialize-》釋放指針指向的內(nèi)存的對象
deallocate -》釋放指針自己本身
指向函數(shù)的指針-》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調(diào)用?
嵌套函數(shù)好復(fù)雜!!!
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)利用作用域,釋放內(nèi)存
2、
swift 2.0以前
用尾隨閉包
func do(b:()-()){
b()
}
do{
。。。。。
}
3、
那么2.0以后呢?
就用do,加入了do關(guān)鍵字,捕獲異常的作用區(qū)域
do {
}
4、
使用匿名閉包----用閉包賦初始化值
let label:UILabel = {return UILabel()}()
42、
swift判等
NSObject子類:看是否重寫了父類isEqual方法,默認的是用父類的isEqual方法判等
Swift類型,不繼承NSObject的類:判等==,需要把類繼承Equatable協(xié)議,然后實現(xiàn)操作符==方法,否則編譯報錯
如果是Swift的原生類型,如String,Dictionary,系統(tǒng)自動實現(xiàn)了Equtable協(xié)議了,我們不需要自己去重寫啥的。
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的子類,默認調(diào)用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的子類,默認調(diào)用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的子類,優(yōu)先看有沒有實現(xiàn)Equatable協(xié)議方法==判等操作符:優(yōu)先調(diào)用了")
if lhs.name == rhs.name {
return true
}
return false
}
}
43、swift日志輸出
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協(xié)議的struct類型,以及一組靜態(tài)的get屬性。
想一想,why?
OptionSetType是實現(xiàn)了SetAlgebraType的
Algebra:代數(shù)學(xué)
set algebra:集合代數(shù)
用集合來代替邏輯運算符&、|位運算
//這里太復(fù)雜: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
//沒有要求在閉包中操作,我還想測試一下循環(huán)引用的
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是一個結(jié)構(gòu)體,范型結(jié)構(gòu)體,范型要求為符合協(xié)議--Sequece協(xié)議
并且自身也符合協(xié)議--Sequece協(xié)議
怎么就跟元組掛上鉤了呢???
難道又是模式匹配嗎,又或是字面量表達
字面量表達-》字面量表達協(xié)議-》協(xié)議規(guī)定了哪些方法??
switch,for,if,try..catch..,
1)判等
2)判可選類型是否為nil
3)判范圍
底層如何實現(xiàn)的呢?
其實就是系統(tǒng)實現(xiàn)了~=操作符。
[(1,2),(12,312),(1234,1234)]
確實是啊!!
public static func ~=(pattern:CountableClosedRange, value: Bound) -> Bool
Sequece協(xié)議規(guī)定了一個~=模式匹配的方法
EnumeratedSequence<[(Int,Int)]>
EnumeratedSequece<[Int]>
46、通過類型獲取對應(yīng)的編碼?這又是個什么鬼
OC中的用法:
@encode
Swift中的用法:
Metatype
不能獲取任意類型的類型編碼了。
但是在Cocoa中,即繼承自NSObject類型的類,可以通過NSValue的objcType來獲取對應(yīng)值的類型指針。
如果需要獲取Swift類型的類型編碼,可以將他轉(zhuǎn)換為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...
函數(shù)類型,閉包類型,協(xié)議類型。。。。
表達式、
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)協(xié)議前面加上@objc
2)協(xié)議后面加上class
applied:應(yīng)用
weak may only be applied to classand class-bound protocol types
protocol ProtocolA17 {
func method()
}
protocol ProtcolA18 where
//這個類不繼承那個協(xié)議,交給它所屬的實例類來實現(xiàn)協(xié)議
class ClassA17{
//協(xié)議類型,這是一個成員屬性,這個屬性必須要求實現(xiàn)協(xié)議
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協(xié)議:
值類型,引用類型都可以繼承某一個協(xié)議,struct,enum雖然可以用protocol,但是不存在引用計數(shù)這樣的內(nèi)存管理問題,所以就無需用到weak
@objc protocol ProtocolA17 {
func method()
}
protocol ProtocolA20:class{
func method()
}
//這個類不繼承那個協(xié)議,交給它所屬的實例類來實現(xiàn)協(xié)議
class ClassA17:ProtocolA18 {
//協(xié)議類型
weak var protocolObj:ProtocolA18?
//method2, method3都不需要實現(xiàn)。
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、關(guān)聯(lián)對象
public struct UnsafeRawPointer :Strideable, Hashable {
}
static var key:Void?
&key=>>UnsafeRawPointer這樣就可以轉(zhuǎn)了嗎?
//key這個參數(shù),為什么是要傳入一個可變的指針
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系列,內(nèi)存管理自動管理的。不需要release等
60、
swift命令
repl:swift repl環(huán)境read eval printloop
可以進行簡單的交互式編程,每輸入一句語句,就立即執(zhí)行到我們眼前
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
結(jié)論,
1)實現(xiàn)了custom和customdebug其中的任何一個,print,debugPring打印的都是一樣的結(jié)果
2)如果都實現(xiàn)了,pring調(diào)用custom,debugPrint調(diào)用customDebug
3)如果都沒有實現(xiàn),那就只能系統(tǒng)默認打一個ClassX.self的類型了
print是執(zhí)行CustomStringConvertible協(xié)議規(guī)定的方法
printDebug是執(zhí)行CustomDebugStringConvertible協(xié)議規(guī)定的方法
對于一個普通的對象,只能打印出它的類型。
struct可以打印出成員的名稱和值
如何實現(xiàn)一個CustomStringConvertible協(xié)議?
extension ClassA20:CustomStringConvertible{
var description: String {
return "helll"
}
}
extensionClassA20:CustomDebugStringConvertible {
var debugDescription: String {
return "world"
}
}
1)實現(xiàn)CustomStringConvertible,不實現(xiàn)CustomDebugStringConvertible:
helll
helll
2)不實現(xiàn)CustomStringConvertible,實現(xiàn)CustomDebugStringConvertible:
world
world
3)實現(xiàn)CustomStringConvertible,實現(xiàn)CustomDebugStringConvertible:
helll
world
4)不實現(xiàn)CustomStringConvertible,不實現(xiàn)CustomDebugStringConvertible:
Xcode8_swift3_ios8_10.ClassA20
Xcode8_swift3_ios8_10.ClassA20
print(ClassA20.self)
debugPrint(ClassA20.self)
輸出
ClassA20
Xcode8_swift3_ios8_10.ClassA20
62、斷言
斷言:它是一個開發(fā)時的特性,只有在debug編譯的時候有效。而在運行時是不能被編譯執(zhí)行的。
所以,在代碼發(fā)布的時候,我們不用刻意去將這些斷言手動清理掉。
這是默認的斷言特性
target, build settings swift
compiler-custom flags中
other swift flags中添加
-assert-config Debug來強制啟用斷言,
-assert-config Release來強制禁用斷言
貌似不管用啊!!!
在release中,如何強制終止程序呢,我們最好不要修改斷言的配置選項。
而是使用另外一個函數(shù)。
fatalError
調(diào)用這個方法,不需要返回值
func asd()->Int{
fatalError("asdf")
}
斷言只會在Debug環(huán)境中有效,而在Release編譯中所有的斷言都將被禁用。在遇到確實因為輸入的錯誤無法使程序繼續(xù)運行的時候,我們一般考慮以產(chǎn)生致命錯誤(fatalError)的方式來終止程序。
63、面向協(xié)議編程和模擬的抽象函數(shù)的方式
64、錯誤和異常
異常
1)為什么要用異常?
調(diào)用某些方法,我們開發(fā)時候很容易忽略的時候,就用異常,避免我們忽略nserror
同步調(diào)用中用異常
異步調(diào)用不用異常,用error
2)怎樣使用異常
do try catch
try?
try!
throws
實現(xiàn)一個繼承Error枚舉的枚舉類。拋出這個新的枚舉類型。
class func someMethodTrhows2 (b:Bool)throws-> Int? {
if b {
throw myError.value
}
return nil
}
//返回的是nil還能執(zhí)行if。因為是optional套一個optional
if let a = try?someMethodTrhows2(b: false){
print(a)
} else {
print("err")
}
rethrows :
在方法中加rethrows,表示這個方法的型參列表中,有一個參數(shù),也可能拋出異常,即是一個能拋出異常的閉包類型或者函數(shù)類型,
然后呢,這個方法本身自己不會拋出任何異常,除了型參的方法被調(diào)用拋出異常外。
如果這個方法,仍然用throws來修飾:表明,型參閉包被調(diào)用時,拋出異常;自己的處理過程中,也允許拋出異常。
凡是調(diào)用了拋出異常的方法,在調(diào)用它時,都必須加上try的形式來調(diào)用。
這表明啊:加rethrows的方法,只要它的參數(shù),我們給他傳遞進去的時候,雖然在型參中我們聲明了這個函數(shù)可能拋出異常,但是
我們在實參的定義中,如果作為實參的閉包,并沒有拋出異常,既沒有寫throw Error.XXX時,我們是可以不用try來調(diào)用的!!
既可以接受普通函數(shù),也可以接受一個普通函數(shù),雖然這個參數(shù)是throw的
//報錯
someMethodTrhows1(b: true)
//報錯
someMethodTrhows3(b:true) { (b) -> Int in
if b {throw myError.value}
}
//不報錯,可以這樣用
someMethodTrhows3(b: true) { (b) -> Intin
return 1
}
//必須要加try調(diào)用
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:告訴編譯器,我們不會再編譯時就確定這個屬性的行為實現(xiàn)
不需要在編譯期間對這個屬性的getter或setter做檢查和關(guān)心。
表示我們將在運行時來提供這個屬性的存取方法,如果在運行時,沒有對這個屬性提供存取方法,就會crash
CoreDataModel,
使用xcode工具,自動生成NSManagedObject子類
Swift,不保證一切都走動態(tài)派發(fā)。
CoreData專用:@NSManaged
68、KVO、KVC
動態(tài)派發(fā)
觀察的對象標記為dynamic
在oc中,KVC的屬性,進行監(jiān)聽。而現(xiàn)在,需要NSObject的,dynamic修飾的,可以監(jiān)聽
Observable-Swift
范型、閉包、屬性觀察器-》》》KVO