歡迎加入QQ討論群258996829
來自星星的你 頭像
蘋果3袋
3
來自星星的你

Xcode 6.3 Beta發(fā)布,Swift 1.2帶來哪些新變化?

發(fā)布時間:2015-02-11 20:53  回復:0  查看:2883   最后回復:2015-02-11 20:53  

北京時間2月10日,蘋果在面向開發(fā)者推送iOS 8.3 Beta的同時,還發(fā)布了版本號為6D520o的Xcode 6.3 Beta,其中便包含了iOS 8.3 Beta和OS X v10.10 SDK,并進一步提升了Swift與Objective-C代碼的交互性,而Swift業(yè)已更新至1.2版本。

 

Xcode 6.3 Beta Release Notes看出,Xcode 6.3 Beta包含了很多頗為值得開發(fā)者期待的改變,共計50多處改動,同時修改了Objective-C的語法,足見蘋果對Swift語言的重視。而其代碼遷移工具可以幫助開發(fā)者將其代碼從Swift 1.1(Xcode 6.1)升級至Swift 1.2(Xcode 6.3),具體執(zhí)行編輯菜單(Edit)->轉(zhuǎn)換(Convert)-至(To)Swift1.2即可。 具體更新如下:

Swift語言的增強

  • Swift現(xiàn)在支持目標增量編譯,例如當一個文件改變時不會重新編譯Target中的每一個文件。這個基于固有依賴分析。所以你依然會看到有很多文件在必要情況下被重編。如果你發(fā)現(xiàn)需要重編但沒有重編的情況,請報一個Bug出來。清理Target后再編,會按照往常的流程進行。
  • 增加了一個新的Set數(shù)據(jù)類型,它提供了元素唯一化,且有完整語義的通用數(shù)據(jù)類型集合。它和NSSet類型橋接,提供和Array和Dictionary相類似的功能。
  • if let語句現(xiàn)在被擴展為可以支持多條條件判斷:


if let a = foo(), b = bar() where a < b,  
let c = baz() {  
 }  

它允許你測試多種選擇,并且包含一個bool判斷。當然這種情況不包含嵌套判斷。

  • let常量現(xiàn)在生成時不需要立即初始化,新的規(guī)則是let常量必須在被首次使用前初始化即可(和var一樣)。或者說它只能被初始化,也就是說在初始化后它不能再被改變或者重新賦值,可用的模式如下:
let x: SomeThing  
 if condition {  
 x = foo()  
 } else {  
 x = bar()  
 }  
 use(x) 

這個正常的來說需要var變量用法,盡管這里沒有任何修改的操作。

  • "Static"靜態(tài)方法和屬性現(xiàn)在允許在class中使用(作為“class final”的別名)。你現(xiàn)在可以在類中聲明一個靜態(tài)存儲屬性,它享有全局存儲空間和首次使用再初始化的惰性構(gòu)造功能。協(xié)議Protocal現(xiàn)在會聲明一個static的類型要求而不是聲明一個class的要求。
  • 對于表達式閉包的類型引用有了幾點改進:
  1. 含有單返回語句的閉包現(xiàn)在類型檢查時以單表達式閉包處理。
  2. 匿名的且含有非空返回類型的單表達式現(xiàn)在可以用在Void上下文中。
  3. 多表達式的閉包類型的情況可能無法被類型推斷出來,這歸功于缺乏返回類型的情況能被正確的推斷出來。
  • Swift中的枚舉類型現(xiàn)在可以通過@objc關鍵字導出到Objective-C中。@objc的枚舉類型必須定義一個整型的原始類型,并且該枚舉不能泛型化或者不能使用關聯(lián)值。由于Objective-C中的枚舉類型沒有命名空間,所以導出到Objective-C中的枚舉類型以枚舉名字和case項目名字的組合的方式使用。 比如在Swift中的聲明:
@objc  
 enum Bear: Int {  
 case Black, Grizzly, Polar  
 }
導出到Objective-C:

