@synthesize obj=_obj的意义详解 @property和@synthesize

本文详细解析了Objective-C中属性(property)、实例变量(ivar)的概念及其相互作用,特别是@synthesize指令的作用,帮助开发者理解如何正确地使用它们。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们在进行iOS开发时,经常会在类的声明部分看见类似于@synthesize window=_window; 的语句,那么,这个window是什么,_ window又是什么,两个东西分别怎么用,这是一个比较基本的问题,也关乎我们理解Objective-C中对类、类的属性、类的存取器、类的局部变量的统一理解。
在32位系统中,如果类的 @interface 部分没有进行 ivar 声明,但有 @property 声明,在类的 @implementation 部分有响应的 @synthesize,则会得到类似下面的编译错误:
Synthesized property 'xX' must either be named the same as a compatible ivar or must explicitly name an ivar
在 64-bit时,运行时系统会自动给类添加 ivar,添加的 ivar 以一个下划线"_"做前缀。
上面声明部分的 @synthesize window=_window; 意思是说,window 属性为 _window 实例变量合成访问器方法。
也就是说,window属性生成存取方法是setWindow,这个setWindow方法就是_window变量的存取方法,它操作的就是_window这个变量。通过这个看似是赋值的这样一个操作,我们可以在@synthesize 中定义与变量名不相同的getter和setter的命名,籍此来保护变量不会被不恰当的访问。

下面是一个常见的例子
写法一:
C代码  收藏代码

@interface MyClass:NSObject{   

        MyObjecct *_myObject; 

@property(nonamtic, retain) MyObjecct *myObject; 

@end 

 

@implementatin MyClass 

@synthesize myObject=_myObject; 


写法二:
C代码  收藏代码

@interface MyClass:NSObject{ 

       

@property(nonamtic, retain) MyObjecct *myObject; 

@end 

 

@implementatin MyClass 

@synthesize myObject=_myObject; 

这个类中声明了一个变量_myObject,又声明了一个属性叫myObject,然后用@synthesize生成了属性myObject的存取方法,这个存取方法的名字应该是:setmyObject和getmyObject。@synthesize myObject=_myObject的含义就是属性myObject的存取方法是做用于_myObject这个变量的。这种用法在Apple的Sample Code中很常见。
弄明白了这个语句的意思之后,我们也就清楚了myObject和_myObject的区别,那么,在使用的时候,有什么需要注意的地方,大家应该也都清楚了。是的,myObject是属性,而_ myObject才是变量,我们最终操作的变量都是myObject。
那么,同样是存取操作,语句
C代码  收藏代码

self.nameVarPtr = [[ObjectName alloc] init]  

C代码  收藏代码

nameVarPtr = [[ObjectName alloc] init] 

两种赋值方式的区别何在呢?

self.nameVarPtr=xxx 这种赋值方式等价于调用 [self setnameVarPtr:xxx], 而setnameVarPtr:xxx的方法的实现又是依赖于@property的属性的,比如retain,assign等属性。


nameVarPtr = xxx 的赋值方式,仅仅是对一个指针进行赋值。nameVarPtr仅仅是一个指针变量,记录了xxx的地址。在这个过程中不会调用setter方法,不会调用setter方法,就和@property没有关系,从而,也和retain,assign等属性没有关系。这种赋值方式就是一个简单的指针赋值。


综上,对成员变量进行赋值,为防内存泄露需要注意的点:

1.self调用setter方法的方式

ObjectName*  tmp= [[ObjectName alloc] init];

self.nameVarPtr =tmp;                 //retainCount=2

[tmp release];                               //retainCount=1


2.指针赋值方式,不会调用setter方法

nameVarPtr= [[ObjectName alloc] init]; // retainCount=1


所以,笔者建议大家在对某个变量进行赋值操作的时候,尽量要写self.myObj = xxx; 这才是最可靠的方法。

@property和@synthesize可以自动生成某个类成员变量的存取方法

readwrite:这个属性是默认的情况,会自动为你生成存取器

assign:这个属性一般用来处理基础类型,比如int、float等等,如果你声明的属性是基础类型的话,assign是默认的,你可以不加这个属性

natomic:默认是有该属性的,这个属性是为了保证程序在多线程情况,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题

readonly:只生成getter不会有setter方法

copy:这个会自动生成你赋值对象的克隆,相当于在内存中新生成了该对象的副本,这样一来,改变赋值对象就不会改变你声明的这个成员变量了

retain:会自动retain赋值对象

nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率

http://blog.youkuaiyun.com/beautifularea/article/details/6886604

assign:指定setter方法用简单的赋值,这是默认操作。你可以对标量类型(如int)使用这个属性。你可以想象一个float,它不是一个对象,所以它不能retain、copy。

assign:简单赋值,不更改索引计数(Reference Counting).使用assign: 对基础数据类型 (NSInteger)和C数据类型(int, float, double, char,等)

retain:指定retain应该在后面的对象上调用,前一个值发送一条release消息。你可以想象一个NSString实例,它是一个对象,而且你可能想要retain它。

retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 ,使用retain: 对其他NSObject和其子类 ,retain,是说明该属性在赋值的时候,先release之前的值,然后再赋新值给属性,引用再加1。

copy:指定应该使用对象的副本(深度复制),前一个值发送一条release消息。基本上像retain,但是没有增加引用计数,是分配一块新的内存来放置它。copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。copy:建立一个索引计数为1的对象,然后释放旧对象,copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。

readonly:将只生成getter方法而不生成setter方法(getter方法没有get前缀)

readwrite:默认属性,将生成不带额外参数的getter和setter方法(setter方法只有一个参数)

atomic:对于对象的默认属性,就是setter/getter生成的方法是一个原子操作。如果有多个线程同时调用setter的话,不会出现某一个线程执行setter全部语句之前,另一个线程开始执行setter的情况,相关于方法头尾加了锁一样。


nonatomic:不保证setter/getter的原子性,多线程情况下数据可能会有问题。nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。先释放原先变量,再将新变量     retain然后赋值;

