简体   繁体   English

Objective-C中的属性

[英]Property in Objective-C

Line 1: First.h
Line 2: @property (nonatomic, retain) NSString *name;

Line  3: First.m
Line  4: @synthesize name;
Line  5: -(void)viewDidLoad()
Line  6: {
Line  7:     name = [NSString stringWithString:@"Hello"];
Line  8:                          OR
Line  9:     self.name = [[NSString alloc]initWithString:@"Hello"]; 
Line 10:                          OR
Line 11:  }
Line 12:-(void)dealloc()
Line 13: {
Line 14: [name release];
Line 14: } 

Question 1: 问题1:
If I follow line number 7 everything is fine and if I used line number 9 Memory leakage is there. 如果遵循第7行,则一切正常,如果使用第9行,则存在内存泄漏。 As I know self is point to current object and if I used self.object or simply object no more difference. 据我所知,self是指向当前对象的,如果我使用self.object或只是object不再有任何区别。

Question 2: And if I used 问题2:如果我用过

@synthesize name = _name;

Then which one is for setting the value of name and which one is for get the value? 那么,哪个用于设置name的值,哪个用于获取name的值? Difference between: 之间的区别:

name = [NSString stringWithString:@"Hello"];
            OR
self.name = [NSString stringWithString:@"Hello"];
            OR
_name = [NSString stringWithString:@"Hello"];

Question 3: 问题3:
If I create any property is there any need to alloc in the memory as I allocated showing the memory leakage? 如果我创建任何属性,那么在分配显示内存泄漏时是否有必要在内存中分配内存?

To respond the first question : you get the leak because initializing the string with the alloc method you are retaining the object created but you don't release the object after, so you get the leak, while creating the string with the stringWithString you get an autoreleased object that is released automatically by the autorelease pool. 要回答第一个问题 :之所以泄漏,是因为使用alloc方法初始化字符串时,您将保留创建的对象,但是之后不释放该对象,因此会泄漏,而使用stringWithString创建字符串时,会得到一个由自动释放池自动释放的自动释放对象。 Note that in your example at line 9 you are initializing the object and passing it to the setter of the property, things would have been different if you have used the ivar ... 请注意,在第9行的示例中,您正在初始化对象并将其传递给属性的setter,如果使用了ivar,情况将会有所不同。

To respond your second question : you are synthesizing the property name and associating it to the internal variable(ivar) named _name , so internally in your class you can access the value of the property using the ivar _name . 回答第二个问题 :您正在合成属性名称,并将其与名为_name的内部变量(ivar)关联,因此在您的类内部,您可以使用ivar _name访问属性的值。

I strongly suggest to read the Apple documentation about memory management . 我强烈建议阅读有关内存管理Apple文档

QUESTION 1: if I follow line number 7 everything is fine and if I used line number 9 Memory leakage is there. 问题1:如果我遵循第7行,那么一切都很好,如果我使用了第9行,则存在内存泄漏。 As I know self is point to current object and if I used self.object or simply object no more difference. 据我所知,self是指向当前对象的,如果我使用self.object或只是对象,则不再有任何区别。

Line  7:     name = [NSString stringWithString:@"Hello"];
Line  8:                          OR
Line  9:     self.name = [[NSString alloc]initWithString:@"Hello"]; 

On line 7 you are using a convenience constructor which returns an autoreleased object and assigning the object directly to your name ivar; 在第7行,您使用了一个便捷构造函数,该构造函数返回一个自动释放的对象,并将该对象直接分配给您的name ivar; now, it is ok to assign an autoreleased object to a retain property, but it is incorrect to assign an autoreleased object directly to an ivar without also explicitly retaining it: 现在,可以将一个自动释放的对象分配给一个保留属性,但是将一个自动释放的对象直接分配给一个ivar而不显式地保留它是不正确的:

name = [[NSString stringWithString:@"Hello"] retain];

On line 9 you are using alloc/init which gives you a retained object: it is correct to assign such an object directly to an ivar, but you should autorelease it before assigning to a retain property, eg: 在第9行上,您使用的是alloc / init,它为您提供了一个保留对象:将这样的对象直接分配给ivar是正确的,但是在分配给keep属性之前,您应该自动释放它,例如:

self.name = [[[NSString alloc]initWithString:@"Hello"] autorelease]; 

