[Objective-C]關聯(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)

来源:http://www.cnblogs.com/Mr-Lin/archive/2016/08/10/5757844.html
-Advertisement-
Play Games

關聯 關聯是指把兩個對象相互關聯起來,使得其中的一個對象作為另外一個對象的一部分。 關聯特性只有在Mac OS X V10.6以及以後的版本上才是可用的。 在類的定義之外為類增加額外的存儲空間 使用關聯,我們可以不用修改類的定義而為其對象增加存儲空間。這在我們無法訪問到類的源碼的時候或者是考慮到二進 ...


關聯

    關聯是指把兩個對象相互關聯起來,使得其中的一個對象作為另外一個對象的一部分。
    關聯特性只有在Mac OS X V10.6以及以後的版本上才是可用的。

在類的定義之外為類增加額外的存儲空間

    使用關聯,我們可以不用修改類的定義而為其對象增加存儲空間。這在我們無法訪問到類的源碼的時候或者是考慮到二進位相容性的時候是非常有用。
    關聯是基於關鍵字的,因此,我們可以為任何對象增加任意多的關聯,每個都使用不同的關鍵字即可。關聯是可以保證被關聯的對象在關聯對象的整個生命周期都是可用的(在垃圾自動回收環境下也不會導致資源不可回收)。

創建關聯

    創建關聯要使用到Objective-C的運行時函數:objc_setAssociatedObject來把一個對象與另外一個對象進行關聯。該函數需要四個參數:源對象,關鍵字,關聯的對象和一個關聯策略。當然,此處的關鍵字和關聯策略是需要進一步討論的。
  ■  關鍵字是一個void類型的指針。每一個關聯的關鍵字必須是唯一的。通常都是會採用靜態變數來作為關鍵字。
  ■  關聯策略表明瞭相關的對象是通過賦值,保留引用還是複製的方式進行關聯的;還有這種關聯是原子的還是非原子的。這裡的關聯策略和聲明屬性時的很類似。這種關聯策略是通過使用預先定義好的常量來表示的。
    下麵的代碼展示瞭如何把一個字元串關聯到一個數組上。

static char overviewKey;  
NSArray * array =[[NSArray alloc] initWidthObjects:@"One", @"Two", @"Three", nil];  
//為了演示的目的,這裡使用initWithFormat:來確保字元串可以被銷毀  
NSString * overview = [[NSString alloc] initWithFormat:@"@",@"First three numbers"];  
objc_setAssociatedObject(array, &overviewKey, overview, OBJC_ASSOCIATION_RETAIN);  
  
[overview release];  
//(1) overview仍然是可用的  
  
[array release];  
//(2)overview 不可用  

   在(1)處,字元串overview仍然是可用的,這是因為OBJC_ASSOCIATION_RETAIN策略指明瞭數組要保有相關的對象。當數組array被銷毀的時候,也就是在(2)處overview也就會被釋放,因此而被銷毀。如果此時還想使用overview,例如想通過log來輸出overview的值,則會出現運行時異常。

獲取相關聯的對象

    獲取相關聯的對象時使用Objective-C函數objc_getAssociatedObject。接著上面列表7-1的代碼,我們可以使用如下代碼來獲取與array相關聯的字元串:

NSString * associatedObject = (NSString *)objc_getAssociatedObject(array, &oveviewKey);  

  

斷開關聯

    斷開關聯是使用objc_setAssociatedObject函數,傳入nil值即可。
    接著列表7-1中的程式,我們可以使用如下的代碼來斷開字元串overview和arry之間的關聯:

objc_setAssociatedObject(array, &overviewKey, nil, OBJC_ASSOCIATION_ASSIGN);  

   其中,被關聯的對象為nil,此時關聯策略也就無關緊要了。
    使用函數objc_removeAssociatedObjects可以斷開所有關聯。通常情況下不建議使用這個函數,因為他會斷開所有關聯。只有在需要把對象恢復到“原始狀態”的時候才會使用這個函數。

一個完整的實常式序

    下麵的程式綜合了前面的代碼.

#import <Foundation/Foundation.h>  
#import <objc/runtime.h>  
  
  
int main(int argc, const char* argv[])  
{  
    NSAutoreleasePool * pool = [[NSAutoreleasePool] alloc init];  
      
    static char overviewKey;  
    NSArray *array =[[NSArray alloc] initWidthObjects:@"One", @"Two", @"Three", nil];  
    //為了演示的目的,這裡使用initWithFormat:來確保字元串可以被銷毀  
    NSString * overview = [[NSString alloc] initWithFormat:@"@",@"First three numbers"];  
    objc_setAssociatedObject(array, &overviewKey, overview, OBJC_ASSOCIATION_RETAIN);  
    [overview release];  
      
    NSString *associatedObject = (NSString *)objc_getAssociatedObject(arrray, &overviewKey);  
    NSLog(@"associatedObject:%@", associatedObject);  
      
    objc_setAssociatedObject(array, &overviewKey, nil, OBJC_ASSOCIATION_ASSIGN);  
    [array release];  
      
    [pool drain];  
    return 0;  
}  

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 很多時候佈局中需要文字垂直居中,有個CSS屬性:vertical-align: middle;該屬性在table里用是有效果的,很多塊級元素沒反應。這裡有2個屬性可以模擬table,來讓vertical-align: middle屬性生效。 很簡單父級元素給固定寬高加上屬性display: tabl ...
  • 最近有學習了JavaScript,學習的過程中發現js對於前端工程師來說可以是最終要的一部分。 個人認為js就是一門語言,如果把前端比作一個人的身體,那麼html就是一個人的結構,css就是這個人長的樣子,那麼JS就是一個人的行為,不是說Html和css不重要,只是JS 相比較而言更難一點,而且可以 ...
  • 先看看勞動成果 佈局 左右各一半(col-md-6) 左側登錄框占左側一半的10/12 右側是登錄系統的註意事項 使用到的BootStrap元素 well 輸入框組(input-group) 按鈕(btn-success) well 輸入框組(input-group) 按鈕(btn-success) ...
  • AngularJS[1] 誕生於2009年,由Misko Hevery 等人創建,後為Google所收購。是一款優秀的前端JS框架,已經被用於Google的多款產品當中。AngularJS有著諸多特性,最為核心的是:MVVM、模塊化、自動化雙向數據綁定、語義化標簽、依賴註入等等。 AngularJs ...
  • jquery-slider是一款基於JSON格式數據的jQuery幻燈片插件。該幻燈片通過JSON數據來提供圖片地址和描述信息等,你可以通過更換JSON數據來動態切換不同的圖片。 線上預覽 源碼下載 使用方法 在頁面中引入jquery和slider.js文件和font-awesome字體圖標文件。 ...
  • 以下是datepicker的css文件和js代碼 ...
  • Android中使用網路訪問來載入網上的內容,並將其解析出來載入到控制項中,是一種很常見的操作。但是Android的UI線程(也就是主線程)中是不允許進行耗時操作的,因為耗時操作會阻塞主線程,影響用戶體驗。而訪問網路同樣是一個耗時操作,並且Android3.0以後是不允許在主線程中訪問網路的,所以我們 ...
  • 斷點續傳指的是在下載或上傳時,將下載或上傳任務(一個文件或一個壓縮包)人為的劃分為幾個部分,每一個部分採用一個線程進行上傳或下載,如果碰到網路故障,可以從已經上傳或下載的部分開始繼續上傳下載未完成的部分,而沒有必要從頭開始上傳下載。用戶可以節省時間,提高速度 使用多線程斷點續傳下載的時候,將下載或上 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...