swift作為蘋果的小兒子,在3.0之前的版本感覺一直不太成熟,所以只是簡單的學(xué)習(xí)了一下进肯,現(xiàn)在到了3.0之后,感覺已經(jīng)好了很多棉磨;swift大勢所趨江掩,作為一個(gè)ioser 還是很有必要掌握的!本文介紹了一些swift下常用的第三方庫乘瓤,文章結(jié)尾會(huì)附帶demo环形,有需要的小伙伴可以自行下載查閱!
1. Alamofire
swift下最常用的網(wǎng)絡(luò)請求框架
- 先定義幾個(gè)參數(shù)
let url = "https://baidu.com"
let param = ["id": device_id] as [String : Any]
- 然后來個(gè)最簡單的調(diào)用
Alamofire.request(url)
這樣就完成了一個(gè)最簡單的網(wǎng)絡(luò)請求衙傀,系統(tǒng)默認(rèn)是get方法抬吟,我知道你怎么想的,請求的響應(yīng)呢统抬?客官莫急火本,后面我們會(huì)講到。
帶參數(shù)的調(diào)用
Alamofire.request(urlBase + urlHomeCategraies, parameters: parame)
想用post 怎么辦
/// - Parameters:
/// - url: 請求地址
/// - method: 請求方法 .put .post .get ...
/// - encoding: 歸檔方式聪建,一般默認(rèn)就夠用了
/// - headers: 請求頭钙畔,不多說
Alamofire.request(url, method: .post, parameters: parame, encoding: JSONEncoding.default, headers: nil)
以上幾個(gè)方法基本能夠完成大部分的網(wǎng)絡(luò)請求了,接下來就是請求完成后的操作金麸!
- response
Alamofire.request(urlBase).response { (response) in
}
返回?cái)?shù)據(jù)類型為json的response
Alamofire.request(urlBase).responseJSON{ (response) in
}
如果你的網(wǎng)址和參數(shù)都沒錯(cuò)的話擎析,這里的response就包含了你所需要的所有數(shù)據(jù)了。另外這里有個(gè)小坑需要注意一下:請求中的參數(shù)是不能用方法的挥下,否則會(huì)報(bào)錯(cuò)揍魂,就像這樣
Alamofire.request(url(urlHomeList)).responseJSON{ (response) in
}
func url(_ subUrl:String) -> String {
return urlBase + subUrl;
}
上面這個(gè)方法會(huì)爆請求參數(shù)錯(cuò)誤桨醋,原因:在請求參數(shù)中的url需要遵循協(xié)議URLConvertible,當(dāng)你傳入的參數(shù)可以轉(zhuǎn)換為URL時(shí)時(shí)沒有問題的现斋,但是這里我們傳入的是函數(shù)喜最,無法轉(zhuǎn)換為URL,所以會(huì)報(bào)錯(cuò)步责!
- response
請求結(jié)束后就是拿我們需要的數(shù)據(jù)了
if let dataValue = response.result.value{
}
這里對response.result.value進(jìn)行解包后的dataValue就是我們請求成功后的data 數(shù)據(jù)了,然后就是數(shù)據(jù)解析了禀苦,請轉(zhuǎn)第二部分蔓肯!
- .validate方法
Alamofire.request(url).validate(statusCode: 200...300)
這里參數(shù)是個(gè) sequence,表示網(wǎng)絡(luò)請求返回的狀態(tài)振乏,各位可以根據(jù)需要來添加蔗包,個(gè)人感覺這個(gè)方法有點(diǎn)雞肋!
2. SwiftyJSON
swift下json解析工具慧邮,這里我們主要和Alamofire配合使用解析拿到的數(shù)據(jù)
Alamofire.request(url).responseJSON { response in
switch response.result {
case .success(let value):
let json = JSON(value)
print("JSON: \(json)")
case .failure(let error):
print(error)
}
}
這個(gè)是Github的例子调限,其中最主要的一句是這句
let json = JSON(value)
如果返回?cái)?shù)據(jù)是data類型的,也可以這樣寫
let rootDic = JSON.init(data: value as! Data)
上面這兩句代碼等同于
if let rootDic = try? JSONSerialization.jsonObject(with: value, options: .allowFragments) as? [[String: Any]],
}
拿到字典或數(shù)組后就可以對其進(jìn)行進(jìn)一步處理误澳,像這樣
/// 可選型的 json 數(shù)據(jù)
let dataDic = rootDic["data"].dictionary
/// 非可選型的 json 數(shù)據(jù)
let dataDic = rootDic["data"].dictionaryValue
/// 可選型的 Any 數(shù)據(jù)類型
let dataDic = rootDic["data"].dictionaryObject
/// Array耻矮,String等其他類型都和字典一樣有三個(gè)方法,可以根據(jù)需要來調(diào)用
let dataArr = dataDic["datalist"].arrayObject
另外我們也可以一步到位忆谓,將解包的操作全權(quán)交給工具來做
let dataArr = rootDic["data"]["datalist"].arrayObject
拿到數(shù)組以后就可以進(jìn)行數(shù)據(jù)轉(zhuǎn)模型的操作了裆装,數(shù)據(jù)轉(zhuǎn)模型沒什么好說的,有需要的可以在文件結(jié)尾中的demo中查看倡缠,接下來就是數(shù)據(jù)展示了哨免!要展示數(shù)據(jù),那自然要用到UI布局昙沦,請看第三部分!
3. SnapKit
swift下自動(dòng)布局工具琢唾,雖然蘋果一直在推崇使用storyboard,但是鑒于其種種弊端盾饮,個(gè)人還是偏向于純代碼方式采桃,SnapKit就是swift下的純代碼布局框架,類似于OC中的Masonry丘损,如果會(huì)使用Masonry芍碧,SnapKit也很容易上手。
self.view.addSubview(box)
box.snp.makeConstraints { (make) -> Void in
make.width.height.equalTo(50)
make.center.equalTo(self.view)
}
首先需要把子視圖添加到父視圖上才能夠進(jìn)行布局号俐,否則crash
上面這個(gè)是GitHub上的例子泌豆,表示視圖寬高相等都等于50,視圖中心等同于父視圖吏饿。當(dāng)你有多個(gè)約束條件相同的時(shí)候踪危,都可以想上面那樣連起來蔬浙!
view.snp_makeConstraints { (make) in
make.edges.equalTo(self.view).inset(UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20))
}
最常用的方法
view1.snp_makeConstraints { (make) in
make.top.equalTo(self.view).offset(20)
make.left.equalTo(self.view).offset(30)
/// 距self.view的右邊30(右邊數(shù)字前要加減號,不然會(huì)變成超出右邊30)
make.right.equalTo(self.view).offset(-30)
///距self.view的下邊50(下邊數(shù)字前要加減號,不然會(huì)變成超出下邊50)
make.bottom.equalTo(self.view).offset(-50)
}
這幾個(gè)方法基本就夠用了,你也可以參考SnapKit自動(dòng)布局使用詳解進(jìn)一步學(xué)習(xí)贞远!
4.FDTemplateLayoutCell / DGTemplateLayoutCell
優(yōu)雅的cell高度計(jì)算工具(優(yōu)雅在何處畴博,看我),對于cell高度的計(jì)算一直是個(gè)很頭大的問題蓝仲,較常用的方法是在model中計(jì)算出cell的高度直接賦值俱病,但是并不很優(yōu)雅,OC中的SDAutoLayout 一行代碼搞定自動(dòng)布局就是一個(gè)結(jié)合自動(dòng)布局與cell高度計(jì)算的第三方框架袱结!而在swift中尚未找到亮隙,也可能是我out了,所以這里我使用了FDTemplateLayoutCell(以下簡稱FD) 結(jié)合 SnapKit一起使用垢夹,同樣能夠優(yōu)雅的實(shí)現(xiàn)cell高度計(jì)算溢吻!
FD中一共提供了三個(gè)計(jì)算高度的方法,如下
- method1
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// 不帶緩存計(jì)算高度
return tableView.fd_heightForCell(with: "cell") { (cell) in
// Configure this cell with data, same as what you've done in "-tableView:cellForRowAtIndexPath:"
// Like:
// cell.data = datas[indexPath.row]
}
}
- method2
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// 通過indexPath緩存高度
return tableView.fd_heightForCell(with: "cell", cacheBy: indexPath) { (cell) in
// Configure this cell with data, same as what you've done in "-tableView:cellForRowAtIndexPath:"
// Like:
// cell.data = datas[indexPath.row]
}
}
- method3
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// 通過identifer來緩存高度
return tableView.fd_heightForCell(with: "cell", cacheByKey: entity.identifier ?? "") { (cell) in
// Configure this cell with data, same as what you've done in "-tableView:cellForRowAtIndexPath:"
// Like:
// cell.data = datas[indexPath.row]
}
}
它們的使用分為兩種
- 使用StoryBoard 或者Xib自動(dòng)布局
在自定義cell中
cell.fd_usingFrameLayout = false // 默認(rèn)就是false果元,所以不設(shè)置也是可以的
在tableview中調(diào)用上述任一方法即可促王,值得注意的是在設(shè)置約束時(shí)需要對cell.contentView的上下左右均有關(guān)聯(lián)才能算成功的!否則而晒,我也不知道會(huì)出現(xiàn)什么情況蝇狼,由于我在StroyBoard和Xib略菜,所以很遺憾不能給各位提供demo倡怎,大家可以自己研究一下题翰!
- 使用Frame
我使用的是SnapKit布局,實(shí)際上也可以算Frame诈胜,如果是第一次用的話豹障,感覺真的好坑啊焦匈!
第一步:在cell中添加這句代碼血公,告訴機(jī)器,我要用frame了缓熟,給我準(zhǔn)備好
self.fd_usingFrameLayout = true
第二部:添加視圖累魔,進(jìn)行布局,哇咔咔够滑,F(xiàn)D有個(gè)神奇的功能垦写,那就是自動(dòng)計(jì)算視圖的高度,不管你是label文字高度彰触,還是ImageView的比例縮放梯投,只要添加合適的約束,它都可以給你實(shí)現(xiàn),老板再也不用當(dāng)心我敲代碼了!
__在lable中:__
titleLabel.snp.makeConstraints { (make) in
make.left.top.equalTo(10)
make.right.equalTo(-10)
}
像這樣不需要設(shè)置titleLabel的高度分蓖,只需要設(shè)置左右和上方的約束尔艇,在添加text后即可自動(dòng)返回高度,是不是很爽懊春住终娃!
__在ImageView中:記得要設(shè)置imageView.contentMode__
imageView.snp.makeConstraints { (make) in
make.left.equalTo(titleLabel)
make.top.equalTo(titleLabel.snp.bottom).offset(10)
make.width.equalTo(imageWidth)
}
這樣結(jié)合第三步就可以計(jì)算出cell的高度了
第三步:在cell中覆寫 sizeThatFits 方法
override func sizeThatFits(_ size: CGSize) -> CGSize {
var totalHeight:CGFloat = 0
totalHeight += titleLabel.sizeThatFits(size).height // 需要幫我計(jì)算出title的高度使用這個(gè)方法
totalHeight += 75 // 自定義高度,不需要計(jì)算蒸甜,直接+
totalHeight += 30 // margin
return CGSize.init(width: size.width, height: totalHeight)
}
覆寫這個(gè)方法的目的就是為了返回cell的高度
第四步:在tableView中調(diào)用上述三種方法之一棠耕,不用翻回去看了
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// 通過indexPath緩存高度
return tableView.fd_heightForCell(with: "cell", cacheBy: indexPath) { (cell) in
// 在這里進(jìn)行cell 賦值操作,和在方法 cellForRowAtIndexPath 中一樣
}
}
接下來commond+R 就是見證奇跡的時(shí)刻柠新!如果第一次沒有達(dá)到你想要的效果窍荧,可以在tableView中打開debug來查看日志
self.tableView.fd_debugLogEnabled = true // default is false
5. Kingfisher
swift下加載圖片工具
這個(gè)工具和OC中的SDWebimage 使用方法非常相似
testView.kf.setImage(with: URL.init(string: url), for: UIControlState.normal)
testView.kf.setImage(with: URL.init(string: url), for: UIControlState.normal, placeholder: nil, options: nil, progressBlock: { (receivedSize, totalSize) in
/// receivedSize 接受到的數(shù)據(jù)大小
/// totalSize 數(shù)據(jù)總的大小
}) { (catchImage, error, catchType, url) in
/// catchImage 緩存到的image
/// error 錯(cuò)誤
/// catchType 枚舉類型
/// url 緩存地址
}
這里的testView 可以是ImageView 也可以是Button,在button中還有設(shè)置背景圖片的方法
testView.kf.setBackgroundImage(with: URL.init(string: url), for: UIControlState.normal)
testView.kf.setBackgroundImage(with: URL.init(string: url), for: UIControlState.normal, placeholder: nil, options: nil, progressBlock: { (receivedSize, totalSize) in
}) { (catchImage, error, catchType, url) in
}
這里如果你的圖片顯示不出來登颓,十有八九是你的圖片地址有問題搅荞,多檢查一下
6. 福利來啦
- 個(gè)人寫的一個(gè)小Demo红氯,目前還在完善中框咙,另外感謝Swift開源項(xiàng)目-模仿今日頭條,在學(xué)習(xí)過程中有很大幫助痢甘!
- Demo2喇嘱,這個(gè)采用的是MVVM設(shè)計(jì)模式,使用用了RxSwift塞栅,有興趣的小伙伴可以參考一下者铜!
** 覺得本文有用的小伙伴,可以動(dòng)動(dòng)小手給個(gè)贊放椰,有問題的請留言作烟,只要我看到了就會(huì)回復(fù),另外本文還會(huì)不斷的更新完善**