You can reason about this in terms of the object retain count: 您可以根据对象保留数对此进行推理:

  1. a convenience constructor will set the retain count to 1, but this will be later on automatically decreased by a release call done by the framework; 便利构造函数将保留计数设置为1,但是稍后框架会通过release调用将其自动减少;

  2. alloc/init will give you a retain count of 1 that will not be decreased unless you explicitly call release ; alloc / init将为您提供保留计数1,除非您明确调用release ,否则保留计数不会减少;

  3. When an object retain count goes to 0, then it will be deallocated. 当对象保留计数变为0时,它将被释放。

Reasoning in terms of retain count is just a way to look at this whole matter of memory management and to understand what is going on deep in the framework; 根据保留计数进行推理只是一种查看内存管理整个问题并了解框架深层内容的方法。 in no case this is a proper way to analyze your objects lifecycle, though. 但是,在任何情况下,这都不是分析对象生命周期的正确方法。

then which one is for setting the value of name and which one is for get the value? 那么哪个用于设置name的值,哪个用于获取name的值? Difference between name = [NSString stringWithString:@"Hello"]; name = [NSString stringWithString:@"Hello"];之间的区别name = [NSString stringWithString:@"Hello"]; OR self.name = [NSString stringWithString:@"Hello"]; self.name = [NSString stringWithString:@"Hello"]; OR _name = [NSString stringWithString:@"Hello"]; _name = [NSString stringWithString:@"Hello"];

name = [NSString stringWithString:@"Hello"];

and

_name = [NSString stringWithString:@"Hello"];

are just the same thing in the two cases given. 在两种情况下都是一样的。 This will bypass the property setter(/getter) method and assign directly to the ivar. 这将绕过属性setter(/ getter)方法,并直接分配给ivar。 In this case, your app would sooner or later crash because you are assigning an autoreleased object to the ivar directly. 在这种情况下,您的应用迟早会崩溃,因为您是直接将自动释放的对象分配给ivar。 This would be correct: 这是正确的:

_name = [[NSString stringWithString:@"Hello"] retain];

or 要么

_name = [[NSString alloc] initWithString:@"Hello"];

Note that in a program where you declare your ivar as _name , you cannot use name to refer to it; 请注意,在将ivar声明为_name的程序中,不能使用name来引用它。 you can use name to directly refer to the ivar if you declared only the property without explicitly specifying the ivar like you did for question 1 (in this case, name would be the ivar automatically generated by the compiler for you). 如果声明属性而没有像问题1一样显式指定ivar,则可以使用name直接引用ivar(在这种情况下, name是编译器自动为您生成的ivar)。

On the other hand: 另一方面:

self.name = [NSString stringWithString:@"Hello"]; 

will use the property accessor method (actually, the setter); 将使用属性访问器方法(实际上是setter); since your property is declared as retain , it is ok to assign to it the autoreleased variable returned by the convenience constructor stringWithString: . 由于您的属性被声明为retain ,因此可以将便利构造函数stringWithString:返回的自动释放变量分配给它。

QUESTION 3: if I create any property is there any need to alloc in the memory as I allocated showing the memory leakage. 问题3:如果我创建任何属性,那么在分配内存时就需要在内存中进行分配。

This is not really clear to me. 这对我来说真的不是很清楚。

A good document where to read about the basic of memory management is: Memory Management Policy and also Practical Memory Management from Apple's Advanced Memory Management Programming Guide. 可以阅读有关内存管理基础知识的一个很好的文档是: 内存管理策略以及Apple的《高级内存管理编程指南》中的实用内存管理

First some background, a summary only of the concepts for MRC : 首先介绍一些背景知识, 概述MRC的概念:

Memory management is all about ownership ; 内存管理与所有权有关。 as long as you own an object it will exist, some time after you relinquish ownership the object will be destroyed. 只要您拥有一个对象,该对象就会存在,在您放弃所有权后的一段时间内,该对象将被销毁。 Any references you maintain to an object are effectively invalid and should not be used once you've relinquished ownership. 您维护的对对象的任何引用实际上都是无效的,并且一旦放弃所有权就不应再使用。

Ownership is not exclusive but follows a shared model, there can be more than one owner at any given time and only when an object has no owners does it become available to be destroyed. 所有权不是排他性的,而是遵循共享模型的,在任何给定时间可以有多个所有者,并且只有当对象没有所有者时,它才可以被销毁。

If you only need to use an object temporarily, eg within a single block of code, you do not always need to take ownership. 如果您只需要临时使用一个对象,例如在单个代码块中,则不必总是拥有所有权。 This is partly a consequence of how ownership and be relinquished; 部分原因是所有权和放弃方式的结果; rather than immediately relinquishing ownership you can request ownership is relinquished later . 而不是立即放弃所有权,您可以请求稍后放弃所有权。

