那些年,學swift踩過的坑__那些年

來源:互聯網
上載者:User
那些年,學swift踩過的坑

最近在學swift,本以為多是文法與oc不同,而且都是使用相同的cocoa架構,相同的API,但是或多或少還是有些坑在裡,為了避免以後再踩,在這裡記下了,以後發現新的坑,也會慢慢在這裡加上

[TOC] 1.main檔案去哪兒了。 OC中main.m中的代碼, 通過@UIApplicationMain標記自動產生 可以注掉AppDelegate裡的@UIApplicationMain,自己實現Main,不過一般沒人這樣做 實現下面代碼就是OC中的main檔案的函數

UIApplicationMain(Process.argc, Process.unsafeArgv, nil, NSStringFromClass(AppDelegate))
2.如何通過字串建立類對象。 在swift中列印對象時,會發現在類型前面總會有命名空間 .+類名 在swift中用字串產生類對象就需要拼接成這樣的格式,才能成功產生類 注意,命名空間不要加特殊符號,不然依然無法擷取控制器類
//擷取命名空間,在info.plist檔案裡就是Executable filelet nameSpace = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as! String//拼接成固定格式let controller:AnyClass = NSClassFromString(nameSpace + "." + controllerName)!//建立對象let viewController = (controller as! UIViewController.Type).init()
3.Swift中的Any,AnyObject,AnyClass分別代表是什麼。 AnyObject: 相當於OC中的id, 表示所有class類型的資料, 所有繼承與NSObject的類都隱式實現了protocol AnyObject協議, 所以他可以表示所有的class類型

Any:所有基礎資料型別 (Elementary Data Type)和enum/ struct都可以用Any來表示

注意: 有的時候你會發現將基礎資料型別 (Elementary Data Type)或者enum/ struct通過AnyObject來儲存也不會報錯, 這是因為Swift中很多資料類型可以和OC中的資料類型進行自動轉換, 系統內部已經將他們轉換為了OC的物件類型

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

  typealias AnyClass = AnyObject.Type  .Type用於擷取類的元類型, 例如Person.Type就代表著擷取Person的元類型  .self如果通過類名調用, 那麼可以擷取該類的類型, 說白了就是擷取自己
4.在Swife中如何抓取異常。 在Swift中抓取異常需要do,catch,try這三個關鍵字 這裡舉個json序列化的例子
do{            let path = /..路徑../            let data =/..轉data../             //編譯器會要求你實行異常檢測,於是在序列化前面添加try欄位            //外部包裹do,catch,顯而易見出錯自然會走catch                       let dicArr = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)        }catch        {            // 如果拋出異常就會來到catch        }
5.在swift中如何定義全域列印方法 由於swift沒有宏,我們不能像oc那樣去定義 直接在AppDelegate中寫,反正哪裡都可以用 用泛型傳參 如何判斷調試與發布狀態呢。 在Build settings裡找到Swift Compiler-custom Flags 在other swift flags 的Debug裡添加兩個欄位 "-D" "DEBUG" 代碼中直接判斷就行
func HJSLog<T>(message: T){    #if DEBUG        print("\(message)")    #endif}
6.在swift中,單例怎麼寫。 在swift中,單例有兩種寫法 一種是按照OC的思維去寫
     static var onceToken: dispatch_once_t = 0    static var instance: NetworkTools?    class func shareNetworkTools() -> NetworkTools    {        dispatch_once(&onceToken) { () -> Void in            print("我被調用了")            instance = NetworkTools()        }        return instance!    }
另一種就是swift的純正寫法 在swift中,let本身就只會建立一次,可以運用這個特性 let是安全執行緒的
static let instance: NetworkTools = NetworkTools()    class func shareNetworkTools() -> NetworkTools    {        return instance    }
7.在swift中如何私人化點擊事件方法 一般我們不公開方法會在前面添加private 但是例如按鈕點擊方法,光是添加private是不夠的 因為swift的方法調用是在編譯時間就決定了 而點擊事件方法由於是來自於runloop中 編譯器不會它一起編譯進來,只有在運行時呼叫,這屬於OC的調用方式 所以我們還需要再在方法前面加上@objc
//按鈕點擊handle    @objc private func composeClick(){    }`
8.在swift中如何懶載入 在swift中對懶載入有專門的關鍵字
///懶載入一個imageViewprivate lazy var icon:UIImageView = {        let imageV = UIImageView(image: UIImage(named: "visitordiscover_feed_image_smallicon"))        return imageV    }()
9.在swift中的協議(protocol) 在swift中定義協議也很簡單 只需要在類前定義就行
@objcprotocol VisitorViewDelegate:NSObjectProtocol{  //點擊註冊按鈕  optional func visitorViewDidRegisterBtnClick(visitView: VisitorView)  //點擊登入按鈕  optional func visitorViewDidLoginBtnClick(visitView:VisitorView)}
代理屬性需要設定為weak,防止循環參考
weak var delegate:VisitorViewDelegate?
在調用代理方法時,代理作為可選屬性,已經幫我們預防代理不存在的可能 我們還需要藉助可選屬性來預防方法未實現 當然在確定實現的前提下可以解包
///註冊handle  @objc private func registerClick(){delegate?.visitorViewDidRegisterBtnClick!(self)  }  ///登入handle  @objc private func loginClick(){ delegate?.visitorViewDidLoginBtnClick?(self)  }
10.在swift中如何寫分類 我剛從oc轉過來就遇到了如何在swift中寫分類的問題 swift中寫分類很簡單 extension就是swift中的分類 例如給UIBarbuttonItem添加分類 建立一個UIBarButtonItem+Extension.swift檔案
import UIKitextension UIBarButtonItem{    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 來在父類中強制拋出錯誤,以保證使用這些代碼的開發人員留意到他們必須在自己的子類中實現相關方法:
class MyClass {      func methodMustBeImplementedInSubclass() {        fatalError("這個方法必須在子類中被重寫")    }}class YourClass: MyClass {      override func methodMustBeImplementedInSubclass() {        print("YourClass 實現了該方法")    }}class TheirClass: MyClass {      func someOtherMethod() {    }}YourClass().methodMustBeImplementedInSubclass()  // YourClass 實現了該方法TheirClass().methodMustBeImplementedInSubclass()  // 這個方法必須在子類中被重寫
不僅僅是對於類似抽象函數的使用中可以選擇 fatalError,對於其他一切我們不希望別人隨意調用,但是又不得不去實現的方法,我們都應該使用 fatalError 來避免任何可能的誤會。比如父類標明了某個 init 方法是 required 的,但是你的子類永遠不會使用這個方法來初始化時,就可以採用類似的方式, 被廣泛使用 (以及被廣泛討厭的) init(coder: NSCoder) 就是一個例子。在子類中,我們往往會寫
required init(coder: NSCoder) {    fatalError("NSCoding not supported")}
12.在swift中使用guard與fatalError配合拋出異常 在嚴謹的開發中會經常用到斷言 前面一條介紹了fatalError來拋出錯誤 這條就來介紹一下guard與fatalError的配合使用達到斷言的效果
guard let safeValue = criticalValue else {  fatalError("criticalValue cannot be nil here")}someNecessaryOperation(safeValue)
本來我認為if也可以達到這樣的效果
if let safeValue = criticalValue {  someNecessaryOperation(safeValue)} else {  fatalError("criticalValue cannot be nil here")}
或者
if criticalValue == nil {  fatalError("criticalValue cannot be nil here")}someNecessaryOperation(criticalValue!)

但是看到有些部落格這麼說:

這個flatten c

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.