多路委托中的 Nonretain Object:CFArrayCreateMutable

在某些需求下,我們需要建立一個(gè)多路委托協(xié)議,以滿足多處的回調(diào)。比如,一個(gè)網(wǎng)絡(luò)請求數(shù)據(jù)回來,需要通知多個(gè)對象使用。實(shí)現(xiàn)方案其實(shí)很簡單,就是把簡單的代理調(diào)用,變更成一個(gè)代理數(shù)組,在回調(diào)時(shí),遍歷數(shù)組發(fā)送消息即可。

但是要注意,代理是可以被外部釋放的,所以除了我們必須要判斷:

    if (self.delegate && [self.delegate respondsToSelector:<#(SEL)#>]) {
            ...
    }

之外,針對多路代理,我們還要對這個(gè)數(shù)組做一個(gè)特殊處理。

我們知道,數(shù)組可以會使對象的引用計(jì)數(shù)增加的。為了保持我們 多路代理數(shù)組 不會印象其內(nèi)元素的引用計(jì)數(shù),我們需要使用 CFArrayCreateMutable 來創(chuàng)建一個(gè) 不會增加引用計(jì)數(shù)的 數(shù)組。

下面直接就是 Nonretaining Array/Dictionary/Set 的代碼了:

NSMutableArray * PDCreateNonRetainingMutableArray()
{
    return (__bridge_transfer NSMutableArray *)CFArrayCreateMutable(nil, 0, nil);
}

NSMutableDictionary *PDCreateNonRetainingMutableDictionary()
{
    return (__bridge_transfer NSMutableDictionary *)CFDictionaryCreateMutable(nil, 0, nil, nil);
}

NSMutableSet *PDCreateNonRetainingMutableSet()
{
    return (__bridge_transfer NSMutableSet *)CFSetCreateMutable(nil, 0, nil);
}

方法是 C 函數(shù),當(dāng)然你也可以封裝成 OC 的函數(shù),純屬個(gè)人喜好。
看到這里,應(yīng)該知道,把這個(gè) 丟到你們對應(yīng)的類別中 就可以愉快使用了,當(dāng)然丟代碼里也行,反正我會不接你的鍋。

測試用例:

    NSObject *obj = [NSObject new];
    NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)obj));

    NSMutableArray *array = @[].mutableCopy;
    [array addObject:obj];
    NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)obj));

    NSMutableArray *nonretainingArray = PDCreateNonRetainingMutableArray();
    [nonretainingArray addObject:obj];
    NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)obj));

結(jié)果:

Retain count is 1
Retain count is 2
Retain count is 2

完美。

7月4日更新:

看到有人提到了 NSPointerArray ,這里也就寫上來,為何我沒有使用 NSPointerArray。

讓我們瞅一眼 NSPointerArray 的使用

NSPointerArray *array = [NSPointerArray weakObjectsPointerArray];
[array addPointer:(__bridge void *)obj];

這貨跟上面一樣丑。那么使用起來,肯定會進(jìn)行一輪的封裝。
讓我們再看看性能:性能檢查的宏實(shí)現(xiàn)在這里

以下為性能測試

寫入測試(每 10^2 次寫入為一組參考值,重復(fù) 10^5 次取平均值):

- (void)measure
{
    NSObject *obj = [NSObject new];

    PDMeasure(@"NSMutableArray 寫入速度", {
        NSMutableArray *mutableArray = @[].mutableCopy;
        for (int i = 0; i < 100; i++)
        {
            [mutableArray addObject:obj];
        }
    })
    
    PDMeasure(@"NSNonretainingMutableArray 寫入速度", {
        NSMutableArray *nonretainingArray = PDCreateNonRetainingMutableArray();
        for (int i = 0; i < 100; i++)
        {
            [nonretainingArray addObject:obj];
        }
    })


    PDMeasure(@"NSPointerArray 寫入速度", {
        NSPointerArray *pointerArray = [NSPointerArray weakObjectsPointerArray];
        for (int i = 0; i < 100; i++)
        {
            [pointerArray addPointer:(__bridge void *)obj];
        }
    })
}

測試結(jié)果輸出:

[P] <ViewController|NSMutableArray 寫入速度> The average runtime for operation is 10479 ns.
[P] <ViewController|NSNonretainingMutableArray 寫入速度> The average runtime for operation is 4822 ns.
[P] <ViewController|NSPointerArray 寫入速度> The average runtime for operation is 40685 ns.

讀取速度幾乎相同,這里就不貼代碼和結(jié)果了。

以上為性能測試

測試結(jié)果是:
寫入速度 CFArray 實(shí)現(xiàn)的 NonRetainMutableArray 比 NSMutableArray 快約 2 倍,比 NSPointerArray 快約 10 倍。
讀取速度幾乎相同。

既然都封裝后再使用的,就選個(gè)性能好的吧。

以上。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,825評論 25 709
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,516評論 19 139
  • 先看示例圖 提前聲明:這個(gè)demo是仿照之前某個(gè)人用Objective-C寫的示例,點(diǎn)擊圓圈手指效果是用的一個(gè)第三...
    船長_閱讀 1,442評論 0 5
  • 一場涼意初乍的雨 順著朱紅色的瓦礫 濡濕了檐下的竊竊私語 一片暑氣未歇的語 逆著鳳凰木的孤寂 捂暖了檐下的怯怯絲雨...
    斐炎涼閱讀 287評論 15 11
  • 營銷調(diào)研課,幫一間新興的英德茶葉公司做策劃。 英德紅茶好有名,在國內(nèi)都是響當(dāng)當(dāng)?shù)拿?但這間公司走的是高端品牌路線...
    麥提爽閱讀 255評論 0 0

友情鏈接更多精彩內(nèi)容