1. 程式人生 > >swift--Swift 3.0實戰:遷移程式到 Swift 3.0

swift--Swift 3.0實戰:遷移程式到 Swift 3.0

每當看到新的程式語言我總是會有相當大的興趣,是的,Swift 3是一門『新語言』,因為它看起來,怎麼都不像過往的 Swift。開啟一個老的專案時,發現滿目瘡痍,基本上能標紅的程式碼全被標紅了。先來個截圖提提神:


圖一 程式碼標紅

怎麼樣,清醒點了沒?可能你會覺得奇怪,怎麼連 whiteColor() 這種通用的東西都不能用了?其實這是本次 Swift(和 SDK)大改的一個重要目標,就是『去重』。新的 SDK 去除了大量可有可無的東西,並且把庫做深度的修整,現在的 SDK 看起來更好用了(當然你也可以吐槽又要記大量新的東西了,不過 Swift 哪次新版釋出時你不改程式了,對吧)。下面我一一來講述。

一、去重

Swift 3 對於重複輸入的表示式深惡痛絕,如上圖所示的 whiteColor(),現在一律被改為了 white()。我們可以推斷出其他類似的改動(或者讓 IDE 幫助我們),如:

UIColor.whiteColor() 
被改為
UIColor.white()
list.objectAtIndex(i)
被改為
list.object(at: i)

同樣的,方法也被如此修改了,如:

presentViewController(controller, animated: true)
被改為
present(toViewController: controller, animated: true
)
dequeueReusableCellWithIdentifier("Cell", forIndexPath:indexPath)
被改為
dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
func numberOfSectionsInTableView(tableView: UITableView) -> Int
被改為
func numberOfSections(in tableView: UITableView) -> Int

一個很不幸而且幾乎會讓人崩潰的訊息是,這樣的改動幾乎發生在每一處函式呼叫,這使用開發人員不得不重新審視幾乎所有的程式碼,因為老的程式碼可能都在新的 SDK 下變得毫無建樹。

二、引數

Swift 3 對引數的傳入做了大幅改動,主要是添加了引數名稱的限定,在 Swift 3 下,一個方法所接受的引數必須擁有『名稱』,而讓全部引數都擁有名稱這件事,改動實在太大了,因此 Swift 又想出了一招可以讓你不寫名稱,使用單個下劃線作為允許匿名符號。參考以下例項:

override func viewWillAppear(animated: Bool)
被改為
override func viewWillAppear(_ animated: Bool)

下面再看一個例項的呼叫例子,加深印象:

func myFunc(x: Int, y: Int)
這個函式在呼叫時必須使用以下程式碼
myFunc(x: 1, y: 2)

若是允許匿名引數,則修改之:

func myFunc(_ x: Int, _ y: Int)
這個函式在呼叫時允許不帶引數名稱
myFunc(1, 2)

這樣的改動較大程度的影響了原有繼承下來的方法,如viewWillAppear,UITableView 的回撥函式等。對於自己寫的方法,稍加註意即可,這兩種方法都有著各自適用的場景。

三、命名

在早期的 Objective-C 或 Swift 中,系統內的常量、函式等的命名一直是一件讓人頭疼的事,例如UIControlContentHorizontalAlignmentCenter這種,簡直又臭又長,超級難記,雖說有 Xcode 這種強大的 IDE,也難免會弄錯。在 Swift 3 內,所有的相關常量都被劃到指定的列舉類中,而常量和函式均遵守相當良好的程式碼規範。來看幾個例項:

lbl.textAlignment = NSTextAlignment.Center
被改為
lbl.textAlignment = NSTextAlignment.center
tableFooterView = UIView(frame: CGRectZero)
被改為
tableFooterView = UIView(frame: CGRect.zero)

另外,現在的新的命名方式也更注重突出實際作用,再給個例子體會下:

lbl.hidden = false
被改為
lbl.isHidden = false

與此同時,所有NS類的類名也變得簡潔了,不再需要NS字首,再配合其他的改動(如去重),對程式碼的精簡形成了相當大的影響:

let bundle = NSBundle.mainBundle()
被改為
let bundle = Bundle.main()
let mgr = NSFileManager.defaultManager()
被改為
let mgr = FileManager.default()

