XCode9新特性 1. 支持遠程調試 2. Xcode綁定Github帳號 3. 支持Swift類重命名 4. Swift低版本兼容 5. Main Thread Checker 6. 模擬器支持多開 7. 標示功能 8. 協議自動補全 9. 代碼段自動抽出函數 10. 自定義顏色名稱 11. Debug View Hierarchy可以顯示ViewController了 12.支持Markdown,可以在xcode中查閱、編輯markdown文件
Swift4更新 1. Extension可以訪問private的屬性 2. 類型和協議的組合類型 3. 新的Key Paths 語法 4. 下標支持泛型 5. 字符串 5.1 可以直接獲取字符串長度了 5.2 字符串獲取子串語法糖… One-sided Slicing 5.3 String增加了Collection的一些特性 5.4 多行字符串 6. 序列化的簡化 7. Dictionary and Set增強 7.1 通過Sequence初始化 7.2 字典過濾後類型不變 7.3 新增mapValues函數 7.4 字典支持默認值 8. MutableCollection新增swapAt(::) 用來交換兩個位置的值
上篇文章我們介紹了iOS11適配iPhoneX總結,這次分享下Xcode9和Swift4新特性。
XCode9新特性新特性每次都是:更快、更高、更強
1. 支持遠程調試從來沒有接過的iOS設備要先插入一次,然後在設備窗口選中 Connect via Network選項,之後就可以斷開設備進行網絡調試。
如果是已經插入過的手機,插入Mac後選中Xcode的 Window -> Devices and Simulators -> Devices -> 勾選Connect via network
這裡有一個前提:iPhone必須升級到iOS11,電腦和iPhone在同一個區域網下。
勾選過一次,以後調試就不用數據線了,爽不爽!手機右邊有個網絡小星球說明是遠程設備。
2. Xcode綁定Github帳號點擊右上角Xcode -> Preferences ->
3. 支持Swift類重命名
原來的版本一直不支持Swift語言的重命名操作,終於啊終於此時應該高歌一曲:
等了好久終於等到今天夢了好久終於 把夢實現前途漫漫任我闖幸虧還有你在身旁盼了好久終於 盼到今天夢了好久終於 把夢實現.
4. Swift低版本兼容原來每次升級Xcode都要convert Swift進行升級,現在Xcode9兼容Swift3.2
5. Main Thread CheckerXcode9以前不會自動檢測是否在非主線程更新UI,這樣會有安全隱患。現在Xcode9自動附帶了Main Thread Checker功能。一旦在非主線程操作UI就會在命令行警告:類似如下:
Main Thread Checker: UI API called on a background thread: -[UIView subviews]PID: 28353, TID: 267810, Thread name: (none), Queue name: com.apple.root.user-initiated-qos, QoS: 25現在讀秒項目中第三方的小米推送和Bugtags、諸葛IO都有這個問題,需要更新到最新版。小米推送一直沒更新,我上周給他們發郵件反饋周四才更新。
6. 模擬器支持多開可以同時打開多個型號模擬器
7. 標示功能範圍標示
將遊標移到 { } 、( ) 或是 class、func、if、for 等關鍵字時,按住 command 鍵,Xcode 將聰明地標示對應的 class、function、if、for 區塊。
提示功能
跟剛剛一樣,將遊標移到關鍵字上,按住 command 鍵,然後點擊,即可出現貼心的提示選單。
比方如圖所示,遊標停在 if 上,按住 command 鍵點擊後提示選單出現 Add 「else」 Statement 和 Add 「else if」 Statement,Extract Method 等選項。選擇 add 「else」 Statement 後,自動完成 else { } 的輸入。
8. 協議自動補全Swift的protocol中必須實現的函數當沒有實現時會報錯,有時我們需要點擊協議定義的地方查看必須實現那些函數。現在Xcode9支持自動補全必須實現的函數
例如UIViewController遵循UITableViewDataSource協議,當未實現函數時會有紅色錯誤提示,點擊Fix就會自動補全。
9. 代碼段自動抽出函數選中一段代碼,右鍵選擇Refactor -> Extract Method 就會把選中的代碼段單獨抽出一個函數。這個功能在代碼重構中很有用。
10. 自定義顏色名稱可以在 Assets.xcasset 裡添加顏色,取個名稱,然後在代碼或者 Storyboard 中引用這個顏色了。
在 Assets.xcassets 頁面,右鍵選擇New Color Set
然後設置顏色和名字
在xib或者sb中使用的時候可以直接在Named Colors中選擇
代碼中使用,現在代碼中只能iOS11以上可以用
if #available(iOS 11.0, *) {self.view.backgroundColor = UIColor(named:"MainBlue")}11. Debug View Hierarchy可以顯示ViewController了Debug View Hierarchy是一個很好的頁面調試工具,方便研究頁面上的控制項,原來是無法看到當前Controller的,現在Xcode9中可以看到了。
12.支持Markdown,可以在xcode中查閱、編輯markdown文件Swift4更新1. Extension可以訪問private的屬性在Swift3中類、結構體和枚舉的擴展中不能訪問private屬性。
下面這種寫法會報錯:'strName' is inaccessible due to 'private' protection level
class ViewController: UIViewController {private var strName:String = "test"}extension ViewController{func testFunc() {print("\(self.strName)")}}必須把private換成fileprivate才可以,但是權限又被擴大了。到了Swift4中extension也可以訪問private中的屬性了。
2. 類型和協議的組合類型class Person {var name:String?}class Student: Person {var sId:Int = 0}class Teacher: Person {}protocol Runnable {func run()}protocol Singing {func sing()}extension Student :Runnable, Singing{func run() {print("\(self.name ?? "")會跑步")}func sing() {print("\(self.name ?? "")會唱歌")}}extension Teacher :Runnable{func run() {print("\(self.name ?? "")會跑步")}}extension ViewController {func test2(human:Person&Singing&Runnable) {if (human.name?.count ?? 0) > 0 {human.run()human.sing()}}}如果在Swift3中只能像下面這樣寫
func test2(man:Person) {if (man.name?.characters.count ?? 0) > 0 {if let mm = man as? Runnable{mm.run()}if let mm = man as? Singing{mm.sing()}}}3. 新的Key Paths 語法Swift4可以使用\+點語法的形式創建KeyPath
let path:KeyPath = \Apple.color
例子:
//MARK: 3.0 新的Key Path語法class Apple {var color:UIColorinit(color:UIColor) {self.color = color}}extension ViewController {func test3(){let apple = Apple(color: UIColor.red)let c = apple[keyPath:\Apple.color]print("\(c)")}}Swift4的KeyPath具有以下優勢:
4. 下標支持泛型在Swift4之前,下標屬性只能返回Any類型,現在可以添加泛型約束
struct School<Key:Hashable , Value> {var studens:[Key: Value]init(studens:[Key: Value]) {self.studens = studens}subscript<Value>(key: Key) -> Value? {return studens[key] as? Value}}extension ViewController {func test4(){let tfboys = School(studens: ["001":"王俊凱","002":"易烊千璽","003":"王源"])let name:String? = tfboys["001"]print("\(name ?? "")")}}5. 字符串5.1 可以直接獲取字符串長度了Swift3中想要獲取字符串的長度必須: str.characters.count ,現在可以str.count直接獲得了。
Swift 3 中的 String 需要通過 characters 去調用的一些屬性方法,在 Swift 4 中可以通過 String 對象本身直接調用。
5.2 字符串獲取子串語法糖… One-sided SlicingSwift3中獲取子串
let values = "歡迎關注微信公眾號:樂Coding"let startIndex = values.index(values.startIndex, offsetBy: 3)let subvalues = values[startIndex..<values.endIndex]Swift4中可以使用...語法
extension ViewController{func test5() {let str = "歡迎關注微信公眾號:樂Coding"let start = str.index(str.startIndex, offsetBy: 2)let subStr = str[start...]let subStr2 = str[...start]print("\(subStr) : \(subStr2)")}}5.3 String增加了Collection的一些特性在Swift4中字符串做了一些Collection類似功能函數的擴展(並不是實現Collection協議,而是使用起來更像Collection,更友好)。
func test6() {let str = "Backwards"let str2 = str.reversed()let reversedWord = String(str2)print(reversedWord)for char in str {print(char, terminator: "")}print("\n Map ---")_ = str.map {print($0.description+"...")}print("\n Filter ---")let filtered = str.filter {$0 == "c"}print("\(filtered)")let letters = "abracadabra"let letterCount = letters.reduce(into: [:]) { counts, letter incounts[letter, default: 0] += 1}print("\(letterCount)")}5.4 多行字符串swift3中寫多行字符串只能在字符串中添加\n,易讀性不好。Swift4中新增加了多行字符串語法""",注意"""要單獨佔一行。
func test7(){let mutableLineStr ="""小明:你媽叫你回家吃飯。小紅。"""print(mutableLineStr)}列印結果:
6. 序列化的簡化原來對象序列化,需要對象遵守NSCoding協議並實現下面三個方法,比較麻煩。
- (id)initWithCoder:(NSCoder *)coder;- (void)encodeWithCoder:(NSCoder *)coder;- (id)copyWithZone:(NSZone *)zone;Swift4中只需要對象實現Codable協議。然後選擇把對象轉成Json(JSONEncoder)還是Plist(PropertyListEncoder)存儲。
struct Animal:Codable {var name: Stringvar age: Int}extension ViewController {func test8(){let cat = Animal(name: "wildcat", age: 2)if let encoded = try? JSONEncoder().encode(cat) {UserDefaults.standard.set(encoded, forKey: "MyCat")UserDefaults.standard.synchronize()}let decode = UserDefaults.standard.object(forKey: "MyCat") as? Dataif let cat2 = try? JSONDecoder().decode(Animal.self, from: decode!){print("\(cat.name)")}}}7. Dictionary and Set增強7.1 通過Sequence初始化字典通過Sequence創建的函數聲明:
public init<S>(grouping values: S, by keyForValue: (S.Element) throws -> Key) rethrows where Value == [S.Element], S : Sequence下面以數組轉字典為例,字典的key是元素在數組中下標
let students = ["Kofi", "Abena", "Efua", "Kweku", "Akosua"]let dic = Dictionary(grouping: students) { (element) -> Int inreturn students.index(of: element) ?? 0}print("dic: \(dic)")7.2 字典過濾後類型不變在Swift3中Dictionary調用filter後會返回一個數組,但我們肯定希望還是返回一個過濾後的Dictionary,在Swift4中按照我們希望的做了修改。
let cities = ["Shanghai": 24_256_800, "Karachi": 23_500_000, "Beijing": 21_516_000, "Seoul": 9_995_000];let massiveCities = cities.filter { $0.value > 10_000_000 }print("massiveCities: \(massiveCities)")7.3 新增mapValues函數先看下面例子:
let populations = cities.map { $0.value * 2 }print("\(populations)")我們原本希望populations返回的還是一個字典,只是值變成2倍,可是map在Swift4中並沒有這麼改,而是添加了一個mapValues()函數
let roundedCities = cities.mapValues { "\($0 / 1_000_000) million people" }print("\(roundedCities)")7.4 字典支持默認值下面的let name =person["name", default: "Anonymous"]默認值語法,類似於let name = person["name"] ?? "Anonymous"
let person = ["name": "Taylor", "city": "Nashville"]let name = person["name", default: "Anonymous"]print("\(name)")let create = person["create", default: "1984-01-01"]print("\(create)")還可以看一個統計數組中元素出現次數的例子:
let favoriteTVShows = ["Red Dwarf", "Blackadder", "Fawlty Towers", "Red Dwarf"]var favoriteCounts = [String: Int]()for show in favoriteTVShows {favoriteCounts[show, default: 0] += 1}print("favoriteCounts: \(favoriteCounts)")8. MutableCollection新增swapAt(::) 用來交換兩個位置的值func test10() {var array = ["王俊凱","易烊千璽","王源"]array.swapAt(0, 1)print("\(array)")}