Objective-C 中的属性和实例变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1551966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 22:20:32  来源:igfitidea点击:

Properties and Instance Variables in Objective-C

objective-ccocoacocoa-touchpropertiesinstance-variables

提问by Steve Harrison

I'm rather confused about properties and instance variables in Objective-C.

我对 Objective-C 中的属性和实例变量感到很困惑。

I'm about half-way through Aaron Hillegass's "Cocoa Programming for Mac OS X" and everything is logical. You would declare a class something like this:

我大约读了 Aaron Hillegass 的“Mac OS X 的 Cocoa 编程”,一切都是合乎逻辑的。你会声明一个这样的类:

@class Something;

@interface MyClass : NSObject {
    NSString *name;
    NSArray *items;

    Something *something;

    IBOutlet NSTextField *myTextField;
}

@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSArray *items;
  • Since other objects need to manipulate our nameand itemsinstance variables, we use @property/@synthesizeto generate accessors/mutators for them. Within our class, we don't use the accessors/mutators—we just interact with the instance variable directly.

  • somethingis just an instance variable that we're going to use in our class, and since no one else needs to use it, we don't create a pair of accessors and mutators for it.

  • We need to interact with a text field in our UI, so we declare an IBOutletfor it, connect it, and we're done.

  • 由于其他对象需要操作我们的nameitems实例变量,我们使用@property/@synthesize为它们生成访问器/修改器。在我们的类中,我们不使用访问器/修改器——我们只是直接与实例变量交互。

  • something只是一个我们将在我们的类中使用的实例变量,由于没有其他人需要使用它,我们不为它创建一对访问器和修改器。

  • 我们需要与 UI 中的文本字段进行交互,因此我们IBOutlet为它声明一个并连接它,然后我们就完成了。

All very logical.

一切都非常合乎逻辑。

However, in the iPhone world, things seem to be different. People declare properties for every single instance variable, declare properties for IBOutlets, and use accessors/mutators to interact with instance variables withinthe class (e.g. they would write [self setName:@"Test"]rather than name = @"Test").

然而,在 iPhone 的世界里,情况似乎有所不同。人们声明属性,为每一个实例变量,用于声明属性IBOutlets,并使用存取/存取器与实例变量相互作用的类别(例如,他们会写[self setName:@"Test"],而不是name = @"Test")。

Why? What is going on? Are these differences iPhone-specific? What are the advantages of declaring properties for all instance variables, declaring properties for IBOutlets, and using accessors/mutators within your own class?

为什么?到底是怎么回事?这些差异是 iPhone 特有的吗?为所有实例变量声明属性、为 声明属性IBOutlets以及在您自己的类中使用访问器/修改器有什么优点?

采纳答案by Mehrdad Afshari

In the iPhone world, there's no garbage collector available. You'll have to carefully manage memory with reference counting. With that in mind, consider the difference between:

在 iPhone 世界中,没有可用的垃圾收集器。您必须使用引用计数仔细管理内存。考虑到这一点,请考虑以下之间的区别:

name = @"Test";

and

self.name = @"Test";
// which is equivalent to:
[self setName: @"Test"];

If you directly set the instance variable, without prior consideration, you'll lose the reference to the previous value and you can't adjust its retain count (you should have released it manually). If you access it through a property, it'll be handled automatically for you, along with incrementing the retain count of the newly assigned object.

如果您直接设置实例变量,而不事先考虑,您将丢失对先前值的引用,并且您无法调整其保留计数(您应该release手动设置)。如果您通过属性访问它,它将自动为您处理,同时增加新分配对象的保留计数。

The fundamental concept is not iPhone specific but it becomes crucial in an environment without the garbage collector.

基本概念不是特定于 iPhone 的,但它在没有垃圾收集器的环境中变得至关重要。

回答by stefanB

Properties are used to generate accessors for instance variables, there's no magic happening.

属性用于生成实例变量的访问器,没有什么神奇的事情发生。

You can implement the same accessors by hand.

您可以手动实现相同的访问器。

You can find in Aaron Hillegass's book examples of 3 memory management strategies for member variables. They are assign/copy/retain. You select one of those as required for given variable.

您可以在 Aaron Hillegass 的书中找到关于成员变量的 3 种内存管理策略的示例。他们是assign/copy/retain。您可以根据给定变量的需要选择其中之一。

I assume you understand memory management in Objective-c ...

我假设您了解 Objective-c 中的内存管理...

Accessors hide the complexity and differences of memory management for each variable.

