访问实例变量的语法? 目标C

如何解决访问实例变量的语法? 目标C

| 在Objective-C中访问实例变量的正确语法是什么? 假设我们有这个变量:
@interface thisInterface : UIViewController {
    NSMutableString *aString;
}

@property (nonatomic,retain) NSMutableString *aString;
并且它是合成的。 当我们要访问它时,我们首先要分配和初始化它。在Objective-C中编程大约一个月以来,我已经看到了两种不同形式的语法。我见过人们只是简单地做
aString = [[NSMutableString alloc] initWithString:@\"hi\"]
,他们就这样分配字符串。我还看到人们以ѭ2开始,然后开始初始化他们的ivar。我想我只是想弄清楚初始化实例变量的最正确方法是什么,因为在前面的示例中,我从中收到了EXC_BAD_ACCESS错误。在加上“ 3”之后,它没有出现。 如果这是一个重复的问题,请原谅我,但是在阅读了有关SO的一些帖子后,这使我感到好奇。我正在尝试使用Objective-C学习正确的语法,因为我更喜欢适当而不是草率。     

解决方法

        如果您声明了一个属性并在.m文件中将其“ 4”表示,则只需按如下所示进行设置:
self.aString = @\"hi\"; // or [[NSMutableString alloc] initWithString:@\"hi\"];
使用
self.varName
可以利用属性声明的实际作用,它可以处理新值的保留(因为属性具有
retain
属性),为您释放旧值等。 如果您只是这样做:
aString = someValue;
...您可能正在泄漏
aString
中的原始值,因为不使用
self.aString
便是直接通过属性访问变量。     ,        注意
self->varName
self.varName
之间的区别 首先是指针访问。第二个是属性访问。 为什么这么重要?指针访问是直接的。另一方面,财产使用权则利用了吸气剂和吸气剂(不论是否为
@synthesized
)。此外,为方便起见,@synthesized访问器会为您处理内存管理(即,使用
self.varName = ...;
时),而ѭ15only只会执行其所声明的内容,即赋值->(这里有EXC_BAD_ACCESS错误的解释,您可能会得到)。 从语法上讲,两种形式都是正确的。如果您想更好地传达意图,请在直接使用指针时使用ѭ11,而在要使用
@property
便利时使用ѭ6。     ,        这是所有可能的组合(我认为) 仅当
aString
属性具有
retain
属性时,OK和BAD才正确:
@property (nonatomic,retain) NSMutableString *aString;
所以: 1个
aString = [[NSMutableString alloc] init]; //OK: 
可以,但是仅在aString未指向无效对象的情况下,否则您将丢失对该对象的引用,并且它将泄漏,因为您将无法到达该对象以释放它。 2
aString = [NSMutableString string]; //BAD
不好,因为您假设要保留aString(如您那样声明),而不是保留它,将来肯定会得到EXC_BAD_ACCESS 3
aString = [[NSMutableString string] retain]; //OK
与第一种方法相同,只有在aString未指向有效对象的情况下才有用。但是,我将使用第一个。 4
aString = [[[NSMutableString alloc] init] autorelease];//BAD
与第二种方法相同。 5
self.aString = [[NSMutableString alloc] init]; //BAD!!
不好,因为您将其保留了两次,因此将导致内存泄漏 6
self.aString = [[NSMutableString string]; //******GOOD!******
这可能是最安全的。它将由属性设置器保留,并且由于您使用的是设置器,因此可能会适当释放aString可能指向的任何其他对象。 7
self.aString = [[NSMutableString string] retain]; //BAD
这将保留两次。 8
self.aString = [[[NSMutableString alloc] init] autorelease];//Ok
这也可以,但是我将使用便捷方法代替这种长方法:) 请注意,如果您知道自己在做什么,那么#1和#3选项就非常好。实际上,我比#6更频繁地使用它们     ,        我个人更喜欢使用
self.
语法。它只是使确定它的实例变量变得容易,而不仅仅是确定当前范围内的其他变量(当耗尽其NSAutoreleasePool时将丢失的变量)。但是,同时使用这两种方法是正确的,并且如果您收到EXC_BAD_ACCESS错误,则不是因为您未使用
self.
进行了访问。正确地说,您必须分配它,并且无论选择哪种方式访问​​变量,都必须使其保持一致,否则您将收到错误。 我希望这有帮助。     ,除
init
dealloc
和配件本身外,请始终使用配件。这样做将为您节省很多麻烦,就像您描述的那样。另外,为您的个人名字命名与您的财产不同的名称(
_foo
foo_
mFoo
,而不是
foo
)。
self.foo
与ѭ39precisely完全相同。我将方法称为“ 37”。
self.foo = x
[self setFoo:x]
完全相同。它调用方法“ 43”。如果您将属性ѭ37synthesized合成为
retain
变量,则该内容类似于:
@synthesize foo = foo_;

- (void)setFoo:(id)value {
  [value retain];
  [foo_ release];
  foo_ = value;
}
这样可以正确释放
foo_
的旧值,分配一个新值并保留它。
foo = x
(假设
foo
是一个ivar)不调用任何方法。没有。它只是将
x
中的指针值赋给
foo
中的指针。如果ѭ37指向保留的内容,则表示已泄漏。如果您分配的新值未保留,您将在以后崩溃。 解决方案是始终使用访问器。     ,        要么 使用点语法(在某些情况下)更干净,并且可以编译为等效语法。即
self.iVar
[self iVar]
相同,
self.iVar = aValue
[self setIVar:aValue];
相同     ,        
self.aString
是to58ѭ的语法糖。合成属性只需创建
-aString
-setAString:
方法(取决于您选择的属性,而不是普通的影响)。 现在的问题是是否使用ѭ61表示法。我建议您不要使用它。 为什么?首先要知道Objective-C只是对C的补充。这意味着每个有效的C代码也是有效的Objective-C代码。 现在看看他们用点符号表示了什么。最后一条语句不再成立。您将不会区分对C结构字段的访问和发送Objective-C方法。 因此,请不要使用点符号。优先使用[self ..]。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-