typedef NS_ENUM(NSInteger, Bear) {  
BearBlack, BearGrizzly, BearPolar  
};  
  • Objective-C語言的擴展語法現(xiàn)在可以判斷出Objective-C API中指針或者block的是否為空,同時允許不帶ImplicitlyUnwrappedOptional協(xié)議地導出Objective-C API函數(shù)。
  • Swift現(xiàn)在可以部分支持導入C的聯(lián)合類型,包括unions、bitfileds、SIMD vector類型以及其他Swift的不支持的C特性。這些不被支持的元素不能在Swift中的直接訪問,但是在Swift中,Objective-C或者C可以以參數(shù)或者返回類型的方式使用。這包括Foundation NSDecimal類型、GLKit GLKVector和GLKMatrix類型,以及其他一些類型。
  • 被導入的C結(jié)構(gòu)體現(xiàn)在在Swift中有一個默認的構(gòu)造器,它會將結(jié)構(gòu)體中的所有的元素初始化為0,例如:
import Darwin  
 var devNullStat = stat()  
 stat("/dev/null", &devNullStat)  

如果一個結(jié)構(gòu)體的元素不能被正確的初始化為0(比如被標記為新的_nonnull標示符時),這個默認的構(gòu)造器將會終止。

  • String的索引類型間新的轉(zhuǎn)換API現(xiàn)在可以用了,如String、String.UnicodeScalarView、String.UTF16View以及String.UTF8View, 同時每個String View轉(zhuǎn)換為String的函數(shù)也可使用。
  • 類型值在println函數(shù)或者字符串內(nèi)插算法中現(xiàn)在可以打印完整的類型名稱了:
toString(Int.self) // 打印 “Swift.Int"  
 println([Float].self) // 打印 "Swift.Array<Swift.Float>”  
 println((Int, String).self) // 打印 "(Swift.Int, Swift.String)"  
  • 一個新的“@noescape”屬性可以用在函數(shù)的閉包參數(shù)上,這意味著這個參數(shù)是唯一可被調(diào)用的(或者用在函數(shù)調(diào)用時以參數(shù)的方式出現(xiàn)),其意思是它的生命周期比函數(shù)調(diào)用的周期短,這有助于一些小小的性能優(yōu)化,但最重要的是它屏蔽了閉包中對self.的需求。這使得函數(shù)的控制流比其他更加透明。在未來的beta版本中,標準庫函數(shù)將普遍采用這種特性,比如autoreleasepool():
func autoreleasepool(@noescape code: () -> ()) {  
   pushAutoreleasePool()  
   code()  
   popAutoreleasePool()  
 }  
  • 相比Swift 1.1,Swift 1.2在很多方面的性能上有本質(zhì)的提高,比如多維數(shù)組算法更快,未優(yōu)化的代碼更加快速。
  • 表達式類型的錯誤診斷有了很大的提高。
  • 很多通用表達式的檢查效率有很大提高,這個有助于降低編譯時間和減少“expression too complex”的錯誤。

Swift語言的改變

  • “確保轉(zhuǎn)換”和“可失敗轉(zhuǎn)換”的概念現(xiàn)在被分為兩個操作符??墒∞D(zhuǎn)換現(xiàn)在使用as!運算符,這個!感嘆號可以讓代碼的讀者更清晰的明白本次轉(zhuǎn)換可能失敗并觸發(fā)一個運行時錯誤。“as”操作符會保持向上轉(zhuǎn)換(比如“someDerivedValue轉(zhuǎn)換為Base”)或者類型標注(“0 轉(zhuǎn)換為Int8”),它保證了轉(zhuǎn)換不會失敗。
  • 結(jié)構(gòu)體和類構(gòu)造器中的let不可變屬性現(xiàn)在被規(guī)范為更加標準的通用模型:lets類型初始化后將永不會被改變或重新賦值。以前的實現(xiàn)是,可以在構(gòu)造器中任意修改,而現(xiàn)在它們只允許被初始化和提供值操作。如果一個屬性在聲明時已經(jīng)賦值,那么它會被所有的構(gòu)造器認為已經(jīng)含有初始值。
  • 從橋接Objective-C類 (NSString/NSArray/NSDictionary)到它Swift中值類型的隱式轉(zhuǎn)化被移除。這將是Swift的類型系統(tǒng)更加簡單和可預測。這意味著:
