屬性關鍵字

屬性關鍵字

  • 深拷貝與淺拷貝
    • 類型
    • 各類對象深淺拷貝判斷
    • 完全深拷貝的實現
  • 屬性關鍵字
    • @property、@synthesize和@dynamic
    • 原子操作
    • 讀寫權限
    • 內存管理
    • strong 🆚 copy
  • 總結

深拷貝與淺拷貝

先前學習OC時已經對深淺拷貝進行了一次學習,這里進行一個復習總結和補充,具體參照博客深拷貝與淺拷貝。

類型

OC對象的拷貝形式分為深拷貝、淺拷貝,其中深拷貝又細分為單層深拷貝和完全深拷貝。

  • 淺拷貝:指針拷貝,復制新指針與原指針存到同一塊內存區域。
  • 深拷貝:內容拷貝,將數據拷貝到一塊新的內存區域,新指針指向新區域。
    • 單層深拷貝:副本對象本身是深拷貝,其里面所有對象是淺拷貝。(例如容器類數組對象本身是深拷貝,數組元素是淺拷貝)
    • 完全深拷貝:無論副本對象本身還是里面對象元素都是深拷貝。

各類對象深淺拷貝判斷

  • 可變對象(非容器類、容器類)的copy和mutableCopy都為深拷貝。
  • 不可變對象(非容器類、容器類)的copy為淺拷貝,mutableCopy為深拷貝。
  • 自定義對象的copy和mutableCopy都為深拷貝。

無論容器類對象還是非容器類對象,都屬于系統類,xCode會自動幫我們實現好copyWithZone:mutableCopyWithZone:方法。然而自定義類的這兩個方法需要我們自己手動實現。

@implementation Person- (id)copyWithZone:(NSZone *)zone {Person *copy = [[[self class] allocWithZone:zone] init];copy.name = [self.name copy];copy.age = self.age;return copy;
}- (id)mutableCopyWithZone:(NSZone *)zone {Person *copy = [[[self class] allocWithZone:zone] init];copy.name = [self.name mutableCopy];copy.age = self.age;return copy;
}@end

從上述的方法實現中我們可以看出,無論是copy還是mutableCopy,這里都init出一個新的對象,開辟了一個新內存,與原對象不在一個內存地址,這就是深拷貝。

完全深拷貝的實現

在之前的博客中對完全深拷貝的實現沒有過多講解,這里具體總結一下從單層深拷貝轉換為為完全深拷貝的兩種方法。

  • 歸檔和解檔

這種方法的重點在于實現encodeWithCoder:initWithCoder:方法。對于系統自帶類來說,自動實現了這兩個方法,可以直接歸檔和解檔。相反,自定義類的歸檔和解檔的關鍵就是遵守NSSecureCoding 協議實現以下方法:

#import "Person.h"@implementation Person//支持安全編碼
+(BOOL)supportsSecureCoding {return YES;
}//將對象轉化為二進制
- (void)encodeWithCoder:(nonnull NSCoder *)coder {[coder encodeObject:self.name forKey:@"name"];
}//二進制還原對象
- (instancetype)initWithCoder:(nonnull NSCoder *)coder {if (self = [super init]) {self.name = [coder decodeObjectOfClass:[NSString class] forKey:@"name"];}return self;
}@end
#import <Foundation/Foundation.h>
#import "Person.h"int main(int argc, const char * argv[]) {@autoreleasepool {Person *person = [[Person alloc] init];person.name = @"Alice";NSLog(@"%p---%@", person, person.name);//歸檔,將對象封裝進二進制容器NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person requiringSecureCoding:YES error:nil];//解檔Person *copyPerson = [NSKeyedUnarchiver unarchivedObjectOfClass:[Person class] fromData:data error:nil];NSLog(@"%p---%@", copyPerson, copyPerson.name);person.name = @"Bob";NSLog(@"%p---%@", person, person.name);NSLog(@"%p---%@", copyPerson, copyPerson.name);}return 0;
}

運行結果:

在這里插入圖片描述

從運行結果可以看出,通過解檔歸檔,得到了一個新對象,新建了一塊內存地址,內容相同但地址不同,因此是深拷貝。并且,修改原始對象不改變解檔對象,二者彼此獨立,所以copyPerson依然是原來的值,這也說明實現了深拷貝。

  • 使用initWithXxx: copyItems:YES方法

