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新特性。歡迎關注微信公眾號:樂Coding
獲得最新文章。
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 Checker
Xcode9以前不會自動檢測是否在非主線程更新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)") //'strName' is inaccessible due to 'private' protection level
}
}
必須把private
換成fileprivate
才可以,但是權限又被擴大了。到了Swift4中extension也可以訪問private中的屬性了。
2. 類型和協議的組合類型
//2.1 定義類
class Person {
var name:String?
}
class Student: Person {
var sId:Int = 0
}
class Teacher: Person {
}
//2.2 協議
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 {
//man既能唱又能跑,還有名字
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:UIColor
init(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具有以下優勢:
- 可以再 class、struct上使用
- 定義類型時無需加上 @objcMembers、dynamic 等關鍵字,使用更簡潔
- 性能更好
- 類型安全和類型推斷,例如
apple.valueForKeyPath(color)
返回的類型是 Any,apple[keyPath: \Apple.color]
直接返回 UIColor 類型 - 可以在所有值類型上使用
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 Slicing
Swift3中獲取子串
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)") //關注微信公眾號:樂Coding : 歡迎關
}
}
5.3 String增加了Collection的一些特性
在Swift4中字符串做了一些Collection類似功能函數的擴展(并不是實現Collection協議,而是使用起來更像Collection,更友好)。
func test6() {
//1.0 字符串翻轉
let str = "Backwards"
let str2 = str.reversed() //ReversedCollection<String>
let reversedWord = String(str2)
print(reversedWord) //sdrawkcaB
//2. 0 遍歷字符串
for char in str {
print(char, terminator: "") //Backwards
}
//3.0 Map
print("\n---------- Map --------")
_ = str.map {
print($0.description+"...")
}
/* 打印
B...
a...
c...
k...
w...
a...
r...
d...
s...
*/
//4.0 Filter
print("\n---------- Filter --------")
let filtered = str.filter {
$0 == "c"
}
print("\(filtered)") //c
//5.0 Reduce
let letters = "abracadabra"
let letterCount = letters.reduce(into: [:]) { counts, letter in
counts[letter, default: 0] += 1
}
print("\(letterCount)") //["b": 2, "a": 5, "r": 2, "d": 1, "c": 1]
}
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: String
var 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? Data
if let cat2 = try? JSONDecoder().decode(Animal.self, from: decode!){
print("\(cat.name)") //wildcat
}
}
}
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 in
return students.index(of: element) ?? 0
}
print("dic: \(dic)")
//dic: [4: ["Akosua"], 2: ["Efua"], 0: ["Kofi"], 1: ["Abena"], 3: ["Kweku"]]
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)")
//massiveCities: ["Shanghai": 24256800, "Karachi": 23500000, "Beijing": 21516000]
//在Swift3中massiveCities返回的是一個數組,要訪問massiveCities中的元素必須massiveCities[0].value。Swift4中變成我們期望的返回一個字典,可以massiveCities["Shanghai"]直接取
7.3 新增mapValues函數
先看下面例子:
let populations = cities.map { $0.value * 2 }
print("\(populations)")
//[48513600, 47000000, 43032000, 19990000]
我們原本希望populations返回的還是一個字典,只是值變成2倍,可是map在Swift4中并沒有這么改,而是添加了一個mapValues()
函數
let roundedCities = cities.mapValues { "\($0 / 1_000_000) million people" }
print("\(roundedCities)")
//["Shanghai": "24 million people", "Karachi": "23 million people", "Beijing": "21 million people", "Seoul": "9 million people"]
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"] //等價于 let name = person["name"] ?? "Anonymous"
print("\(name)") // Taylor
let create = person["create", default: "1984-01-01"]
print("\(create)") // 1984-01-01
還可以看一個統計數組中元素出現次數的例子:
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)")
//["易烊千璽", "王俊凱", "王源"]
}
覺得不錯請點擊下方【喜歡】,為了微博認證也是拼了!還差1660個??
更多iOS、Swift、iOS逆向最新文章請關注微信公眾賬號:樂Coding
,或者微信掃描下方二維碼關注
icon.jpg