iOS / Objective C:代码说明

时间:2013-04-10 15:11:44

标签: ios objective-c

#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 个答案:

答案 0 :(得分:3)

  

1.在大括号中定义变量之间的区别是什么   @property?

    @interface XXX:YYY 
    {
       place for ivars
    }
    place for properties. ivars prefixed with _(underscore) gets created automatically in new compiler.
    @end
  

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

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

  

3.在.h和.m文件中声明#import之间的区别是什么?

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

  

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

Chuck的摘录,Best practice and rationale: #import in .m or .h

答案 1 :(得分: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

答案 2 :(得分:1)

  

1)在大括号中定义变量之间的区别是什么?   @property?

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

  

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

第一个答案的后半部分包括答案。简要&#39;定义setter&amp; getter方法及其可访问性&#39;

  

3).h与.m文件中声明@synthesize之间的区别是什么?

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

答案 3 :(得分:1)

  1. 在大括号内,您可以声明所需的任何实例变量。在大括号之外是您声明@properties的位置,它会自动生成对象的getter和setter,以及您在实现文件中定义的任何非私有方法。

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

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

  4.   

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

         

    如果您不需要从已创建的其他类创建ivar,那么只需#import将其添加到您的实现文件中。

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