該方法只能實現一層深拷貝,因此只有當容器類對象中的對象是自定義類對象或者可變對象時,可以實現完全深拷貝。很好理解,因為自定義類對象和可變對象的拷貝都是深拷貝,因此使用該方法再實現一層深拷貝就實現了完全深拷貝。

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) {@autoreleasepool {NSMutableString *str1 = [NSMutableString stringWithString:@"Alice"];NSMutableString *str2 = [NSMutableString stringWithString:@"Bob"];NSArray *arr = @[str1, str2];NSArray *copyArr = [[NSArray alloc] initWithArray:arr copyItems:YES];NSLog(@"%@---%p", arr, arr);NSLog(@"%@---%p", copyArr, copyArr);NSLog(@"%@---%p", str1, str1);NSLog(@"%@---%p", copyArr[0], copyArr[0]);[str1 appendString:@"Tom"];NSLog(@"%@---%p", str1, str1);NSLog(@"%@---%p", copyArr[0], copyArr[0]);}return 0;
}

運行結果:

在這里插入圖片描述

從運行結果可以看出,通過這種方法只復制了內容,但地址不同,并且對原對象的修改不會影響copyArr對象的內容。

值得注意的是:如果不是上述所說的容器類對象中的對象是自定義類對象或者可變對象時,使用該方法實現的是單層深拷貝。

屬性關鍵字

  1. 屬性的本質是 ivar(實例變量)+getter(getter方法)+setter(setter方法)。
  2. 屬性的修飾符應該按照順序排列:原子操作、讀寫權限、內存管理

@property、@synthesize和@dynamic

ivar+getter+setter的組合方式使得代碼臃腫,因此使用@property、@synthesize和@dynamic來實現屬性自動合成存取方法。

  • @property:用于封裝對象中的數據,自動生成屬性的setter與getter方法的聲明。
  • @synthesize:自動生成setter和getter方法。
  • @dynamic:告訴編譯器不自動進行@synthesize,而是程序員手動實現setter和getter方法。

注意??:

  • 如果重寫setter和getter方法,編譯器就不會自動為@property生成@synthesize,需要手動添加。
  • 如果在協議里使用@property聲明一個屬性,那么在某個類中遵循這個協議時,@synthesize需要手動添加同時生成實例變量和setter和getter方法。
#import <Foundation/Foundation.h>@protocol Demand <NSObject>-(void)testDemand;
@property(nonatomic, strong) NSString *name;@end@interface Person : NSObject<NSSecureCoding>@end#import "Person.h"@implementation Person@synthesize name = _name;-(void)testDemand {NSLog(@"屬性關鍵字");
}

原子操作

屬性是否具有原子性可以理解為線程是否安全。

同步鎖:在多線程環境中,當多個線程同時訪問或修改同一對象時,會導致程序崩潰等結果。同步鎖則是一種用于確保在給定時間內只有一個線程可以執行某特定代碼而保證線程安全的機制。

  • atomic:原子性,加同步鎖,但也不一定保證線程安全,且會損耗性能。
  • nonatomic:非原子性,不加同步鎖,使用這個可以提高訪問性能,代碼中常用nonatomic修飾屬性。

讀寫權限

  • readwrite:默認,生成setter和getter方法。
  • readonly:只生成getter方法。