访问器隐藏了每个变量的内存管理的复杂性和差异。

For example:

例如:

name = @"Test"

is a simple assignment, namenow holds reference to NSString @"Test". However you could decide to use copyor retain. No matter which version of memory management you chose accessor hides the complexity and you always access the variable with (or similar):

是一个简单的赋值,name现在持有对NSString @"Test". 但是,您可以决定使用copyretain。无论您选择哪个版本的内存管理,访问器都隐藏了复杂性,并且您总是使用(或类似的)访问变量:

[self setName:@"Test"] 
[self name]

Now setName:might use assign/copy or retainand you don't have to worry about it.

现在setName:可能会使用assign/copy or retain,您不必担心。

My guess is that iPhone tutorials use properties to make it easier for new developers to jump through memory management (even though it's handy to generate appropriate accessors with properties rather than implement them by hand every time).

我的猜测是 iPhone 教程使用属性使新开发人员更容易跳过内存管理(即使生成具有属性的适当访问器而不是每次都手动实现它们很方便)。

回答by Peter Hosey

However, in the iPhone world, things seem to be different. People declare properties for every single instance variable, declare properties for IBOutlets, and use accessors/mutators to interact with instance variables within the class (e.g. they would write [self setName:@"Test"]rather than name = @"Test").

然而,在 iPhone 的世界里,情况似乎有所不同。人们为每个实例变量声明属性,为 声明属性IBOutlets,并使用访问器/修改器与类中的实例变量交互(例如,他们会写[self setName:@"Test"]而不是name = @"Test")。

That's not iPhone-specific. Except in initmethods and the deallocmethod, it's good practice to always use your accessors. The main benefit, especially on the Mac (with Cocoa Bindings), is that using your accessors means free KVO notifications.

这不是特定于 iPhone 的。除了init方法和dealloc方法之外,始终使用访问器是一种很好的做法。主要的好处,尤其是在 Mac(使用 Cocoa Bindings)上,是使用你的访问器意味着免费的 KVO 通知。

The reason why people “declare properties for every single instance variable” is most probably that all of their instance variables are things they want to expose as properties. If they had something they would want to keep private, they would not declare a property for it in the header file. (However, they may make a property for it in a class extension in the implementation file, in order to get the aforementioned free KVO notifications.)

人们“为每个实例变量声明属性”的原因很可能是他们所有的实例变量都是他们想要作为属性公开的东西。如果他们有想要保密的东西,他们不会在头文件中为其声明属性。(但是,他们可能会在实现文件的类扩展中为其创建一个属性,以便获得上述免费 KVO 通知。)

Declaring properties for outlets is overkill, in my opinion. I don't see a point to it. If you don't make a property, the nib loader will set the outlet by direct instance-variable access, which is just fine for that task.

在我看来,为网点声明属性是多余的。我看不出有什么意义。如果您不创建属性,nib 加载器将通过直接实例变量访问来设置插座,这对于该任务来说很好。

回答by JRT

I would suggest that modern development has made a very strong attempt to identify, define and apply best practices.

我认为现代发展已经做出了非常强烈的尝试来识别、定义和应用最佳实践。

Among these best practices we find continuity and consistency.

在这些最佳实践中,我们发现了连续性和一致性。

Apart from arguing over use of accessors in initand deallocmethods, accessors should generally be used all the time (inside and outside of a class) for the benefits they offer, including encapsulation, polymorphic var implementations (which both allow for abstracting and refactoring) and to facilitate those best practices of continuity and consistency. The fundamental benefits of an object-orient language come into play when doing things in this way and exploiting the fullness of the language's capabilities. Always being consistent in one's coding is an oft undermentioned benefit, as any senior programmer will usually attest.

除了过度使用存取的争论initdealloc方法,存取一般应使用所有的时间(一个类的内部和外部)为他们所提供的好处,包括封装,多态VAR实现(这既允许提取和重构)和促进连续性和一致性的最佳实践。当以这种方式做事并充分利用语言的全部功能时,面向对象语言的基本优势就会发挥作用。始终在编码中保持一致是一个经常被忽视的好处,正如任何高级程序员通常会证明的那样。

回答by Shafraz Buhary

You can write like this

你可以这样写

//MyClass.h

@class Something;

@interface MyClass : NSObject 

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSArray *items;

@end 

//MyClass.m
@interface MyClass() 

@property (nonatomic, strong) IBOutlet NSTextField *myTextField;
@property (nonatomic, strong) Something *something;

@end