Objective C实例variables

好的 – 所以我确信我的困惑只是被卡在“Java心态”中,而不了解Obj C在这种情况下的不同之处。

在Java中,我可以像这样在类中声明一个variables,并且该类的每个实例都有自己的variables:

MyClass { String myVar; MyClass() { // constructor } } 

在Obj中,CI试图通过只在.m文件中声明一个variables来做同样的事情:

 #import "MyClass.h" @implementation MyClass NSString *testVar; @end 

我的期望是这个variables的范围仅限于这个类。 所以我创build了第二个类(相同):

 #import "MySecondClass.h" @implementation MySecondClass NSString *testVar; @end 

我所看到的(让我感到困惑的是)改变一个class级的variables,影响另一class级的价值。 事实上,如果我设置了一个断点,然后“跳到定义”的variables,它需要我

我创build了一个非常小的XCode项目来演示这个问题

没有什么比移动到一种新的语言更谦虚:)

提前致谢。

改变这个:

 @implementation MyClass NSString *testVar; @end 

至:

 @implementation MyClass { NSString *testVar; } // methods go here @end 

你会得到你所期望的。

就像你一样,你实际上正在创build一个全局variables。 这两个全局variables被链接器合并成一个,这就是为什么当你设置一个variables的时候它们都会改变。 花括号中的variables将是一个适当的(和私有的)实例variables。

编辑:在没有明显原因被低估之后,我想我会指出做事的方式和方式。

旧的方式:

SomeClass.h

 @interface SomeClass : UIViewController <UITextFieldDelegate> { UITextField *_textField; BOOL _someBool; } @property (nonatomic, assign) BOOL someBool; // a few method declarations @end 

SomeClass.m

 @implementation SomeClass @synthesize someBool = _someBool; // the method implementations @end 

现在使用现代Objective-C编译器的新的改进方法:

SomeClass.h

 @interface SomeClass : UIViewController @property (nonatomic, assign) BOOL someBool; // a few method declarations @end 

SomeClass.m

 @interface SomeClass () <UITextFieldDelegate> @end @implementation SomeClass { UITextField *_textField; } // the method implementations @end 

新方法有几个优点。 主要的优点是在.h文件中没有关于该类的实现特定细节。 客户端不需要知道实现需要的代表。 客户端不需要知道我使用的是什么ivars。 现在,如果实现需要新的ivar或需要使用新的协议,则.h文件不会更改。 这意味着更less的代码被重新编译。 它更干净,更高效。 这也使编辑更容易。 当我编辑.m文件并意识到我需要一个新的ivar时,请在我正在编辑的.m文件中进行更改。 不需要来回交换。

另请注意,实现不再需要ivar或@synthesize作为属性。

在Java中

 MyClass { String myVar; MyClass() { // constructor } } 

在Objective-c中

 MyClass.h @interface MyClass : NSObject{ NSString* str; // Declaration } @end MyClass.m @implementation MyClass -(void)initializieTheString { //Defination } @end 

在Objective-C中,通过这样做来将variables定义为私有

 MyClass.h @interface MyClass : NSObject{ NSString* _myTestVar; // Declaration } @end 

并通过像MyClass.m那样在实现类中引用它

 #import "MyClass.h"; @implementation MyClass -(void)initializieTheString { _myTestVar= @"foo"; //Initialization } @end 

你可能想要的(除非你使用的是一个非常老的操作系统和编译器)只是使用属性语法。 即:

 @interface MyClass : NSObject // method declarations here ... @property (copy) NSString* myVar; // ... or here. @end 

这将做你想做的事情。 这将隐式地为这个variables合成一个实例variables和一个getter / setter对。 如果你手动创build实例variables(除非你需要你的代码来处理非常旧的MacOS版本,那么你通常不需要这个variables),这就是上面的代码在创buildivar时所做的:

 @interface MyClass : NSObject { NSString* _myVar; } // method declarations here. @end 

注意花括号,它告诉编译器,这不仅仅是方法之间的全局variables,而且实际上是一个属于这个对象的实例variables。

如果你只是为了内部使用而创build这个属性,并且不希望你的类的客户弄乱它,那么你可以通过使用一个inheritance来“隐藏”这个类来隐藏它,而不是最老的ObjC编译器声明来自头文件,但可以独立于它(通常在你的实现文件中)。 类扩展看起来像一个没有名字的类:

 @interface MyClass () @property (copy) NSString* myVar; @end 

你可以把你的财产声明在那里,甚至是伊娃的声明(再次用大括号括起来)。 您甚至可以在类接口中声明相同的属性为readonly属性,然后将其重新声明为相同的,但在扩展名中为readwrite ,以便客户端只读取它,但是您的代码可以更改它。

请注意,如果你没有使用ARC(也就是说,你已经closures了自动引用计数的默认设置),你必须在你的dealloc方法中将所有属性设置nil (除非它们被设置为weak或者当然assign )。

注意 – 以上都是@interface部分。 你的实际代码将在单独的@implementation部分。 这样,您可以将头文件( .h )交给您的课程客户端,它们只包含您打算使用的部分,并将实现细节隐藏在实现文件( .m )中,您可以在其中无需更改不必担心有人可能意外地使用了它们,并且会破坏其他代码。

PS – 请注意NSStrings和其他对象,你想不可变的味道,但也存在一个可变的味道(即NSMutableString )应该永远是copy属性,因为这将把一个NSMutableString变成一个NSString,使外部没有人可以改变你下面的可变string。 对于所有其他对象types,通常使用strongtypes(或者retain如果不是ARC)。 对于你的class级的所有者(例如它的代表),你通常使用weak (或者如果不是ARC,则assign )。