內存管理

  • assign:
    • 既可以修飾基本數據類型(NSInteger、BOOL、int、float 等),也可以修飾對象類型。

      ps:如果使用assign修飾OC對象,對象銷毀時可能會產生懸垂指針,從而出現程序崩潰,因此最好assign只用來修飾基本數據類型。

    • 一般對于基本數據類型,setter方法的實現可以是直接賦值。
    • 修飾對象類型時,不增加引用計數。
    • 修飾delegate 在MRC使用assign.
    • 會產生懸垂指針,assign修飾的對象在被釋放后,指針仍然指向原對象地址,也就是說如果assign修飾的對象被釋放后,仍通過該指針訪問原對象的話,程序可能崩潰。

      懸垂指針:指針所指的內存已經被釋放(對象已被銷毀),但指針本身仍然存在,并繼續指向那塊現在已經無效的內存地址。

  • weak:
    • 只能修飾對象類型(只能修飾OC對象,如UIButton、UIView等)。
    • ARC下才能使用。

      ARC: 是一種編譯器特性,它*編譯時自動為你插入適當的內存管理代碼(retain, release, autorelease),而不是像傳統手動引用計數(MRC)那樣需要開發者自己寫這些代碼。

    • 修飾弱引用,不增加引用計數,用于避免循環利用。
    • weak 修飾的對象在被釋放之后,會自動將指針置為 nil,不會產生懸垂指針。
    • 對于有必要進行 remove 的視圖可以使用 weak,remove 之后會自動置為 nil。
    • 修飾delegate 在ARC使用weak。
  • unsafe_unretained:
    • 既可以修飾基本數據類型,也可以修飾對象類型。
    • MRC 下經常使用,ARC 下基本不用。
    • 修飾弱引用,同 weak,但性能更好,同時使用要求高,因為會產生懸垂指針。
  • retain:
    • MRC下使用。
    • 修飾強引用,將指針原來指向的舊對象釋放掉,然后指向新對象,同時新對象的引用計數加1。
    • setter 方法的實現是 release 舊值,retain 新值,用于OC對象類型。

strong 🆚 copy

  • strong:
    • ARC 下才能使用。
    • 原理同 retain,但在修飾 block 時,strong 相當于 copy,而 retain 相當于 assign。
    • 淺拷貝
  • copy:
    • setter 方法的實現是 release 舊值,copy 新值。一般用于 block、NSString、NSArray、NSDictionary 等類型。
    • copy設置的屬性會復制傳入的對象,而不是僅僅保持對傳入對象的引用,用于確保屬性擁有自己的獨立副本,使得避免不經意的更改。
  • 區別:
    • 屬性聲明使用copy修飾,則合成方法使用類的copy方法,生成一個對象的不可變副本。
    • strong修飾的的對象的賦值是多個指針指向同一個地址,而copy對象的賦值是每次在內存中開辟一個新內存地址,指針指向不同的地址。
@interface Person : NSObject<NSSecureCoding>@property(nonatomic, strong) NSString *strStrong;
@property(nonatomic, copy) NSString *strCopy;
@property(nonatomic, strong) NSMutableString *mutablestrStrong;
@property(nonatomic, copy) NSMutableString *mutablestrCopy;-(void)testDemo;@end-(void)testDemo {NSMutableString *str = [NSMutableString stringWithString:@"Hello"];NSLog(@"%@---%p", str, str);self.strStrong = str;NSLog(@"%@---%p", self.strStrong, self.strStrong);self.strCopy = str;NSLog(@"%@---%p", self.strCopy, self.strCopy);self.mutablestrStrong = str;NSLog(@"%@---%p", self.mutablestrStrong, self.mutablestrStrong);self.mutablestrCopy = str;NSLog(@"%@---%p", self.mutablestrCopy, self.mutablestrCopy);[str appendString:@" iOS"];NSLog(@"%@---%p", self.strStrong, self.strStrong);NSLog(@"%@---%p", self.strCopy, self.strCopy);NSLog(@"%@---%p", self.mutablestrStrong, self.mutablestrStrong);NSLog(@"%@---%p", self.mutablestrCopy, self.mutablestrCopy);
}

運行結果:

在這里插入圖片描述

從運行結果看的出,正如我們的結論所說,strong修飾的賦值指向同一個地址(淺拷貝),copy修飾的賦值指向新的地址(深拷貝)。因此,當原值改變時,strong修飾的對象的指針還指向原內存,因此值隨之改變,而copy的不會改變。

因此,對于copy修飾的對象,為確保對象中的字符串值不會無意改動,應該在賦值前拷貝一份。

總結

屬性關鍵字的知識還有很多,后續學習后會完善補充。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98053.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98053.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98053.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

突發奇想,還未實踐,在Vben5的Antd模式下,將表單從「JS 配置化」改寫成「模板可視化」形式(豆包版)