再次告知一個不幸的訊息,這樣的改動幾乎也牽動了全部的程式碼!!講到這裡可能有一部分人已經哭了,居然要改那麼多程式碼,還能不能好好玩耍了? 別擔心,下面還有一半。

四、方法的返回值處理

我們在開發中可能會經常呼叫一些帶有返回值的方法,但是卻不處理返回值,例如以下這種:

navigationController!.popViewControllerAnimated(true)

這個方法實際上返回一個 UIViewController,但是很少有人會用,更多的場景是把它當成無返回的方法來使用。但是在 Swift 3 中,這樣做是不行的,你必須處理掉這個返回值,如下:

let _ = navigationController!.popViewController(animated: true)

使用單個下劃線來指代一個不會被使用的變數。

另外,Swift 3 不再允許傳入傳出的物件,之前帶有 var 的方法宣告將全部作廢:

func myFunc(var a: Int) -> Int

如以上這種宣告,已不可再使用,對於有多個值要返回的方法,必須改為:

fun myFunc(a: Int) -> (Int, Int)

五、可選型別

Swift 3 對可選型別的處理更嚴格了,必須顯式的在任何地方使用感嘆號,例如我們有以下程式碼:

var str: String! = "a"
var s = str
print(s)

在 Swift 以往的版本中,print 語句會打印出 str 的值,也就是『a』。而在 Swift 2.3 下,則是會打印出『Optional("a")』。因此很多對字串處理(特別是路徑處理)的程式碼都會出錯,因為會莫名其妙的帶上了各種各樣的『Optional』字樣。正確的處理方式是:

var str: String! = "a"
var s = str!
print(s)

或者

var str: String! = "a"
var s = str
print(s!)

同樣的,在實際開發中,如果用到字串模板,也需要非常注意這樣的變化:

var str  = "Loaded: \(data)"
需要被修改為
var str  = "Loaded: \(data!)"

六、Selector

Swift 對於 Selector 的修改可能是最讓人無奈的了,我們來細數一下經歷過的版本:

