那些年,學swift踩過的坑

最近在學Swift,本以為多是語法與oc不同,而且都是使用相同的cocoa框架,相同的API,但是或多或少還是有些坑在里,為了避免以后再踩,在這里記下了,以后發(fā)現新的坑,也會慢慢在這里加上

[TOC]

1.main文件去哪兒了?

OC中main.m中的代碼, 通過@UIApplicationMain標記自動生成

可以注掉AppDelegate里的@UIApplicationMain,自己實現Main,不過一般沒人這樣做

實現下面代碼就是OC中的main文件的函數

UIApplicationMain(Process.argc, Process.unsafeArgv,nil, NSStringFromClass(AppDelegate))

2.如何通過字符串創(chuàng)建類對象?

在swift中打印對象時,會發(fā)現在類型前面總會有命名空間

.+類名

在swift中用字符串生成類對象就需要拼接成這樣的格式,才能成功生成類

注意,命名空間不要加特殊符號,不然依然無法獲取控制器類

//獲取命名空間,在info.plist文件里就是Executable fileletnameSpace = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"]as!String//拼接成固定格式letcontroller:AnyClass = NSClassFromString(nameSpace +"."+ controllerName)!//創(chuàng)建對象letviewController = (controlleras! UIViewController.Type).init()

3.Swift中的Any,AnyObject,AnyClass分別代表是什么?

AnyObject: 相當于OC中的id, 表示所有class類型的數據, 所有繼承與NSObject的類都隱式實現了protocol AnyObject協議, 所以他可以表示所有的class類型

Any:所有基本數據類型和enum/ struct都可以用Any來表示

注意: 有的時候你會發(fā)現將基本數據類型或者enum/ struct通過AnyObject來保存也不會報錯, 這是因為Swift中很多數據類型可以和OC中的數據類型進行自動轉換, 系統內部已經將他們轉換為了OC的對象類型

AnyClass: 用來表示任意類的類類型(元類型)

typealiasAnyClass=AnyObject.Type.Type用于獲取類的元類型, 例如Person.Type就代表著獲取Person的元類型? .self如果通過類名調用, 那么可以獲取該類的類型, 說白了就是獲取自己

4.在Swife中如何抓取異常?

在Swift中抓取異常需要do,catch,try這三個關鍵字

這里舉個json序列化的例子