在 Vben5 的 Antd 模式下&#xff0c;完全可以將表單從「JS 配置化」改寫成「模板可視化」形式&#xff0c;把表單項直接寫在 Vue 模板中&#xff0c;更直觀且符合傳統 Vue 開發習慣。以下是完整的改寫示例&#xff0c;保留原功能但結構更清晰&#xff1a; 改寫思路 放棄 JS 中…

【更新完畢】2025數學建模國賽E題思路代碼文章高教社杯全國大學生數學建模-AI 輔助智能體測

全部更新完畢 包含完整的文章全部問題的代碼、結果、圖表 完整內容請看文末最后的推廣群基于AI姿態識別的立定跳遠運動分析與個性化訓練優化研究 隨著《國家學生體質健康標準》的頒布實施&#xff0c;通過AI技術輔助體育運動分析已成為提升學生體質健康水平的重要手段。本研究針…

小白友好,無需基礎也能快速上手的AI部署工具,一鍵部署

AI大模型相信已經成為許多人工作和生活中的得力助手。然而&#xff0c;對于大多數普通用戶而言&#xff0c;將強大的AI模型部署到自己的電腦上&#xff0c;似乎是一項遙不可及的技術活&#xff0c;往往涉及到復雜的命令行操作、環境配置和代碼調試。那有沒有一種工具&#xff0…

《Python復刻植物大戰僵尸開源項目實戰:Pygame框架+JSON關卡設計,解鎖塔防游戲開發新技能》?

&#x1f4cc; 大家好&#xff0c;我是智界工具庫&#xff0c;每天分享好用實用且智能的開源項目&#xff0c;以及在JAVA語言開發中遇到的問題&#xff0c;如果本篇文章對您有所幫助&#xff0c;請幫我點個小贊小收藏小關注吧&#xff0c;謝謝喲&#xff01;&#x1f618; 博主…

CCS——將工程中的 include / lib 修改為相對路徑,方便工程分享

在使用 Code Composer Studio (CCS) 開發 DSP 或 ARM 工程時&#xff0c;經常會遇到這樣一個問題&#xff1a;在 A 電腦上能正常編譯的工程&#xff0c;拷貝到 B 電腦上后就報錯。錯誤的原因通常是 工程使用了絕對路徑&#xff0c;而不同電腦上的文件路徑不一致&#xff0c;比如…

java解析網絡大端、小端解析方法

文章目錄一、背景介紹二、說明核心概念&#xff1a;什么是字節序&#xff08;Endianness&#xff09;&#xff1f;大端字節序 (Big-Endian)小端字節序 (Little-Endian)三、不同解析方式介紹一、背景介紹 中轉臺通過SNMP協議V1\V2上報中轉臺IP&#xff0c;然后程序解析入庫&…

【數據分享】土地利用矢量shp數據分享-甘肅

今天要說明數據就是土地利用shp數據分享-甘肅。數據介紹▲ 1km土地利用數據&#xff08;2020年&#xff09;▲ 土地利用數據&#xff08;2025年&#xff09;▲土地利用數據&#xff08;2018年&#xff09;▲ 30m土地利用數據&#xff08;2023年&#xff09;▲ 公路鐵路道路河流…

java log相關:Log4J、Log4J2、LogBack,SLF4J

目錄測試maven依賴logback.xml測試主程序測試輸出arthas查看logger總結使用參考文檔測試 maven依賴 <dependencies><!-- SLF4J API --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>…

AES加密算法詳細加密步驟代碼實現--身份證號碼加解密系統

系統概述 本系統是一個基于AES-256-CBC加密算法的身份證號碼加解密工具&#xff08;手搓底層步驟&#xff09;&#xff0c;針對的是上一篇文章對的AES加密原理的講解&#xff0c;雖說是演示&#xff0c;但功能完善&#xff0c;可單獨提供接口給項目調用&#xff0c;采用Python…

LangChain: Models, Prompts 模型和提示詞

獲取openapikey #!pip install python-dotenv #!pip install openai import osimport openai ? from dotenv import load_dotenv, find_dotenv _ load_dotenv(find_dotenv()) # read local .env file openai.api_key os.environ[OPENAI_API_KEY] # account for deprecat…

ACMESSL自動續簽教程