self.performSelector(onMainThread: #selector(handle(ret:)), with: ret, waitUntilDone: true)
就以 Swift 3 下的這個函式為基準吧,老版本的Selector獲取方法是這樣的:
#selector(ViewController.handle(_:))    // 2.2
#selector(ViewController.handle(:))     // 2.1
#selector(handle)                       // 2.0
@selector("handle:")                    // 1.x  x等於幾已經不記得了
"handle:"                               // 沒記錯的話是 1.0 時代,直接傳個字串就是 Selector
N/A                                     // Swift 的歷史上,還真有過沒有 Selector 的版本

回到 Swift 3 上來,目前的 Selector 寫法如最上面那種,需要注意的是,Selector 的方法名和引數名必須與實際被呼叫的方法完全一致,否則編譯時就會報錯。

另外,Selector 傳參時,只能傳遞物件,不能傳基礎資料型別,傳基礎資料型別的情況下,一律變成0(希望這只是當前版本的 bug,不然太蛋疼了)。雖說蘋果已經把大部分的 NS 類都去掉了字首,但是 NSNumber 這東西還是得經常用一下呢,至少目前是這樣的。

七、類庫

隨著 Swift 3 一起釋出的 iOS SDK 10,其改動也不小,特別是對一些類庫的改動,刪除了大量的方法,有些方法可能是對我們過去的開發帶來大量幫助的。但是沒有辦法,我們必須接受這樣的改變。

類庫的改動沒有辦法一一說明,我用到的 SDK 成員也非常有限,所以就只講幾個例子。

  • 針對有 option 選項的 protocol,目前強制要求為每一條都寫上 @objc,如:

    @objc protocol MyProtocol: NSObjectProtocol {
          optional func foo(myClass: MyClass?)
          optional func bar(myClass: MyClass?)
    }
    需要改為
    @objc protocol MyProtocol: NSObjectProtocol {
          @objc optional func foo(myClass: MyClass?)
          @objc optional func bar(myClass: MyClass?)
    }
  • 不再有CGRectMakeCGSizeMake等常用函數了,如:

    UIView(frame: CGRectMake(0, 0, 48, 48))
    被改為
    UIView(frame: CGRect(x: 0, y: 0, width: 48, height: 48))
  • Normal選項用方括號對來代替,如:

    btn.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
    被改為
    btn.setTitleColor(UIColor.white(), for: [])

    至於為什麼會如此改,我是沒想明白,不管怎麼說,UIControlState內已經沒有normal這個選項了,目前也只能這麼做。方括號非常容易引起對於陣列或是集合等的聯想,但是此處卻又完全不是陣列或集合,方括號的語義並不清晰。

  • 圖形圖象庫有較大改動,給個具體例子參考下:

    let imgData = UIImageJPEGRepresentation(img, 1)
    let imgPath = "\(FileUtils.getDocumentPath())/\(name)"
    imgData!.writeToFile(imgPath, atomically: true)
    必須改為
    let imgData = UIImageJPEGRepresentation(img, 1)
    let imgPath = "\(FileUtils.getDocumentPath()!)/\(name!)"
    NSData(data: imgData!).write(toFile: imgPath, atomically: true)

結束語

就先講這麼些吧,已經夠各位改一陣子了。雖然 Swift 這麼虐,但是隨著一次次迭代,還是可以看到它在穩固的進步著,希望以後不要再那麼大變化了吧。至少語法給個相容,類庫給個 Mapping,不要直接全屏飄紅(可以飄黃呀...),或許這樣才能走得更快更穩吧。

最後多講一句,臨時改標題是不對的,但是我還是改了,跟大家說聲抱歉。昨天犯了個錯誤,XCode8 裡面的確是 Swift3,只是我們都被它內建的 2.3 給誤導了,真正的 Swift3 編譯器被放在一個奇怪的地方:

Swift 2.2: Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift
Swift 2.3: Developer/Toolchains/Swift_2.3.xctoolchain/usr/bin/swift
Swift 3:   Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-migrator/swift



原文連結:http://www.jianshu.com/p/198405c1c467

相關推薦

swiftSwift 3.0實戰遷移程式Swift 3.0

每當看到新的程式語言我總是會有相當大的興趣,是的,Swift 3是一門『新語言』,因為它看起來,怎麼都不像過往的 Swift。開啟一個老的專案時,發現滿目瘡痍,基本上能標紅的程式碼全被標紅了。先來個截圖提提神: 圖一 程式碼標紅 怎麼樣,清醒點了沒?可能你會覺得奇怪,怎麼

swiftSwift 3.0實戰實現Dispatch once擴充套件

在3中原有的Dispatch once已經被廢棄了。但是可以通過給DispatchQueue實現一個擴充套件方法來實現原有的功能。 程式碼如下: public extension DispatchQueue { private static var _onceTr

ASP.NET Core 3.0 實戰構建多版本 API 介面

第一次在部落格寫分享,請多多捧場,如有歧義請多多包含! 因為業務需求發展需要,所以API介面的變更升級是必不可少的事情,而原有的介面是不可能馬上停止使用的。例如:Login介面為例,1.0版本之返回使用者的基本資訊,而2.0版本的迭代下,要把使用者祖宗十八代資訊都要返回到客戶端,這時候1.

ASP.NET Core 3.0 實戰構建多版本 API 接口

版本信息 include swaggerui 各類 val 業務 oca head sem 第一次在博客寫分享,請多多捧場,如有歧義請多多包含! 因為業務需求發展需要,所以API接口的變更升級是必不可少的事情,而原有的接口是不可能馬上停止使用的。例如:Login接口為例,

ASP.NET Core 實戰將 .NET Core 2.0 專案升級到 .NET Core 2.1

 一、前言    最近一兩個星期,加班,然後回去後弄自己的部落格,把自己的電腦從 Windows 10 改到 Ubuntu 18.10 又弄回 Windows 10,原本計劃的學習 Vue 中生命週期的相關知識目前也沒有任何的進展,嗯,罪過罪過。看了眼時間,11月也快要結束了,準備補上一

3.redis實戰redis自動備份與備份管理

redis實戰:redis自動備份與備份管理 使用redis開啟多個服務 在實際的部署中redis需要開啟多個埠來向外提供服務,不僅要設定不同的啟動引數,還需要我們及時做好備份的相關操作,這就需要藉助shell或者python等指令碼來進行管理配置。

【Web API系列教程】3.2 — 實戰處理資料(新增模型和控制器)

前言 在本部分中,你將新增用於定義資料庫實體的模型類。然後你將新增用於在這些實體上執行CRUD(Create、Retrieve、Update、Delete——譯者注)操作的Web API 控制器。 新增模型類 在本教程中,我們將通過使用“Code Fi

Scala實戰遷移檔案

開發十年,就只剩下這套架構體系了! >>>   

蘋果新的編程語言 Swift 語言進階(二)基本數據類型

保持 popu 多條語句 常量 num access 對象 程序 進制 一 、 常量和變量 Swift語言 對常量和變量的聲明進行了明白的區分 Swift語言的常量類型比C 語言的co

蘋果新的編程語言 Swift 語言進階(十三)類型檢查與類型嵌套

兩個類 nes left p s 查詢 text edi host letter 一 類型檢查 1、 類型檢查操作符 類型檢查用來檢查或轉換一個實例的類型到另外的類型的一種方式。 在Swift中,類型檢查使用is和as操作符來實現。

蘋果新的程式語言 Swift 語言進階(二)基本資料型別

一  、   常量和變數                    Swift語言 對常量和變數的宣告進行了明確的區分          Swift語言的常量型別比C 語言的constants型別更加強大,語義更加明確。          常量和變數的區別是常量在設定或初

Swift 3必看Error與NSError的關係

在學習Swift 3的過程中整理了一些筆記,如果想看其他相關文章可前往《Swift 3必看》系列目錄 在之前的版本中,Swift中Error與OC中NSError的關係就像上海的南京路與南京的上海路關係一樣,那就是沒有關係。 我們先來看兩者的區別。 Error是一個實現Erro

swift Swift 進階

聽說你已經學習Swift幾個月了,有沒有想更進一步成為Swift高手的想法?我這裡有10招祕技,各位施主且聽我慢慢道來,結個善緣。 1. 擴充套件(Extension) 任務: 求數字的平方。 // 菜鳥版 func square(x: Int) -> Int { r

[iOS] Module compiled with Swift 3.1 cannot be imported in Swift 4.0.3

遇到使用 AirWatchSDK,拿到舊的版本是用 Swift 3.1 寫的,官方寫要用 xcode 8.3 來跑,但目前是用 xcode 9.2 開發,使用的是 xcode 4.0.3 版,會顯示下列的錯誤訊息: Module compiled with Swift 3.1 cannot be impor

Swift學習函式(六)

這章就以程式碼的方式記錄了,力求做到:簡潔、完整。 //帶引數 返回值的函式         func sayHello(_ personName:String) ->String         {             let greeting =

Swift 3必看新的訪問控制fileprivate和open

在swift 3中新增加了兩種訪問控制權限 fileprivate和 open。下面將對這兩種新增訪問控制做詳細介紹。 fileprivate 在原有的swift中的 private其實並不是真正的私有,如果一個變數定義為private,在同一個檔案中的其他類依然是可以訪問

2016/07/31  安裝cocoapods 失敗 原因ruby 環境版本必須大雨2.2 > 更新到2.3後重新安裝

Last login: Sun Jul 31 08:36:30 on ttys000 mcdeMacBook-Pro:~ wufuzeng$ gem sources *** CURRENT SOURC

kafka文件(30.8.2-kafka API(java版本)

    Apache Kafka包含新的java客戶端,這些新的的客戶端將取代現存的Scala客戶端,但是為了相容性,它們仍將存在一段時間。可以通過一些單獨的jar包呼叫這些客戶端,這些包的依賴性都比較小,同時老的Scala客戶端仍會存在。 一、Producer

Swift基礎呼叫第三方OC專案

第一步:建立和配置Bridging-Header.hSwift與OC進行混編,首先要有一個.h檔案,這裡使用Bridging-Header.h然後設定專案的Build Settings--Swift C

Swift基礎手勢識別(雙擊、捏、旋轉、拖動、划動、長按)

// // ViewController.swift // JieUITapGestureRecognizer // // Created by jiezhang on 14-10-4. // Copyright (c) 2014年 jiezhang. All rig