-2
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>

@interface CustomAnnotation : NSObject <MKAnnotation>
{
    CLLocationCoordinate2D coordinate;
    NSString *title;
    NSString *subTitle;
}

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

- (id)initWithLocation:(CLLocationCoordinate2D)coords title:(NSString *)aTitle andSubtitle:(NSString*)aSubtitle;

@end

我正在做一个包含上面代码的教程。

我的问题:

  1. 在大括号和@property 中定义变量有什么区别?
  2. 为什么我们需要在这两个地方定义变量?
  3. 在 .h 和 .m 文件中声明 #import 有什么区别?

请回答所有三个问题。

4

4 回答 4

3

1.在大括号和@property 中定义变量有什么区别?

    @接口 XXX:YYY
    {
       伊娃的地方
    }
    属性的地方。以 _(下划线) 为前缀的 ivars 会在新编译器中自动创建。
    @结尾

2. 为什么我们需要在这两个地方定义变量?

这是旧样式,现在只是完成了。只有@property就够了。

3.在 .h 和 .m 文件中声明 #import 有什么区别?

如果你想要一些类对象作为属性,你可以在 .h 中定义它,如果你只想在实现中而不是在 .m 中导入。

如果您将所有#imports 放在头文件中,则没有两个类可以相互依赖,因为文件无法导入导入它的文件。另一方面,如果您将#import 放在实现文件中,问题就会消失。

Chuck 的摘录,最佳实践和基本原理:#import in .m or .h

于 2013-04-10T15:15:41.887 回答
2

在大括号之间声明变量具有实际创建变量存储的效果。

@property声明将访问方法并自动为您生成支持 ivar,这使得第一个声明变得多余。所以你可以去掉花括号之间的声明,只保留你的属性声明。

自动合成的 ivar 将有一个前导下划线,当您直接访问 ivar 或通过访问器时,它会更加清晰,例如

@property (nonatomic, strong) MyThing *myThing;

将在您的课堂上直接使用

_myThing = [[MyThing alloc] init];

或通过访问器

[self setMyThing:[[MyThing alloc] init]];

通常,除非您在被覆盖的访问器方法中,否则大多数时候通过访问器是您想要的。


曾经有一段时间@property并且@synthesize只会为您生成访问器方法,您必须确保为它们的使用创建存储 - 在花括号之间声明 ivar。

然后事情继续进行,@property并且@synthesize是您所需要的,并且支持 ivar 将被自动合成。

目前的游戏状态@property是(在大多数情况下)只需要 ,并且@synthesize隐式完成。


进口

没有技术差异,该语句实际上只是抓取您正在导入的文件的内容并将它们转储到它的位置。

您需要注意循环依赖

FileA           | FileB
----------------+----------------
#import "FileB" | #import "FileA"
                |

从字面上看,这将成为

FileA           |<-
----------------|  \
#import "FileB" |  /
#import "FileA" |-'

FileB           |<-
----------------|  \
#import "FileA" |  /
#import "FileB" |-'

这两个文件都将处于循环循环中,试图导入自己,例如这不起作用。

因此,避免此问题的最简单方法是在您的标头中进行最少量的导入。

如果您需要在标题中引用一个类,请使用前向声明 ( @class)

所以你最终得到了这个

@class MyClass

@interface MyOtherClass : NSObject

@property (nonatomic, strong) MyClass *mything;

@end

您基本上已经告诉编译器MyClass存在,因此您可以引用它。

MyClass然后,您可以在实现文件中导入实际的标头。

#import "MyOtherClass.h"
#import "MyClass.h"

@implementation MyOtherClass

@end
于 2013-04-10T15:24:38.907 回答
1

1) 在大括号和@property 中定义变量有什么区别?

因为@property定义了变量的态度以及它的可访问性限制,如果你不写@property它也可以工作,但是如果你希望编译器自动为变量创建getter和setter方法,那么在.m文件中使用@property@synthesize

2)为什么我们需要在两个地方定义变量?

第一个答案的后半部分包括它的答案。简要“定义 setter 和 getter 方法及其可访问性”

#import3)在 .h 和 .m 文件中声明有什么区别?

如果您在 .h 文件中导入使用它,它将对该类的所有子类可用,而如果您在 .m 文件中导入,它将仅对 .m 文件可用(范围)

于 2013-04-10T15:24:57.243 回答
1
  1. 在大括号内,您可以声明任何您希望的实例变量。大括号之外是您声明的地方@properties,它会自动为对象生成 getter 和 setter,以及您在实现文件中定义的任何非私有方法。

  2. 正如@Anoop Vidya 所提到的,在这两个地方声明变量现在是多余的并且没有必要。

  3. 导入文件的一般经验法则:相互导入的文件会产生运行时错误。因此,请遵守以下规则:

如果您需要另一个类的实例变量,请在头文件中使用 导入另一个类,@class然后#import将其导入实现文件中。

如果您不需要从您创建的另一个类创建 ivar,那么只需#import将其放入您的实现文件中。

如果在执行这些步骤后仍然遇到相互依赖问题,那么您可能需要重新考虑您的设计。

于 2013-04-10T15:25:03.317 回答