import Foundation  
func log(s: String) { println(x) }  
let ns: NSString = "some NSString" // Okay  
log(ns) // 錯誤  
// "'NSString' 不能轉(zhuǎn)換為 'String'"  
為了完成橋接轉(zhuǎn)換,需要用顯式轉(zhuǎn)化符標注:

log(ns as String) // succeeds  
從Swift類型到Objective-C類型的橋接隱式轉(zhuǎn)換依然被允許,比如:

func nsLog(ns: NSString) { println(ns) }  
 let s: String = “some String”  
 nsLog(s) // okay: implicit conversion from String to NSString is still permitted  
  • @autoclosure現(xiàn)在標注在參數(shù)上,而不是標注在參數(shù)的類型上。比如:
//以前我們這樣寫:  
 func assert(predicate : @autoclosure () -> Bool) {… }  
//現(xiàn)在需要這樣寫:  
 func assert(@autoclosure predicate : () -> Bool) {… }  
  • 使用在函數(shù)參數(shù)上的 @autoclosure屬性現(xiàn)在含有@noescape新屬性的功能,這個改進限制了@autoclosure作為控制流程以及惰性計算的能力。
  • 柯里化函數(shù)現(xiàn)在可以指定參數(shù)標簽了:
func curryUnnamed(a: Int)(_ b: Int) { return a + b }  
curryUnnamed(1)(2)  
func curryNamed(first a: Int)(second b: Int) -> Int { return a + b }  
curryNamed(first: 1)(second: 2)  
  • Swift現(xiàn)在可以檢測在Swift類型系統(tǒng)中覆蓋和重寫的差異以及通過Objective-C運行時可見的影響。比如,下面Objective-C類中對屬性的setter和類擴展中對方法的“setProperty”它們之間的沖突現(xiàn)在可以被診斷:
class A : NSObject {  
 var property: String = "Hello" // 注意: Objective-C 方法 'setProperty:’  
 // 以前這里“屬性”這里是通過setter聲明  
 }  
 extension A {  
 func setProperty(str: String) { } // 錯誤:方法"setProperty"  
 // 重復聲明了Objective-C方法  
 //'setProperty:'  
 }  
同樣地檢查在Objective-C中重寫:

class B : NSObject {  
func method(arg: String) { } // 注意:重寫操作  
// 這里含有類型:'(String) -> ()'  
}  
class C : B {  
func method(arg: [String]) { } // 錯誤: 重寫的選擇器方法含有不匹配的類型'([String]) -> ()'  
}  
和協(xié)議的適配性一樣:

class MyDelegate : NSObject, NSURLSessionDelegate {  
 func URLSession(session: NSURLSession, didBecomeInvalidWithError: Bool){ }  
 // 錯誤:Objective-C 方法 'URLSession:didBecomeInvalidWithError:'  
 //由方法提供: 'URLSession(_:didBecomeInvalidWithError:)'  
 // 和可選類型的需求方法相沖突:  
 // 'URLSession(_:didBecomeInvalidWithError:)' 在協(xié)議  
 // 'NSURLSessionDelegate'  
 }  

Swift語言Bug修復

  • 動態(tài)轉(zhuǎn)換符(“as!”, “as?“和“is”)現(xiàn)在可以用在Swift的協(xié)議類型上,只要該協(xié)議類型沒有關聯(lián)類型。
  • 在Playground增加的一致性需求現(xiàn)在可以按照預期工作了,比如:
