Swift4.0 擴(kuò)展協(xié)議

在OC里面中耻姥,Category大家一定不陌生,他可以很好的為我們服務(wù)有咨,給指定的類實(shí)現(xiàn)系統(tǒng)不提供的方法琐簇。


  • 例子可能不恰當(dāng),無關(guān)緊要座享,重點(diǎn)不是OC

比如要實(shí)現(xiàn):把Data轉(zhuǎn)化為一個UInt8的數(shù)組
我們可能會這樣子寫

UInt8 *bytes = (UInt8 *)data.bytes;

現(xiàn)在我們不想像上面那個樣子婉商,強(qiáng)制類型轉(zhuǎn)換,直接就是UInt8的數(shù)組渣叛,我們就可以創(chuàng)建一個Category丈秩,然后實(shí)現(xiàn)方法

.h 
- (UInt8 *)toUInt8;

.m
- (UInt8 *)toUInt8{
   return (UInt8 *)data.bytes;
}

實(shí)現(xiàn)了上面的方法之后,到需要的地方引入頭文件就可以實(shí)現(xiàn)這樣子調(diào)用

UInt8 *bytes = data.toUInt8;

這樣子淳衙,我們就可以在實(shí)現(xiàn)了對NSData這個類的擴(kuò)展蘑秽,并且是無污染的,拖到任何一個工程就可以使用(當(dāng)然箫攀,例子中的命名方式不是很靠譜肠牲,這里忽略,重點(diǎn)不是他)靴跛。


現(xiàn)在來到Swift中缀雳,如果我們也要實(shí)現(xiàn)如上的功能,我們可以使用Extension梢睛,也可以很方便的完成它肥印。

新建一個Swift文件,然后實(shí)現(xiàn)如下代碼:

extension Data {
    func toUInt8() -> [UInt8]{
        var bytes: [UInt8] = [UInt8](repeating: 0, count: count)
        copyBytes(to: &bytes, count: count)
        return bytes
    }
}

調(diào)用如下:

let data = Data(bytes: [0,1,2,3,4,5,6,7,8])
print(data.toUInt8())

打印結(jié)果:
[0, 1, 2, 3, 4, 5, 6, 7, 8]



假設(shè)你現(xiàn)在這個代碼就寫完啦绝葡,也沒有問題,可以達(dá)到預(yù)想的效果了竖独,然后新來的了一個工程師,然后他也需要把Data轉(zhuǎn)化為[UInt8]挤牛,但是代碼是你寫的莹痢,他并不知道啊。

  • 第一種情況 于是乎他又寫了一個方法UInt8墓赴,實(shí)現(xiàn)的功能和你的一樣竞膳,這樣子就會有兩個功能一樣,只是命名方式不一樣的方法了诫硕。
  • 第二種情況 他也寫了一個和你命名方式一樣的方法,但是他也新建了一個文件坦辟,然后你們兩個方法就沖突了,他就很納悶章办,黑人問號锉走?滨彻??,然后就是一頓查找……
    然后就是隨著你的需求增加挪蹭,你添加的方法越來越多亭饵,當(dāng)你去了另外一家公司,你的這些成果本來是想著拖進(jìn)去就用梁厉,但是卻有了耦合辜羊,這豈不是很尷尬?



所以在Swift有了一種更優(yōu)雅的擴(kuò)展方法:協(xié)議擴(kuò)展



接下來用一個Demo去實(shí)現(xiàn)它词顾,看看他到底有多爽0送骸!H忭铩昔驱!

正題開始啦!I先獭舍悯!




1、 布局UI睡雇,并且他事件拖入到ViewController
image.png
2萌衬、新建一個Swift文件 PQDataEncodable.swift

這里需要注意的是:
Swift標(biāo)準(zhǔn)庫為我們提供了55中協(xié)議,他們的命名方式有著自己規(guī)則它抱,基本是以“Type”秕豫、“able'”、“Convertible”結(jié)尾观蓄,分別代表了“可以被當(dāng)做XX類型”混移、“具備某種能力或特性”、“能夠進(jìn)行改變或者變換”侮穿。所以在命名的時候應(yīng)該盡可能遵守這一套規(guī)則歌径,便于開發(fā)人員之間的高校合作。

image.png

3亲茅、創(chuàng)建一個協(xié)議回铛,實(shí)現(xiàn)它。
  • 3.1 創(chuàng)建一個協(xié)議先:
protocol PQDataEncodable {
    /// 關(guān)聯(lián)類型
    associatedtype WarpperType
    /// 這個就是命名克锣,我這里使用pq茵肃,你可以使用你的,比如:SnapKit袭祟,他的就是 view.snp.XXXX
    var pq: WarpperType { get }
}
  • 3.2 創(chuàng)建一個結(jié)構(gòu)體验残,繼承協(xié)議