目錄 1、選擇申請證書 ?編輯2、選擇CA機構 ?編輯3、選擇自動驗簽 ?編輯4、證書續簽設置 5、自動發布設置 本教程實現ACMESSL自動續簽&#xff0c;請按照此教程實現。 1、選擇申請證書 點擊快捷入口或者訂單或證書列表中的【創建證書】按鈕&#xff1a; 2、選擇CA機構 …

基于飛算JavaAI的在線圖書借閱平臺設計實現

項目概述與需求分析 1.1 項目背景與意義 隨著數字化時代的快速發展&#xff0c;傳統圖書館管理模式已無法滿足現代讀者的需求。在線圖書借閱平臺通過互聯網技術將圖書資源數字化&#xff0c;為讀者提供便捷的檢索、借閱和管理服務&#xff0c;有效解決了傳統圖書館開放時間有…

通過API接口管理企業微信通訊錄案例

1.開始前需要登錄企業微信管理員后臺&#xff0c;開啟通訊錄同步&#xff0c;同時添加企業可信IP地址&#xff0c;記錄下Secret信息和企業ID&#xff0c;后面的程序會用到這兩個參數。2.下面是用python寫的創建企業微信賬號的具體案例。#!/usr/bin/env python3 # -*- coding: u…

硬件開發_基于物聯網的自動售賣機系統

一.系統概述 物聯網自動售賣機系統的主要功能如下&#xff1a; 核心控制器&#xff1a;采用STM32單片機作為系統核心&#xff0c;負責整體數據處理和各設備的統一控制。商品選擇&#xff1a;支持語音識別及按鍵方式&#xff0c;方便用戶在售賣機內選擇商品。語音播報&#xff1…

AGENTS.md: AI編碼代理的開放標準

每個項目都有一個 README.md 文件供人類閱讀。但隨著 AI 編碼代理和 AI 輔助開發的興起,我們需要一個新標準:AGENTS.md。這個 Markdown 文件定義了代理如何構建、測試和協作。 這就是 AGENTS.md 的作用。 它是一個簡單的 Markdown 文件,告訴 AI 助手如何在你的項目中操作:…

如何解決 OutOfMemoryError 內存溢出 —— 原因、定位與解決方案

網羅開發&#xff08;小紅書、快手、視頻號同名&#xff09;大家好&#xff0c;我是 展菲&#xff0c;目前在上市企業從事人工智能項目研發管理工作&#xff0c;平時熱衷于分享各種編程領域的軟硬技能知識以及前沿技術&#xff0c;包括iOS、前端、Harmony OS、Java、Python等方…

阿里云服務器配置ssl-docker nginx

# 切換到您當前的目錄 cd /AAAAAAAAAAAA# 創建存放nginx配置、證書和日志的目錄結構 mkdir -p nginx-config/conf.d nginx-ssl nginx-logs# 為掛載做準備&#xff0c;您可能需要將當前dist目錄內容移動到新的html目錄 # 首先查看當前dist目錄的內容 ls -la dist/# 如果html目錄…

2025全球生成式引擎優化(GEO)服務商發展趨勢與企業賦能白皮書

引言&#xff1a;人工智能技術的迅猛發展&#xff0c;特別是在生成式AI領域的突破&#xff0c;正以前所未有的力量重塑商業世界的競爭格局。對于尋求提升在線可見性、優化品牌互動及實現可持續增長的企業而言&#xff0c;生成式引擎優化&#xff08;GEO&#xff09;已然成為數字…

海康威視工業相機SDK開發實戰:使用C/C++實現軟件觸發圖像采集(含詳細中文注釋代碼)

一、前言 在機器視覺、自動化檢測、智能制造等領域&#xff0c;工業相機是獲取圖像數據的核心設備。海康威視作為國內領先的機器視覺廠商&#xff0c;其工業相機產品線豐富&#xff0c;廣泛應用于各類工業場景。 本文將帶你從零開始&#xff0c;使用 海康MVS SDK&#xff08;Ma…

Modbus RTU 協議介紹

Modbus RTU 協議介紹 異步串行傳輸方式&#xff0c;采用二進制格式&#xff0c;適用于串行通訊&#xff08;如RS-485&#xff09;&#xff0c;效率高&#xff0c;是工業現場的主流選擇。 主站是Master&#xff0c;從站是Slave。 Modbus RTU 協議格式 幀結構 地址碼&#xf…