iphone - Objective C中变量位置的声明/定义?

自从开始研究 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
  • 我对 1 和 4 的理解是,它们是 C 风格的基于文件的声明和定义,对类的概念没有任何理解,因此必须准确地使用它们在 C 中的使用方式。我之前已经看到它们用于实现基于静态变量的单例。我还缺少其他方便的用途吗?
  • 我对 iOS 的看法是,在 @synthesize 指令之外几乎已经完全淘汰了 ivars,因此几乎可以忽略不计。是这样吗?
  • 关于 5:我为什么要在私有(private)接口(interface)中声明方法?我的私有(private)类方法似乎编译得很好,没有在接口(interface)中声明。主要是为了可读性吗?

非常感谢,伙计们!

最佳答案

我能理解你的困惑。尤其是最近对 Xcode 的更新和新的 LLVM 编译器改变了 ivars 和属性的声明方式。

在“现代”Objective-C(在“旧”Obj-C 2.0 中)之前,您没有太多选择。实例变量过去在大括号 { }:

之间的 header 中声明
// 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;

更改生成的 ivar 的名称
// 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/

相关文章:

ios - 使用自动布局在 UICollectionView 中指定单元格的一维

objective-c - 最佳实践 - 您自己的项目/应用程序的 NSError 域和代码

c++ - 从 C++ 成员函数调用 Objective-C 方法?

objective-c - 何时使用 -retainCount?

ios - 我如何通过 Foundation 获取星期几?

ios - 从文档目录中删除指定文件

iphone - 使用 Core Data 实现枚举的最佳方法

ios - 了解 ibecon 距离

ios - Xcode MyProjectName-Bridging-Header.h 不存在

ios - Objective-C/Cocoa 中 Java 的 Thread.sleep() 等价