struct Point {  
 var x, y: Double  
 }  
 extension Point : Printable {  
 var description: String {  
 return "(\(x), \(y))"  
 }  
 }  
 var p1 = Point(x: 1.5, y: 2.5)  
 println(p1) // prints "(1.5, 2.5)”  
  • 導入的沒有文檔化的NS_ENUM類型,比如UIViewAnimationCurve,現(xiàn)在可以通過init(rawValue:) 構(gòu)造器從它的原始整型類型轉(zhuǎn)換出來而不會重設為nil,為解決這個問題而用替代方法unsafeBitCast編寫的代碼現(xiàn)在可以使用原始值構(gòu)造器編寫了。比如:
let animationCurve =  
nsafeBitCast(userInfo[UIKeyboardAnimationCurveUserInfoKey].integerValue,  
UIViewAnimationCurve.self)  
現(xiàn)在可以寫為:

let animationCurve = UIViewAnimationCurve(rawValue:  
userInfo[UIKeyboardAnimationCurveUserInfoKey].integerValue)! 
  • 在枚舉類型中負浮點數(shù)可以用作原始值了。
  • 指向Objective-C類,或者Swift中繼承自Objective-C對象的無主引用,在該無主引用指向的對象釋放后無主引用被重新賦值時不會再Crash。
  • 含有觀察訪問器的變量或者屬性如果它可以從初始值表達式中推斷出類型就無需顯式指定類型。
  • NSClassFromString函數(shù)搜索失敗時其結(jié)果和nil的比較現(xiàn)在工作正常。
  • 子類中的重寫基類含有可選類型的方法時,如果涉及到可選類型的轉(zhuǎn)換將不會導致Crash。
class Base {  
 func foo(x: String) -> String? { return x }  
 }  
 class Derived: Base {  
 override func foo(x: String?) -> String { return x! }  
 }  

關于Objective-C語言的增強

  • Objective-C API中可以表示參數(shù),返回值,屬性,變量等等的“nullability”屬性。比如,下面是表達很多UITableView API的為空特性:
-(void)registerNib:(nonnull UINib *)nib forCellReuseIdentifier:(nonnull  
SString *)identifier;  
-(nullable UITableViewCell *)cellForRowAtIndexPath:(nonnull  
SIndexPath)indexPath;  
@property (nonatomic, readwrite, retain, nullable) UIView *backgroundView;
這個nullability標示符影響了Objective-C API在Swift的可選類型值,nonnull標示符標示的類型將會以非可選的類型的導入,這個用來替代隱式解封可選類型如(e.g., UINib!)。而nullable標示符標示的類型則會以可選類型導入(如UITableViewCell?),所以下面的API在Swift中表現(xiàn)如下:

func registerNib(nib: UINib, forCellReuseIdentifier identifier: String)  
func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell?  
var backgroundView: UIView?  
  • 可空特性標示符也可以用在指針類型,包括C指針,block指針和C++成員指針,使用雙下劃線方式,比如:
void enumerateStrings(__nonnull CFStringRef (^ __nullable callback)(void));  
這里,它自身的回調(diào)函數(shù)是nullable的,但是它的回調(diào)函數(shù)的返回類型為nonnull,所以這個API在Swift以如下方式使用:

func enumerateStrings(callback: (() -> CFString)?)  
總的來說,可空特性標示符有三種,可以用雙下劃線(用在任何指針類型),或者沒有下劃線的(用在Objective-C屬性,方法結(jié)果類型或者方法參數(shù)類型)。