struct ExtensionPQDataEncodable<T>: PQDataEncodable {
    /// T 泛型
    let pq: T
    /// 構(gòu)造方法
    init(pq: T) {
        self.pq = pq
    }
}
  • 3.3 很重要的一環(huán)來了,為自己的協(xié)議添加默認(rèn)實(shí)現(xiàn)方法
/// 這里指定 WrapperType 是 Data巾乳,所以在 PQDataEncodable 中的 pq 就是 Data 類型了
extension PQDataEncodable where WarpperType == Data {
    /// 方法名 返回參數(shù)
    func toUInt8() -> [UInt8]{
        /// 根據(jù)數(shù)組長度您没,創(chuàng)建數(shù)組
        var bytes = [UInt8](repeating: 0, count: pq.count)
        /// 把 Data 的 Bytes 拷貝到 數(shù)組中
        pq.copyBytes(to: &bytes, count: pq.count)
        /// 返回數(shù)組
        return bytes
    }
    
    func toHex() -> String {
        /// 創(chuàng)建一個字符串
        var hex: String = ""
        /// 遍歷數(shù)組鸟召,在轉(zhuǎn)換為16進(jìn)制添加到字符串中
        for i in 0..<toUInt8().count {
            hex.append(NSString(format: "%02x", pq[i]) as String)
            /// 長度為4就添加一個空格, 格式化字符串
            if (i + 1) % 4 == 0 { hex.append(" ") }
        }
        /// 返回字符串
        return hex
    }
}
  • 3.4 最后一步就是氨鹏,在Data中添加一個結(jié)構(gòu)體欧募,由于這個結(jié)構(gòu)體是繼承我自己的協(xié)議的,所以就擁有了我協(xié)議里面默認(rèn)的實(shí)現(xiàn)方法喻犁。
extension Data {
    var pq: ExtensionPQDataEncodable<Data> {
        return ExtensionPQDataEncodable(pq: self)
    }
}




然后我們就可以在ViewController中這樣子調(diào)用了

class ViewController: UIViewController {
    
    let data = Data(bytes: [0x2,0x33,0x54,0x78,0x1,0x2d,0x3a,0x5b])

    @IBAction func toHexBtnClick(_ sender: Any) {
        print(data.pq.toHex())
    }
    @IBAction func toUInt8BtnClick(_ sender: Any) {
        print(data.pq.toUInt8())
    }
    @IBAction func redBtnClick(_ sender: Any) {
    }
    @IBAction func greenBtnClick(_ sender: Any) {
    }
    @IBAction func blueBtnClick(_ sender: Any) {
    }
}

輸出結(jié)果如下:

02335478 012d3a5b 012d3a5b 012d3a5b 
[2, 51, 84, 120, 1, 45, 58, 91, 1, 45, 58, 91, 1, 45, 58, 91]


這樣子整個逼格就提高啦槽片,但是你可能會有疑問何缓,為什么要新建一個結(jié)構(gòu)體呢肢础??碌廓?

我們在UIView的時候不是可以直接指定么传轰?
例如下面的寫法:

import UIKit

protocol TEST where Self : UIView {
    
}

然后我們就嘗試的這樣子寫:

protocol TEST where Self : Data {
    
}
error

我們進(jìn)入UIView,看看他的定義

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusItem, CALayerDelegate>

在進(jìn)入Data谷婆,看看他的定會

public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessCollection, MutableCollection, RangeReplaceableCollection

一個是Class慨蛙、一個是Struct,所以我們需要一個Struct來繼承協(xié)議纪挎,不可以直接對原有的struct進(jìn)行處理期贫。
剛才分析到Class就可以這樣子搞,那么也就是說這個Struct也可以是一個Class异袄,然后我們就來實(shí)驗(yàn)一下通砍。

4、新建一個協(xié)議 PQColorable.swift然后實(shí)現(xiàn)如下代碼
/// 新建一個協(xié)議
protocol PQColorable {
    /// 關(guān)聯(lián)類型
    associatedtype WarpperType
    var pq: WarpperType { get }
}

/// 定義一個類
final class ExtensionPQColorable<T>: PQColorable {
    /// 泛型
    let pq: T
    /// 構(gòu)造方法
    init(pq: T) {
        self.pq = pq
    }
}

/// 為協(xié)議實(shí)現(xiàn)默認(rèn)方法
extension PQColorable where WarpperType == UIColor{
    /// 獲取紅色
    func red() -> CGFloat {
        var value: CGFloat = 0
        pq.getRed(&value, green: nil, blue: nil, alpha: nil)
        return value
    }
    /// 獲取綠色
    func green() -> CGFloat {
        var value: CGFloat = 0
        pq.getRed(nil, green: &value, blue: nil, alpha: nil)
        return value
    }
    /// 獲取藍(lán)色
    func blue() -> CGFloat {
        var value: CGFloat = 0
        pq.getRed(nil, green: nil, blue: &value, alpha: nil)
        return value
    }
}