Later occurs at certain points in the execution of an application and unless any such points are manually added there is one such point after the execution of each cycle through the run loop. 后来发生在一个应用程序的执行的某些点,除非手动添加任何这样的点有每个周期通过运行循环执行一个这样的点是。

Ownership is asserted through a retain call or calling a method which returns an object you own - most commonly alloc , but also copy and others. 通过retain调用或调用返回您拥有的对象的方法来声明所有权 ,该对象通常是alloc ,但也可以是copy和其他对象。 Ownership is relinquished using a call to release ; 使用release请求放弃所有权; and is relinquished later using a call to autorelease . 稍后通过调用autorelease

Question 1: 问题1:

Line  7:     name = [NSString stringWithString:@"Hello"];
Line  8:                          OR
Line  9:     self.name = [[NSString alloc] initWithString:@"Hello"]; 

The right hand side (RHS) of line 7 returns a reference to an object you do not own. 第7行的右侧(RHS)返回对您拥有的对象的引用。 The left hand side (LHS) assigns this reference to the instance variable name . 左侧(LHS)将此引用分配给实例变量 name You have now stored a reference to something you do not own, this is bad as at any future time the owner(s) of the object may relinquish ownership, the object destroyed, and you have an invalid reference in name . 现在,您已经存储了对您不拥有的东西的引用, 这很不好,因为在将来的任何时候,对象的所有者可能会放弃所有权,该对象被破坏,并且name引用无效。 Lesson: *Do not store references to objects you do not own in instance variables". 课程:*不要将对您不拥有的对象的引用存储在实例变量中”。

On the other hand the RHS of line 9 returns a reference to an object you do own . 另一方面,第9行的RHS返回对您拥有的对象的引用。 However the LHS uses a property invocation self.name to store the reference, and that also takes ownership as it is a retain property - you now own it twice, this is bad but if a different way; 但是,LHS使用属性调用 self.name来存储引用,并且它还拥有所有权,因为它是retain属性-您现在拥有它两次, 这很不好,但是如果使用另一种方式; unless you also relinquish ownership twice, which you probably won't do, the object will always have an owner and will live forever, commonly called a leak . 除非您也两次放弃所有权(您可能不会这样做),否则该对象将始终具有所有者并且将永远存在,通常称为泄漏

If you swap the code around: 如果交换代码:

Line  7a:     name = [[NSString alloc] initWithString:@"Hello"];
Line  8a:                          OR
Line  9b:     self.name = [NSString stringWithString: @"Hello"]; 

then it will do what you expect. 然后它将完成您的期望。 The RHS of line 7a returns an object reference you own and the LHS stores it in the instance variable name which is managed by the property name . 第7a行的RHS返回您拥有的对象引用,LHS将其存储在实例变量 name ,该实例变量 name属性 name管理。

The RHS of line 9a returns an object reference you do not own, however the LHS uses a property invocation and as the property has the retain attribute ownership is taken and the reference stored in the instance variable name is to an owned object. 第9a行的RHS返回您不拥有的对象引用,但是LHS使用属性调用,并且由于该属性具有retain属性所有权,并且实例变量 name存储的引用是对拥有对象的引用。

In either case when the current instance ( self ) is destroyed as the property name has the retain attribute ownership of any object reference by the instance variable name will be relinquished. 无论哪种情况,当当前实例( self )被销毁时,属性name具有实例变量name引用的任何对象引用的retain属性所有权,则将被放弃。

Question 2 问题2

What is the affect of using: 使用有什么影响:

@synthesize name = _name;

This just means that the property name will use an instance variable _name rather than name . 这仅意味着属性 name将使用实例变量 _name而不是name In your code snippets you never declare name or _name so both are automatically declared by the @synthesize ; 在您的代码段中,您永远不会声明name_name因此两者都由@synthesize自动声明; so there is only either a name or an _name instance variable depending on the @synthesize . 因此,取决于@synthesize只有name实例name_name实例变量。 So the answer to Question 2 is the answer to Question 1 with every reference to the instance variable name replaced by _name . 因此,问题2的答案就是问题1的答案,每个实例变量name引用都由_name替换。

Question 3 问题3

If I understand this question, and I'm not sure I do, it is covered by the answer to Question 1. 如果我理解此问题,但不确定我是否知道,那么问题1的答案将涵盖该问题。

HTH 高温超导

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM