1幌墓、as、as?、as!三種區(qū)別
as
- 從派生類(lèi)轉(zhuǎn)換為基類(lèi)秕铛,向上轉(zhuǎn)型(upcasts)
- 數(shù)值類(lèi)型(CGFloat, Int, Double)轉(zhuǎn)換
- switch 語(yǔ)句中進(jìn)行模式匹配
switch person1 {
case let person1 as Student:
print("是Student類(lèi)型,打印學(xué)生成績(jī)單...")
case let person1 as Teacher:
print("是Teacher類(lèi)型缩挑,打印老師工資單...")
default: break
}
as!
向下轉(zhuǎn)型(Downcasting, 基類(lèi)轉(zhuǎn)換為派生類(lèi))時(shí)使用但两。由于是強(qiáng)制類(lèi)型轉(zhuǎn)換,如果轉(zhuǎn)換失敗會(huì)報(bào) runtime 運(yùn)行錯(cuò)誤供置。
as?
as? 和 as! 操作符的轉(zhuǎn)換規(guī)則完全一樣谨湘。但 as? 如果轉(zhuǎn)換不成功的時(shí)候便會(huì)返回一個(gè) nil 對(duì)象。成功的話返回可選類(lèi)型值芥丧。由于 as? 在轉(zhuǎn)換失敗的時(shí)候也不會(huì)出現(xiàn)錯(cuò)誤紧阔,所以對(duì)于如果能確保100%會(huì)成功的轉(zhuǎn)換則可使用 as!,否則使用 as?
2续担、便利構(gòu)造函數(shù)
示例:
convenience init(imageName: String, bgImageName: String){
self.init()
setImage(UIImage(named:imageName), for: .normal)
}
使用convenience修飾的構(gòu)造函數(shù)叫做便利構(gòu)造函數(shù)
便利構(gòu)造函數(shù)通常用在對(duì)系統(tǒng)的類(lèi)進(jìn)行構(gòu)造函數(shù)的擴(kuò)充時(shí)使用擅耽。
- 便利構(gòu)造函數(shù)通常都是寫(xiě)在extension里面(也可用在類(lèi)中)
- 便利函數(shù)init前面需要加載convenience
- 在便利構(gòu)造函數(shù)中需要明確的調(diào)用self.init()
3、private(set)
private(set)將set方法的訪問(wèn)級(jí)別降低物遇,低于get訪問(wèn)級(jí)別乖仇,set方法只有在該模塊中調(diào)用憾儒,對(duì)外是只讀的。
示例:
public private(set) lazy var name: String = {
return "hello";
}()
4乃沙、Swift和OC混編
- 在OC項(xiàng)目中創(chuàng)建一個(gè)swift文件的時(shí)候起趾,Xcode 會(huì)提示 需要?jiǎng)?chuàng)建一個(gè)橋接文件,其名字為:工程名-Bridging-Header.h
- 進(jìn)入TARGETS ->Build Settings -> Packaging 中設(shè)置Defines Module為YES警儒。
- Objective-C Bridging Header中設(shè)置橋接文件训裆,路徑為:工程名/工程名-Bridging-Header.h
- OC調(diào)用Swift時(shí),在OC文件中導(dǎo)入 #import “工程名-Swift.h”冷蚂,就可以調(diào)用Swift的代碼了缭保。
- Swift調(diào)用OC時(shí),需要將要調(diào)用的OC頭文件導(dǎo)入到橋接文件中蝙茶,就能調(diào)用了艺骂。
注意:最好每一步操作前comman+B編譯一下,看是否報(bào)錯(cuò)隆夯。
5钳恕、NS_ASSUME_NONNULL_BEGIN & NS_ASSUME_NONNULL_END
Swift中的對(duì)象使用 ? 和 ! 可以分為可選和不可選,OC里面沒(méi)有這個(gè)區(qū)分蹄衷,導(dǎo)致OC和Swift混編的時(shí)候忧额,Swift不知道一個(gè)Objective-C對(duì)象到底是optional還是non-optional,因此這種情況下編譯器會(huì)隱式地將Objective-C的對(duì)象當(dāng)成是non-optional愧口。
為了解決這個(gè)問(wèn)題睦番,蘋(píng)果在Xcode 6.3引入了一個(gè)Objective-C的新特性:nullability annotations。這一新特性的核心是兩個(gè)新的類(lèi)型注釋: __nullable 和 __nonnull耍属,如果需要每個(gè)屬性或每個(gè)方法都去指定nonnull和nullable托嚣,是一件非常繁瑣的事。蘋(píng)果為了減輕我們的工作量厚骗,專門(mén)提供了兩個(gè)宏:NS_ASSUME_NONNULL_BEGIN示启, NS_ASSUME_NONNULL_END。在這兩個(gè)宏之間的代碼领舰,所有簡(jiǎn)單指針對(duì)象都被假定為nonnull夫嗓,因此我們只需要去指定那些nullable的指針。
NS_ASSUME_NONNULL_BEGIN
@interface TestObject : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic) BOOL isOpen;
- (void)setDataAccessDate:(NSDate*)date forRequestWithIdentifier:(NSString* _Nullable)identifier;
@end
NS_ASSUME_NONNULL_END
6冲秽、Switch語(yǔ)句
Swift中Switch語(yǔ)句不需要在每個(gè)case后面加break舍咖,會(huì)自動(dòng)跳出不執(zhí)行后面的case,如果想按順序執(zhí)行下面的case锉桑,可以加上fallthrough語(yǔ)句谎仲。
7、可失敗構(gòu)造器
如果一個(gè)類(lèi)刨仑,結(jié)構(gòu)體或枚舉類(lèi)型的對(duì)象郑诺,在構(gòu)造自身的過(guò)程中有可能失敗,則為其定義一個(gè)可失敗構(gòu)造器杉武。使用 init? 的方法辙诞,當(dāng)返回nil的時(shí)候表示構(gòu)造失敗。
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil }
self.species = species
}
}
8轻抱、try try? try! 的區(qū)別
發(fā)生異常的時(shí)候的三種處理方式:
- try:發(fā)生異常處理異常
do {
var str = try testFunc(str: "three")
} catch {
print(“error”)
}
- try?: 如果不想處理異常那么可以用這個(gè)關(guān)鍵字,使用這個(gè)關(guān)鍵字返回一個(gè)可選值類(lèi)型,如果有異常出現(xiàn),返回nil.如果沒(méi)有異常,則返回可選值
var str = try? testFunc(str: "three")
- try!:如果不想處理異常,而且不想讓異常繼續(xù)傳播下去,可以使用try!.這有點(diǎn)兒類(lèi)似NSAssert().但是一旦使用try!后,在可能拋出異常的方法中拋出了異常,那么程序會(huì)立刻停止.不推薦使用飞涂。
var str = try! testFunc(str: "three")
9、逃逸閉包和非逃逸閉包
閉包只有在函數(shù)中做參數(shù)時(shí)才會(huì)區(qū)分逃逸閉包和非逃逸閉包祈搜。
Swift 3.0之后较店,傳遞閉包到函數(shù)中的時(shí)候,系統(tǒng)會(huì)默認(rèn)為非逃逸閉包類(lèi)型@noescaping容燕,逃逸閉包在閉包前要添加@escaping關(guān)鍵字梁呈。
兩者生命周期的區(qū)別:
非逃逸閉包的生命周期與函數(shù)相同:
- 把閉包作為參數(shù)傳給函數(shù);
- 函數(shù)中調(diào)用閉包蘸秘;
- 退出函數(shù)官卡。結(jié)束
逃逸閉包的生命周期:
- 閉包作為參數(shù)傳遞給函數(shù);
- 退出函數(shù)醋虏;
- 閉包被調(diào)用寻咒,閉包生命周期結(jié)束
即逃逸閉包的生命周期長(zhǎng)于函數(shù),函數(shù)退出的時(shí)候颈嚼,逃逸閉包的引用仍被其他對(duì)象持有毛秘,不會(huì)在函數(shù)結(jié)束時(shí)釋放
逃逸閉包示例:
//ClassDetailsDAO.swift
func enrollToClass(classUUID: String, spot: String?, completion: @escaping (Result<ClassData>) -> Void) {
guard let calendarEntry = model.calendarEntry(withUUID: classUUID, createNew: false) else {
completion(.failure(ClassDetailsDAOError.entryNotFound))
return
}
}
逃逸閉包一般使用的場(chǎng)景:網(wǎng)絡(luò)請(qǐng)求請(qǐng)求結(jié)束后才調(diào)用的閉包,因?yàn)榘l(fā)起請(qǐng)求后過(guò)了一段時(shí)間后這個(gè)閉包才執(zhí)行阻课,并不一定是在函數(shù)作用域內(nèi)執(zhí)行叫挟。
循環(huán)引用
非逃逸閉包不會(huì)產(chǎn)生循環(huán)引用,它會(huì)在函數(shù)作用域內(nèi)釋放柑肴,編譯器可以保證在函數(shù)結(jié)束時(shí)閉包會(huì)釋放它捕獲的所有對(duì)象霞揉。
逃逸閉包會(huì)產(chǎn)生循環(huán)引用的問(wèn)題,為了解決循環(huán)引用問(wèn)題晰骑,使用[weak self]
classDetailsDAO.enrollToClass(classUUID: classUUID, spot: spot) { [weak self] (result) in
guard let strongSelf = self else {
return
}
switch result {
case .success(let classData):
strongSelf.presenter.didEnrollToClass(classData: classData)
case .failure(let error):
strongSelf.presenter.didFailToEnrollToClass(error: error)
}
}
10适秩、Any和AnyObject
- 有點(diǎn)類(lèi)似OC中的id,Swift為不確定的類(lèi)型硕舆,提供了兩種特殊別名秽荞,any和anyobject,
- AnyObject可以表示class類(lèi)型的實(shí)例抚官。
- Any可以表示任何類(lèi)型的實(shí)例扬跋。
11、String(describing:)
獲取類(lèi)名稱的字符串
class Foo {
// 實(shí)例屬性中指定明確的類(lèi)名來(lái)獲取名稱
var typeName: String {
return String(describing: Foo.self)
}
// 實(shí)例屬性中動(dòng)態(tài)獲取類(lèi)名來(lái)獲取名稱
var otherTypeName: String {
let thisType = type(of: self)
return String(describing: thisType)
}
// 類(lèi)屬性中直接獲取名稱
static var typeName: String {
return String(describing: self)
}
}
Foo().typeName // = "Foo"
Foo().otherTypeName // = "Foo"
Foo.typeName // = "Foo"
12凌节、defer的使用
Swift2.0中加入了defer新語(yǔ)法聲明钦听,defer譯為延緩洒试、推遲之意。
使用場(chǎng)景:
比如朴上,讀取某目錄下的文件內(nèi)容并處理數(shù)據(jù)垒棋,你需要首先定位到文件目錄,打開(kāi)文件夾痪宰,讀取文件內(nèi)容以及處理數(shù)據(jù)叼架,在讀取文件內(nèi)容失敗、處理數(shù)據(jù)失敗的情況下要關(guān)閉文件的操作衣撬,在讀取成功的情況下最后也要關(guān)閉文件的操作乖订,這個(gè)時(shí)候可以把關(guān)閉文件的代碼放到defer中來(lái)延遲執(zhí)行。
所以具练,defer{}中的代碼會(huì)在作用域結(jié)束之前或者說(shuō)return之前最后調(diào)用
例子:
func fridgeContains(_ food: String) -> Bool {
fridgeIsOpen = true
defer {
//最后調(diào)用
fridgeIsOpen = false
}
let result = fridgeContent.contains(food)
return result
}
13乍构、@discardableResult的作用
@discardableResult func doSomething() -> Bool {
return true
}
例如上面的方法,如果使用 doSomething() 調(diào)用該函數(shù)靠粪,但是沒(méi)有用變量來(lái)接收函數(shù)的返回參數(shù)時(shí)蜡吧,就會(huì)報(bào)警告,這時(shí)候@discardableResult來(lái)消除警告占键。