extension UIColor{
    var pq: ExtensionPQColorable<UIColor>{
        return ExtensionPQColorable(pq: self)
    }
}



最后我們就可以在ViewController中調(diào)用啦

class ViewController: UIViewController {
    
    let data = Data(bytes: [0x2,0x33,0x54,0x78,0x1,0x2d,0x3a,0x5b,0x1,0x2d,0x3a,0x5b,0x1,0x2d,0x3a,0x5b])
    let color = #colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)

    @IBAction func toHexBtnClick(_ sender: Any) {
        print(data.pq.toHex())
    }
    @IBAction func toUInt8BtnClick(_ sender: Any) {
        print(data.pq.toUInt8())
    }
    @IBAction func redBtnClick(_ sender: Any) {
        print(color.pq.red())
    }
    @IBAction func greenBtnClick(_ sender: Any) {
        print(color.pq.green())
    }
    @IBAction func blueBtnClick(_ sender: Any) {
        print(color.pq.blue())
    }
}

打印結(jié)果如下:

02335478 012d3a5b 012d3a5b 012d3a5b 
[2, 51, 84, 120, 1, 45, 58, 91, 1, 45, 58, 91, 1, 45, 58, 91]
0.745098054409027
0.156862750649452
0.0745098069310188

OK烤蜕,到這里應(yīng)該就會如何去裝逼了封孙,使命已經(jīng)達(dá)成。撤讽营!


別走虎忌,留下DEMO

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市橱鹏,隨后出現(xiàn)的幾起案子膜蠢,更是在濱河造成了極大的恐慌,老刑警劉巖莉兰,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狡蝶,死亡現(xiàn)場離奇詭異,居然都是意外死亡贮勃,警方通過查閱死者的電腦和手機(jī)贪惹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寂嘉,“玉大人奏瞬,你說我怎么就攤上這事枫绅。” “怎么了硼端?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵并淋,是天一觀的道長。 經(jīng)常有香客問我珍昨,道長县耽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任镣典,我火速辦了婚禮兔毙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘兄春。我一直安慰自己澎剥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布赶舆。 她就那樣靜靜地躺著哑姚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芜茵。 梳的紋絲不亂的頭發(fā)上叙量,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機(jī)與錄音九串,去河邊找鬼绞佩。 笑死,一個胖子當(dāng)著我的面吹牛蒸辆,可吹牛的內(nèi)容都是我干的征炼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼躬贡,長吁一口氣:“原來是場噩夢啊……” “哼谆奥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拂玻,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤酸些,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后檐蚜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體魄懂,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年闯第,在試婚紗的時候發(fā)現(xiàn)自己被綠了市栗。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖填帽,靈堂內(nèi)的尸體忽然破棺而出蛛淋,到底是詐尸還是另有隱情,我是刑警寧澤篡腌,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布褐荷,位于F島的核電站,受9級特大地震影響嘹悼,放射性物質(zhì)發(fā)生泄漏叛甫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一杨伙、第九天 我趴在偏房一處隱蔽的房頂上張望其监。 院中可真熱鬧,春花似錦缀台、人聲如沸棠赛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鼎俘,卻和暖如春哲身,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贸伐。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工勘天, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捉邢。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓脯丝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親伏伐。 傳聞我的和親對象是個殘疾皇子宠进,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件藐翎、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,121評論 4 61
  • 136.泛型 泛型代碼讓你可以寫出靈活,可重用的函數(shù)和類型,它們可以使用任何類型,受你定義的需求的約束材蹬。你可以寫出...
    無灃閱讀 1,476評論 0 4
  • 今天和同事堤器,突然聊到了用手機(jī)刷公交車的問題,先暫且記錄一下這個想法末贾,改天過來繼續(xù)補(bǔ)充細(xì)節(jié)
    Vicky_HMLiu閱讀 218評論 0 0
  • 記開遠(yuǎn)市法律援助中心對周邊清塘子村21家村民援助實(shí)情 2017年3月初,冬的晨露未散辉川,所里有些稀稀冷掂为,急碎的腳步聲...
    一然夢飛閱讀 313評論 0 1
  • 死亡陰影籠罩的望族 維特根斯坦家族是真正的名門望族,歷史悠久資產(chǎn)雄厚员串。祖父是一位富有的猶太羊毛商勇哗。娶了維也納銀行家...
    麥麥sky閱讀 2,027評論 1 3