do{letpath =/..路徑../letdata =/..轉data..///編譯器會要求你實行異常檢測,于是在序列化前面添加try字段//外部包裹do,catch,顯而易見出錯自然會走catchletdicArr =tryNSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)? ? ? ? }catch{// 如果拋出異常就會來到catch}

5.在swift中如何定義全局打印方法

由于swift沒有宏,我們不能像oc那樣去定義

直接在AppDelegate中寫,反正哪里都可以用

用泛型傳參

如何判斷調試與發(fā)布狀態(tài)呢?

在Build settings里找到Swift Compiler-custom Flags

在other swift flags 的Debug里添加兩個字段

"-D"

"DEBUG"

代碼中直接判斷就行

funcHJSLog(message: T){? ? #ifDEBUGprint("\(message)")? ? #endif}

6.在swift中,單例怎么寫?

在swift中,單例有兩種寫法

一種是按照OC的思維去寫

static var onceToken: dispatch_once_t =0staticvarinstance: NetworkTools?classfunc shareNetworkTools() -> NetworkTools? ? {? ? ? ? dispatch_once(&onceToken) { () ->Voidinprint("我被調用了")instance= NetworkTools()? ? ? ? }returninstance!? ? }

另一種就是swift的純正寫法

在swift中,let本身就只會創(chuàng)建一次,可以運用這個特性

let是線程安全的

staticletinstance:NetworkTools=NetworkTools()classfuncshareNetworkTools() ->NetworkTools{returninstance? ? }

7.在swift中如何私有化點擊事件方法

一般我們不公開方法會在前面添加private

但是例如按鈕點擊方法,光是添加private是不夠的

因為swift的方法調用是在編譯時就決定了

而點擊事件方法由于是來自于runloop中

編譯器不會它一起編譯進來,只有在運行時呼叫,這屬于OC的調用方式

所以我們還需要再在方法前面加上@objc

//按鈕點擊handle@objcprivatefunccomposeClick(){? ? }`

8.在swift中如何懶加載

在swift中對懶加載有專門的關鍵字

///懶加載一個imageViewprivate lazy var icon:UIImageView= {? ? ? ? let imageV =UIImageView(image:UIImage(named:"visitordiscover_feed_image_smallicon"))returnimageV? ? }()

9.在swift中的協議(protocol)

在swift中定義協議也很簡單

只需要在類前定義就行

@objcprotocolVisitorViewDelegate:NSObjectProtocol{//點擊注冊按鈕optionalfuncvisitorViewDidRegisterBtnClick(visitView: VisitorView)//點擊登錄按鈕optionalfuncvisitorViewDidLoginBtnClick(visitView:VisitorView)}

代理屬性需要設定為weak,防止循環(huán)引用

weakvardelegate:VisitorViewDelegate?

在調用代理方法時,代理作為可選屬性,已經幫我們預防代理不存在的可能

我們還需要借助可選屬性來預防方法未實現

當然在確定實現的前提下可以解包

///注冊handle@objcprivatefuncregisterClick(){delegate?.visitorViewDidRegisterBtnClick!(self)? }///登錄handle@objcprivatefuncloginClick(){ delegate?.visitorViewDidLoginBtnClick?(self)? }

10.在swift中如何寫分類

我剛從oc轉過來就遇到了如何在swift中寫分類的問題

swift中寫分類很簡單

extension就是swift中的分類

例如給UIBarbuttonItem添加分類

新建一個UIBarButtonItem+Extension.swift文件

importUIKitextensionUIBarButtonItem{? ? convenience init(target:AnyObject?,action:Selector,image:String) {? ? ? ? let btn =UIButton(type:UIButtonType.Custom)? ? ? ? btn.setImage(UIImage(named: image), forState:UIControlState.Normal)? ? ? ? btn.setImage(UIImage(named: image +"_highlighted"), forState:UIControlState.Highlighted)? ? ? ? btn.addTarget(target, action: action, forControlEvents:UIControlEvents.TouchUpInside)self.init(customView:btn)? ? }}

11.為何經常被強制實現init(coder: NSCoder)

因為Objective-C 和 Swift 中都沒有直接的這樣的抽象函數語法支持

然而有些時候我們卻有不想讓別人調用某個方法,但又不得不將其暴露出來的時候。

一般滿足這種需求的就是抽象類型或者抽象函數

在面對這種情況時,為了確保子類實現這些方法,而父類中的方法不被錯誤地調用,我們就可以利用 fatalError 來在父類中強制拋出錯誤,以保證使用這些代碼的開發(fā)者留意到他們必須在自己的子類中實現相關方法:

classMyClass{funcmethodMustBeImplementedInSubclass(){? ? ? ? fatalError("這個方法必須在子類中被重寫")? ? }}classYourClass:MyClass{overridefuncmethodMustBeImplementedInSubclass(){print("YourClass 實現了該方法")? ? }}classTheirClass:MyClass{funcsomeOtherMethod(){? ? }}YourClass().methodMustBeImplementedInSubclass()// YourClass 實現了該方法TheirClass().methodMustBeImplementedInSubclass()// 這個方法必須在子類中被重寫

不僅僅是對于類似抽象函數的使用中可以選擇 fatalError,對于其他一切我們不希望別人隨意調用,但是又不得不去實現的方法,我們都應該使用 fatalError 來避免任何可能的誤會。比如父類標明了某個 init 方法是 required 的,但是你的子類永遠不會使用這個方法來初始化時,就可以采用類似的方式, 被廣泛使用 (以及被廣泛討厭的) init(coder: NSCoder) 就是一個例子。在子類中,我們往往會寫

requiredinit(coder:NSCoder) {fatalError("NSCoding not supported")}

12.在swift中使用guard與fatalError配合拋出異常

在嚴謹的開發(fā)中會經常用到斷言

前面一條介紹了fatalError來拋出錯誤

這條就來介紹一下guard與fatalError的配合使用達到斷言的效果

guardletsafeValue = criticalValueelse{? fatalError("criticalValue cannot be nil here")}someNecessaryOperation(safeValue)

本來我認為if也可以達到這樣的效果

ifletsafeValue = criticalValue {? someNecessaryOperation(safeValue)}else{? fatalError("criticalValue cannot be nil here")}

或者

ifcriticalValue ==nil{? fatalError("criticalValue cannot be nil here")}someNecessaryOperation(criticalValue!)

但是看到有些博客這么說:

這個flatten code以其他方式進入一個if let 代碼塊,并且在靠近相關的環(huán)境中過早地退出了,而不是進入else代碼塊。甚 至當你沒有捕獲一個值(guard let),這個模式在編譯期間也會強制過早退出。在第二個if的例子里,盡管代碼flattend得像guard一樣,但是一個毀滅性的錯誤或者其他返回 一些無法退出的進程(或者基于確切實例的非法態(tài))將會導致crash。一個過早的退出發(fā)生時,guard聲明將會及時發(fā)現錯誤,并將其從else block中移除。(這博主翻譯得真爛)

所以,還是用guard比較好

13.在swift中,互斥鎖變成什么樣了?

在swift中,互斥鎖如何寫

oc中的互斥鎖:

@synchronized(self) {//需要執(zhí)行的代碼塊}

swift中的互斥鎖

objc_sync_enter(self)//需要執(zhí)行的代碼塊objc_sync_exit(self)

至于其他多線程的API和以前的一樣,只是少了perform這一類的API,蘋果已經去掉了

14.在swift中,引用self時,如何避免循環(huán)引用

在oc中,我們需要在代碼塊用到self時,可以直接把self付給其他變量,然后在塊中使用完畢后制空,或者像下面弱引用self來避免循環(huán)引用:

__weaktypeof(self) weakSelf =self;

那么在swift中我們怎么辦到這點呢?

很簡單,看下面代碼

//這里用gcd舉例不好,畢竟系統的塊不會造成循環(huán)引用,這里就勉強的學一下怎么改吧dispatch_async(dispatch_get_global_queue(0,0)) {[unownedself] () -> Voidinself.view//添加自己的代碼}

只需要在閉包里加入[unowned self]即可

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容