自从开始研究 iOS 应用程序和 Objective-C 以来,我一直对可以声明和定义变量的不同位置感到非常困惑。一方面,我们有传统的 C 方法,另一方面,我们有新的 ObjectiveC 指令,在此基础上添加了 OO。你们能否帮助我了解我想将这些位置用于我的变量的最佳实践和情况,并可能纠正我目前的理解?
这是一个示例类(.h 和 .m):
#import <Foundation/Foundation.h>
// 1) What do I declare here?
@interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
// 3) class-specific method / property declarations
@end
和
#import "SampleClass.h"
// 4) what goes here?
@interface SampleClass()
// 5) private interface, can define private methods and properties here
@end
@implementation SampleClass
{
// 6) define ivars
}
// 7) define methods and synthesize properties from both public and private
// interfaces
@end
非常感谢,伙计们!
最佳答案
我能理解你的困惑。尤其是最近对 Xcode 的更新和新的 LLVM 编译器改变了 ivars 和属性的声明方式。
在“现代”Objective-C(在“旧”Obj-C 2.0 中)之前,您没有太多选择。实例变量过去在大括号 { }
:
// MyClass.h
@interface MyClass : NSObject {
int myVar;
}
@end
您只能在您的实现中访问这些变量,而不能从其他类访问。为此,您必须声明访问器方法,如下所示:
// MyClass.h
@interface MyClass : NSObject {
int myVar;
}
- (int)myVar;
- (void)setMyVar:(int)newVar;
@end
// MyClass.m
@implementation MyClass
- (int)myVar {
return myVar;
}
- (void)setMyVar:(int)newVar {
if (newVar != myVar) {
myVar = newVar;
}
}
@end
通过这种方式,您也可以从其他类获取和设置此实例变量,使用通常的方括号语法发送消息(调用方法):
// OtherClass.m
int v = [myClass myVar]; // assuming myClass is an object of type MyClass.
[myClass setMyVar:v+1];
由于手动声明和实现每个访问器方法非常烦人,因此引入了 @property
和 @synthesize
来自动生成访问器方法:
// MyClass.h
@interface MyClass : NSObject {
int myVar;
}
@property (nonatomic) int myVar;
@end
// MyClass.m
@implementation MyClass
@synthesize myVar;
@end
结果是更清晰和更短的代码。访问器方法将为您实现,您仍然可以像以前一样使用括号语法。但除此之外,还可以使用点语法来访问属性:
// OtherClass.m
int v = myClass.myVar; // assuming myClass is an object of type MyClass.
myClass.myVar = v+1;
从 Xcode 4.4 开始,您不必再自己声明实例变量,也可以跳过 @synthesize
。如果您不声明 ivar,编译器会为您添加它,并且它还会生成访问器方法,而无需您使用 @synthesize
。
自动生成的 ivar 的默认名称是以下划线开头的名称或您的属性。您可以使用 @synthesize myVar = iVarName;
// MyClass.h
@interface MyClass : NSObject
@property (nonatomic) int myVar;
@end
// MyClass.m
@implementation MyClass
@end
这将与上面的代码完全一样。出于兼容性原因,您仍然可以在 header 中声明 ivars。但是因为你想要这样做(而不是声明属性)的唯一原因是创建一个私有(private)变量,你现在也可以在实现文件中这样做,这是首选方式。
实现文件中的@interface
block 实际上是Extension并可用于转发声明方法(不再需要)和(重新)声明属性。例如,您可以在标题中声明一个 readonly
属性。
@property (nonatomic, readonly) myReadOnlyVar;
并在您的实现文件中将其重新声明为 readwrite
以便能够使用属性语法来设置它,而不仅仅是通过直接访问 ivar。
至于完全在任何 @interface
或 @implementation
block 之外声明变量,是的,它们是纯 C 变量,工作方式完全相同。
https://stackoverflow.com/questions/12632285/