Swift 3.0
iOS10 訪問權限
//在info.plist文件中添加鍵值對,輸入Privacy 就可以找到各種權限的鍵 值為描述字符
Privacy - Photo Library Usage Description : 親,可以打開你的相冊嗎?
//用到自帶地圖、鑰匙鏈、后台、HomeKit、VPN等網絡配置權限的應用,需要到工程配置的Capabilities中打開對應開關
使用Carthage管理第三方庫
touch Cartfile
#list github source
carthage update
Cartfile content
github "Alamofire/Alamofire" ~> 4.0.1
github "SnapKit/SnapKit" == 3.0.2
github "SwiftyJSON/SwiftyJSON" >= 2.1.2
github "rs/SDWebImage" ~> 3
github "mxcl/PromiseKit" ~> 4.0
github "uacaps/PageMenu"
>= 1.0 for “at least version 1.0”
~> 1.0 for “compatible with version 1.0”
== 1.0 for “exactly version 1.0”
常用第三方庫
- Alamofire (類AFN)
- SwiftyJSON (類MJExtension)
- SDWebImage (同)
- SnapKit (類Masorny)
- SwiftLint (代碼風格檢查器)
- PromiseKit (異步編程框架)
- SVProgressHUD (HUD)
第三方庫的基本使用
SVProgressHUD的使用
SVProgressHUD的靜態方法
Code | 效果 |
---|---|
show() | 顯示無限循環進度條 |
dismiss() | 關閉HUD |
showProgress(0.1, status: "正在下載") | 顯示有進度的HUD |
showInfo(withStatus: "請輸入密碼") | 顯示信息 |
showSuccess(withStatus: "下載完成") | 顯示成功信息 |
showError(withStatus: "密碼錯誤") | 顯示錯誤信息 |
show(UIImage(named:"icon"), status: "展示圖片") | 顯示自定義圖片 |
Alamofire
- 常用的GET請求
Alamofire.request("https://jsonapi.com").responseJSON { (rs) in
switch rs.result {
case .success(let v):
print(v)
case .failure(let e):
print(e)
}
}
- 常用的POST請求
let parameters: Parameters = [
"name": "xiaos",
"age": 22,]
Alamofire.request("https://jsonapi.com",method:.post,parameters:parameters).responseJSON { (rs) in
//rs.request?.url == "https://jsonapi.com"
//rs.request?.httpBody == name=xiaos age=22
}
Alamofire.request("https://jsonapi.com",method:.post,parameters:parameters,encoding:URLEncoding.queryString).responseJSON { (rs) in
//rs.request?.url == "https://jsonapi.com?name=xiaos&age=22"
}
- 完整的GET請求
Alamofire.request("https://jsonapi.com", method: .get, parameters: ["name":"xiaos"], encoding: URLEncoding.methodDependent, headers: ["key1":"value1"]).responseJSON { (rs) in
print("the request is \(rs.request)")//the request is https://jsonapi.com?name=xiaos
print("the request header is \(rs.request?.allHTTPHeaderFields)")//the request header is ["key1": "value1"]
switch rs.result {
case .success(let v):
print("this is com req \(v)")
case .failure(let e):
print("error is \(e)")
}
}
參數編碼的使用
URLEncoding.methodDependent
- 在GET HEAD DELETE中,將參數添加到url后面,拼接成query鍵值對
- 在POST中,將參數添加到請求體中
URLEncoding.queryString
- 在GET POST HEAD DELETE中,都是將參數添加到url后面,拼接成query鍵值對
URLEncoding.httpBody
- 在GET HEAD DELETE中無效
- 在POST中,將參數添加到請求體中
默認使用的.methodDependent適合大部分場景
SwiftyJSON的使用
datas.json
{
"list":[{
"id":"495450",
"type_id":"4",
"title":"你養我長大,我陪你變老……",
"link":"http://zhangjunliang.baijia.baidu.com/article/649503",
"summary":"時間都去哪兒了王錚亮 - 聽得到的時間當我們還在感嘆着時間都去哪兒了時間已經悄悄染白了父母...",
"addtime":"1476013530",
"arr":[1,2,3],
"dict":{"name":"xiao"}
},
{
"id":"495451",
"type_id":"4",
"title":"你養我長大,我陪你變老……",
"link":"http://zhangjunliang.baijia.baidu.com/article/649503",
"summary":"時間都去哪兒了王錚亮 - 聽得到的時間當我們還在感嘆着時間都去哪兒了時間已經悄悄染白了父母...",
"addtime":"1476013530",
"arr":[4,5,6],
"dict":{"name":"xiao1"}
},
{
"id":"495452",
"type_id":"4",
"title":"你養我長大,我陪你變老……",
"link":"http://zhangjunliang.baijia.baidu.com/article/649503",
"summary":"時間都去哪兒了王錚亮 - 聽得到的時間當我們還在感嘆着時間都去哪兒了時間已經悄悄染白了父母...",
"addtime":"1476013530",
"arr":[7,8,9],
"dict":{"name":"xiao2"}
}
]
}
model
import Foundation
import SwiftyJSON
class NewsModel {
var id:String?
var type_id:String?
var title:String?
var link:String?
var summary:String?
var addtime:String?
var arr:[Any]?
var dict:[String:Any]?
init(_ json:JSON) {
self.id = json["id"].string
self.type_id = json["type_id"].string
self.link = json["title"].string
self.summary = json["link"].string
self.addtime = json["addtime"].string
self.arr = json["arr"].array
self.dict = json["dict"].dictionary
}
}
轉換json數據為對象
let filePath = Bundle.main.path(forResource: "datas", ofType: "json")
if let jsonPath = filePath {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: jsonPath))
let dict = try JSONSerialization.jsonObject(with: data as Data, options: JSONSerialization.ReadingOptions.mutableLeaves)
if let list = JSON(dict)["list"].array {
//let newsModels:[NewsModel] = list.map(v in return NewsModel(v))
let newsModels:[NewsModel] = list.map({NewsModel($0)})
print(newsModels)//此處已經將json中的list數組轉換為newsModel對象數組
}
}
catch{
print(error)
}
}
轉換json的data
let jsonStr = "{\"name\":\"xiao\"}"
if let jsonData = jsonStr.data(using: .utf8, allowLossyConversion: false) {
let json = JSON(data: jsonData)
print(json["name"].string)//xiao?
}
PromiseKit與Alamofire的配合使用
//model
class Person {
var name:String?
init(_ json:JSON) {
self.name = json["name"].string
}
}
//handle data
//json1.json {"name":"xiaos1"}
firstly {
Alamofire.request("https://www.xsdota.com/json1.json").responseJSON()
}.then(on:DispatchQueue.global()) { (json) -> Promise<Person> in
let json = JSON(json)
return Promise(value:Person(json))
}.then { (person) -> Void in
print("person name is \(person.name)")
}.catch { (e) in
print(e)
}
func login(username:String,pwd:String) -> Promise<Person> {
let q = DispatchQueue.global()
UIApplication.shared.isNetworkActivityIndicatorVisible = true
let params = ["username":username,"pwd":pwd]
return
firstly {
Alamofire.request("https://www.xsdota.com/login.json",parameters:params).responseJSON()
}
.then(on: q) { json in
Person(JSON(json))
}
.always {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
firstly {
login(username: "xiaos", pwd: "123456")
}
.then { (person) -> Void in
print(person.name)
}
.catch { (e) in
switch e {
case Alamofire.AFError.responseSerializationFailed:
self.bn_showInfo(msg: "json解析失敗")
default:break
}
}
//when 多個異步任務全部處理完成后
let oneTask = Alamofire.request("https://www.xsdota.com/json3.json").responseJSON()
let twoTask = Alamofire.request("https://www.xsdota.com/json2.json").responseJSON()
when(fulfilled: [oneTask,twoTask])
.then { (rs) -> Void in
for result in rs {
print(result)
}
}.catch { (e) in
print(e)
}
//race 龜兔賽跑 誰先完成獲得誰的結果
race(oneTask,twoTask).then { (rs) -> Void in
print("龜兔賽跑 冠軍是 \(JSON(rs)["name"])")
}.catch { (e) in
print(e)
}
Promise與UIKit的配合
UIAlertController
let alert = PMKAlertController.init(title: "this is title", message: "this is msg", preferredStyle: .alert)
let one = alert.addActionWithTitle(title: "one")
let two = alert.addActionWithTitle(title: "two")
promise(alert)
.then { (action) -> Promise<Int> in
switch action {
case one:
return Promise(value:10)
case two:
return Promise(value:20)
default: throw BNError.msg
}
}
.then {num ->Void in
print("num is \(num)")
}.catch { (e) in
print(e)
}
現代的Swift
代碼風格指南
- 可讀性第一
- 文檔注釋第二
- 枚舉類型以大寫開頭的駝峰形式,函數和變量以小寫開頭的駝峰形式
- 使用類型接口
集合
集合
for-if簡寫
let datas = [1,2,3,4,5]
for i in datas {
if i == 2{
print(i) //2
}
}
for i in datas where i == 2 {
print(i) //2
}
Map方法
//獲得斐波那契數列的平方
//常規寫法
let fibs = [1,1,2,3,5,8]
var squared:[Int] = []
for fib in fibs {
squared.append(fib*fib)
}
//map寫法
let squared = fibs.map{fib in fib*fib}
//可以用map方法來完成的操作,一般就是新建一個數組容器,然后遍歷數據源,操作后把結果塞進容器中。諸如此類所有操作都可以用map代替
//map方法的實現
extension Array {
func map<U>(transform:Element->U) -> [U]{
var result:[U] = []
result.reserveCapacity(self.count)
for x in self {
result.append(transform(x))
}
return result
}
}
//Element是數組元素的占位符
Filter方法
fibs.filter{num in num%2 == 0}//獲得fibs數組中能被2整除的元素
//filter方法發實現
extension Array{
func filter (f:Element->Boll) -> [Element] {
var result:[Element] = []
for item in self where f(item) {
result.append(item)
}
return result
}
}
Reduce方法
var sum = 0
for num in fibs {
sum = sum + num
}
fibs.reduce(0){sum,num in sum+num}
//實現
extension Array {
func reduce<U>(var initial:U,f:(U,Element)->U) ->U {
for item in self {
initial = f(initial,item)
}
return initial
}
}
//可以理解函數式。不推薦使用,時間復雜度高
//使用reduce模擬map方法
extension Array {
func map2<U>(transform:Element->U) -> [U]{
return reduce([],f:{item1,item2 in item1 + [transform(item2)]})
}
}
//模擬filter方法
extension Array {
func filter2(f:Element->Bool) -> [Element] {
return reduce([],{item1,item2 in f(item2)?item+[item2]:item1})
}
}
flatMap方法
//flatMap鋪平的map方法
let suits = ["1", "2", "3", "4"]
let ranks = ["J", "Q", "K", "A"]
let allCombinations = suits.flatMap { suit in
ranks.map{ rank in
(suit, rank)
}
}