      注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。

%% LED光谱合成与优化 - 修正版 % 中央民族大学数学建模竞赛 - 问题2解决方案 % 所有函数定义移至文件末尾 %% 初始化 clear; clc; close all; % 定义波长范围 (380-781nm) wavelengths = 380:1:781; % 402个波长点 % 五通道LED SPD (实际应从Excel导入) % 这里使用模拟数据代替 blue = zeros(402,1); green = zeros(402,1); red = zeros(402,1); ww = zeros(402,1); cw = zeros(402,1); % 创建模拟SPD数据 (高斯分布) for i = 1:402 wl = wavelengths(i); blue(i) = exp(-((wl-450)/20).^2); green(i) = exp(-((wl-540)/25).^2); red(i) = exp(-((wl-620)/15).^2); ww(i) = exp(-((wl-580)/80).^2); cw(i) = exp(-((wl-500)/100).^2); end % 归一化SPD blue = blue / max(blue); green = green / max(green); red = red / max(red); ww = ww / max(ww); cw = cw / max(cw); % 模拟CIE标准函数 cie_x = zeros(402,1); cie_y = zeros(402,1); cie_z = zeros(402,1); mel_sens = zeros(402,1); D65 = zeros(402,1); for i = 1:402 wl = wavelengths(i); cie_x(i) = exp(-((wl-600)/100).^2); cie_y(i) = exp(-((wl-550)/100).^2); cie_z(i) = exp(-((wl-450)/80).^2); mel_sens(i) = exp(-((wl-480)/40).^2); D65(i) = exp(-((wl-550)/150).^2); end %% 优化问题设置 % 边界条件 (权重在0-1之间) lb = [0, 0, 0, 0, 0]; ub = [1, 1, 1, 1, 1]; % 优化选项 options = optimoptions('fmincon', 'Display', 'iter', ... 'Algorithm', 'sqp', 'MaxFunctionEvaluations', 10000); % 初始权重 w0 = [0.2, 0.2, 0.2, 0.2, 0.2]; %% 求解日间照明模式 (最大化Rf) % 调用优化器 [w_opt_day, fval_day] = fmincon(... @(w) obj_func_day(w, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65), ... w0, [], [], [], [], lb, ub, ... @(w) constraints_day(w, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65), ... options); % 计算实际Rf值 spd_day = synthesize_spd(w_opt_day, blue, green, red, ww, cw); [~, rf_day] = calculate_rf_rg(spd_day, D65); rf_day = -fval_day; %% 求解夜间助眠模式 (最小化mel-DER) % 调用优化器 [w_opt_night, mel_der_night] = fmincon(... @(w) obj_func_night(w, blue, green, red, ww, cw, mel_sens, D65), ... w0, [], [], [], [], lb, ub, ... @(w) constraints_night(w, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65), ... options); %% 结果计算与展示 % 计算日间模式所有参数 spd_day = synthesize_spd(w_opt_day, blue, green, red, ww, cw); [X_day, Y_day, Z_day] = calculate_xyz(spd_day, cie_x, cie_y, cie_z); [cct_day, duv_day] = calculate_cct_duv(X_day, Y_day, Z_day); [rf_day, rg_day] = calculate_rf_rg(spd_day, D65); mel_der_day = calculate_mel_der(spd_day, mel_sens, D65); % 计算夜间模式所有参数 spd_night = synthesize_spd(w_opt_night, blue, green, red, ww, cw); [X_night, Y_night, Z_night] = calculate_xyz(spd_night, cie_x, cie_y, cie_z); [cct_night, duv_night] = calculate_cct_duv(X_night, Y_night, Z_night); [rf_night, rg_night] = calculate_rf_rg(spd_night, D65); mel_der_night = calculate_mel_der(spd_night, mel_sens, D65); % 显示结果 fprintf('\n===== 日间照明模式最优解 =====\n'); fprintf('权重: 蓝光=%.4f, 绿光=%.4f, 红光=%.4f\n', w_opt_day(1), w_opt_day(2), w_opt_day(3)); fprintf(' 暖白光=%.4f, 冷白光=%.4f\n', w_opt_day(4), w_opt_day(5)); fprintf('CCT: %.0f K, Duv: %.4f\n', cct_day, duv_day); fprintf('Rf: %.1f, Rg: %.1f\n', rf_day, rg_day); fprintf('mel-DER: %.3f\n\n', mel_der_day); fprintf('===== 夜间助眠模式最优解 =====\n'); fprintf('权重: 蓝光=%.4f, 绿光=%.4f, 红光=%.4f\n', w_opt_night(1), w_opt_night(2), w_opt_night(3)); fprintf(' 暖白光=%.4f, 冷白光=%.4f\n', w_opt_night(4), w_opt_night(5)); fprintf('CCT: %.0f K, Duv: %.4f\n', cct_night, duv_night); fprintf('Rf: %.1f, Rg: %.1f\n', rf_night, rg_night); fprintf('mel-DER: %.3f\n', mel_der_night); %% 光谱可视化 figure('Position', [100, 100, 1200, 500]); % 日间模式光谱 subplot(1, 2, 1); plot(wavelengths, spd_day/max(spd_day), 'b', 'LineWidth', 2); hold on; plot(wavelengths, mel_sens/max(mel_sens), 'g--', 'LineWidth', 1.5); title('日间照明模式光谱'); xlabel('波长 (nm)'); ylabel('归一化强度'); legend('合成光谱', '视黑素灵敏度', 'Location', 'northeast'); grid on; xlim([380, 780]); % 夜间模式光谱 subplot(1, 2, 2); plot(wavelengths, spd_night/max(spd_night), 'r', 'LineWidth', 2); hold on; plot(wavelengths, mel_sens/max(mel_sens), 'g--', 'LineWidth', 1.5); title('夜间助眠模式光谱'); xlabel('波长 (nm)'); ylabel('归一化强度'); legend('合成光谱', '视黑素灵敏度', 'Location', 'northeast'); grid on; xlim([380, 780]); %% 权重分布图 figure(); labels = {'蓝光', '绿光', '红光', '暖白光', '冷白光'}; subplot(1, 2, 1); bar(w_opt_day); set(gca, 'XTickLabel', labels); title('日间模式权重分布'); ylabel('权重系数'); ylim([0, 1]); subplot(1, 2, 2); bar(w_opt_night); set(gca, 'XTickLabel', labels); title('夜间模式权重分布'); ylabel('权重系数'); ylim([0, 1]); %% ==================== 函数定义区域 ==================== % 以下为所有函数定义,确保位于文件末尾 function spd = synthesize_spd(weights, blue, green, red, ww, cw) % 合成五通道光谱 w_b = weights(1); w_g = weights(2); w_r = weights(3); w_ww = weights(4); w_cw = weights(5); spd = w_b*blue + w_g*green + w_r*red + w_ww*ww + w_cw*cw; end function [X, Y, Z] = calculate_xyz(spd, cie_x, cie_y, cie_z) % 计算CIE XYZ三刺激值 X = sum(spd .* cie_x); Y = sum(spd .* cie_y); Z = sum(spd .* cie_z); end function [cct, duv] = calculate_cct_duv(X, Y, Z) % 计算相关色温(CCT)Duv % 转换到CIE 1960 UCS空间 u = 4*X / (X + 15*Y + 3*Z); v = 6*Y / (X + 15*Y + 3*Z); % 简化计算 - 实际应使用普朗克轨迹插值 % 这里使用近似公式 n = (X - 0.3320*Y - 0.0038*Z) / (0.0037*Y - 0.0011*Z); cct = 437*n^3 + 3601*n^2 + 6861*n + 5517; duv = sqrt((u - 0.2)^2 + (v - 0.3)^2); % 示例计算 end function [rf, rg] = calculate_rf_rg(spd, ref_spd) % 简化版显色指数计算 % 这里使用色差模拟 diff = mean(abs(spd - ref_spd)); rf = 90 - 15*diff; % Rf在75-95之间 rg = 95 - 10*diff; % Rg在85-105之间 end function mel_der = calculate_mel_der(spd, mel_sens, D65) % 计算褪黑素日光效率比 mel_flux = sum(spd .* mel_sens); d65_mel = sum(D65 .* mel_sens); mel_der = mel_flux / d65_mel; end function f = obj_func_day(weights, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65) % 日间模式目标函数:最大化Rf spd = synthesize_spd(weights, blue, green, red, ww, cw); rf = calculate_rf_rg(spd, D65); f = -rf; % 最大化Rf = 最小化 -Rf end function [c, ceq] = constraints_day(weights, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65) % 日间模式约束条件 spd = synthesize_spd(weights, blue, green, red, ww, cw); [X, Y, Z] = calculate_xyz(spd, cie_x, cie_y, cie_z); [cct, ~] = calculate_cct_duv(X, Y, Z); [rf, rg] = calculate_rf_rg(spd, D65); % 约束条件: % CCT在5500-6500K, Rg在95-105 c1 = 5500 - cct; % cct >= 5500 c2 = cct - 6500; % cct <= 6500 c3 = 95 - rg; % rg >= 95 c4 = rg - 105; % rg <= 105 ceq = []; % 无等式约束 c = [c1; c2; c3; c4]; % 非线性不等式约束 (需要c<=0) end function f = obj_func_night(weights, blue, green, red, ww, cw, mel_sens, D65) % 夜间模式目标函数:最小化mel-DER spd = synthesize_spd(weights, blue, green, red, ww, cw); f = calculate_mel_der(spd, mel_sens, D65); end function [c, ceq] = constraints_night(weights, blue, green, red, ww, cw, cie_x, cie_y, cie_z, D65) % 夜间模式约束条件 spd = synthesize_spd(weights, blue, green, red, ww, cw); [X, Y, Z] = calculate_xyz(spd, cie_x, cie_y, cie_z); [cct, ~] = calculate_cct_duv(X, Y, Z); [rf, ~] = calculate_rf_rg(spd, D65); % 约束条件: % CCT在2500-3500K, Rf>=80 c1 = 2500 - cct; % cct >= 2500 c2 = cct - 3500; % cct <= 3500 c3 = 80 - rf; % rf >= 80 ceq = []; % 无等式约束 c = [c1; c2; c3]; % 非线性不等式约束 (需要c<=0) end 上述代码哪些位置可以加入真实数据,请详细列举出来,并且给我加入真实数据的方法
最新发布
08-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值