Type qualifier spelling
Objective-C property/method spelling
Swift view
Meaning 
__nonnull 
nonnull 
Non-optional, 如: UINib
該值永遠不會為nil(有一種例外是可能參數(shù)傳遞時傳入的消息為空)
__nullable 
nullable 
Optional, 如:UITableViewCell?
該值可能為nil 
__null_unspecified
null_unspecified 
隱式解封可選類型如, NSDate!
不確定該值是否為空(很少見) 
  • 特別是在Objective-C API中,很多指針傾向于nonnull,因此Objective-C提供了“audited”域(通過新的#pragma),它會認為未被標注的指針為nonnull,比如下面的例子等同于上面第一個例子,但是它用的是“audited”域來簡化語句表達:
#pragma clang assume_nonnull begin  
 // …  
 -(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString  
*)identifier;  
 -(nullable UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath)indexPath;  
 @property (nonatomic, readwrite, retain, nullable) UIView *backgroundView;  
 // …  
 #pragma clang assume_nonnull end  
  • 為了保證代碼的連續(xù)性,我們強烈建議你在所有的Objective-C頭文件使用“audited”域來表述其api的可空性,同時避免null_unspecified情況,建議使用在將可空性引入到現(xiàn)有的頭文件時采用該功能作為過渡工具。
  • Objective-C增加的nullability注解不會影響它的向后兼容性也不會影響代碼的編譯。比如nonnull在有些情況下依然可以以nil結(jié)束,諸如消息路由到一個為nil的接收器,但是,nullability注解只是提高Swift的編程體驗,它會在Objective-C中產(chǎn)生一個新的警告,諸如朝一個nonnull的參數(shù)賦一個nil的話,這使得Objective-c API更加高效以及使用的正確。
  • Objective-C可以通過null_resettable來表達屬性的空屬性,該屬性setter訪問器允許將其設置為nil(設置該屬性為默認值),但是它的getter訪問器不會提供一個nil值(因為它提供了默認值),有一個這樣的屬性如UIView’s tintColor,如果沒有tint顏色指定時它會提供一個默認的tint顏色值,如:
@property (nonatomic, retain, null_resettable) UIColor *tintColor;  
這樣的API在Swift使用隱式強制解封的方法使用:

var tintColor: UIColor!  
  • C指針類型的參數(shù)或者Block指針類型可以使用noescape新屬性標志,它用來標明這個指針參數(shù)不會離開這個函數(shù)或者方法而使用。這種情況下,可以安全的傳遞一個局部變量地址,noescape block指針在Swift中將會被映射為@noescape參數(shù):
void executeImmediately(__attribute__((noescape)) void (^callback)(void);  
將被影射到Swift為:

func executeImmediately(@noescape callback: () -> Void)  
  • LLDB現(xiàn)在包含了一個printf()函數(shù)去計算C/C++/Objective-C表達式,這個將在arm64設備上提升表達式計算的體驗,但是可能和用戶在.lldbinit定義的表達式前綴沖突,如果你發(fā)現(xiàn)在表達式計算時出現(xiàn)錯誤,這可能就是root cause。
  • XCode 6.3將Apple LLVM編譯器更新為6.1.0,這個新的編譯器版本包含了對C++14標準的全部支持,包括大量的增強的警告診斷和新的優(yōu)化,對于arm64架構(gòu)的支持進行了有效的重構(gòu)來支持ARM的實現(xiàn), 這個將明顯影響矩陣內(nèi)聯(lián)函數(shù)計算。
  • 為arm64 vfma/vfms內(nèi)聯(lián)函數(shù)預定的參數(shù)被移除,雖然這個改變不會產(chǎn)生一個編譯時錯誤,但是它會中斷代碼運行時操作,我們需要明確這個變化來減少風險。默認的,編譯器現(xiàn)在會對使用這種內(nèi)聯(lián)屬性提供警告并維持固有的行為,在盡可能的情況下,你需要接受這個變化并且定義USE_CORRECT_VFMA_INTRINSICS宏為1告訴編譯器接收警告,當然你也可以可以USE_CORRECT_VFMA_INTRINSICS宏為0來屏蔽警告并保持固有行為。但是請不要保留這樣的代碼太久,因為我們計劃在未來的版本中移除對這種舊行為的支持。
  • 含有自動尺寸標志的視圖以及包含在UITableView、UICollectionView或NSScrollView的視圖在打開文檔時不會再出現(xiàn)對齊錯誤。


作者簡介:

王芳杰 目前就職于疊拓信息技術(shù)有限公司,擔任疊拓NGN中國人力資源培養(yǎng)經(jīng)理、疊拓NGN中國售前經(jīng)理,《老碼說編程之玩轉(zhuǎn)Swift江湖》一書作者。

您還未登錄,請先登錄

熱門帖子

最新帖子

?