Objective-C:关于头文件声明的简单问题

时间:2011-08-31 04:41:08

标签: iphone objective-c header

这里的初学者,为iPhone开发,有一个非常简单的问题:在头文件中声明方法然后在实现文件中填写它的原因是什么? 总是必须完成吗?

另外,我知道在头文件的@interface中声明变量,但为什么只有有时重复使用@property标记?这是否适用于其他类可能希望读取或写入的变量(因此它们会自动创建getter和setter方法)?

亲切的问候。

5 个答案:

答案 0 :(得分:10)

在.h文件中声明方法称为前向声明。如果在.h文件中声明方法头,则编译器将在实际链接之前知道方法名称,参数和返回类型。您只能在.m文件中编写方法体。但该方法只能由该文件中声明的方法使用。但是如果你在标题中声明一个方法那么它就不是问题了。因为在编译器的第一次传递过程中,方法签名将被所有人知道,并且将在第二次传递中链接。

@property@synthesize标记用于创建自动的getter和setter(或AccessorsMutatorsObjective-C术语),但还有更多。在iOS中,您必须手动执行内存管理(应该在iOS5中进行更改,如Apple承诺的那样)。在@property标记中,您可以了解内存在分配期间的行为。

iOS通过维护保留计数来跟踪对象的内存管理。当您分配一个对象时,它的保留计数变为1.然后您可以通过retain方法手动增加保留计数(例如[myObj retain])或通过释放方法减少保留计数(例如[myObj release])。当保留计数降至0 iOS时,从内存中删除该对象。使用@property标记,您可以定义在分配期间如何管理保留计数。例如,@property标记中最常用的两个参数是:

@property (nonatomic, retain)
@property (nonatomic, assign)

在分配期间的第一种情况下,对象的保留计数将自动增加1(例如self.myObj = anotherClass.anotherObjOfSameClass;),在后一种情况下,保留计数不会增加。

答案 1 :(得分:4)

任何C语言中头文件的要点是将实现与可用方法分开。也就是说,您在头文件中定义类的模板,以便使用您的代码的人可以就像“哦,我想使用此方法和此方法,现在我知道如何实例化此类的对象”。这都是关于抽象的。 : - )

答案 2 :(得分:3)

我想这只是制作两个文件,一个用于公共API(.h),另一个用于(.m)中的逻辑和实现,以隐藏其他人。还有属性标记有助于为变量创建getter和setter。

你在头文件中使用@property而不是在实现中使用@synthesize,它允许你访问getter和setter。

更多阅读,

http://developer.apple.com/library/mac/#referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/_index.html#//apple_ref/doc/uid/TP40007594

仅供参考,你也可以这样做,但不推荐

#import <UIKit/UIKit.h>

@interface FileSystemDemoViewController : UIViewController {

    UITextView *actorListBox;
    NSArray *dataToShow;
}

@property (nonatomic, retain) IBOutlet UITextView *actorListBox;
@property (nonatomic, retain) NSArray *dataToShow;

-(IBAction) covertToAscending:(id)sender;
-(IBAction) covertToDescending:(id)sender;

@end

@implementation
...Your implementation here...
@end

以上所有代码都在.m文件中,实现。

再次不推荐

快乐编码

答案 3 :(得分:2)

为什么要分开.h和.m文件?

从历史上看,在C中,当你包含.h文件时,它几乎完全等同于将文件粘贴到包含它的文件中。实际上,所有声明都在使用它们的每个文件中重复。没关系,在C中你可以重复声明你想要的任何声明,只要它们不会改变。但是,重复定义会导致函数的多个副本和一般破坏。因此,您不能包含模块的整个代码,只能包含其声明。

我认为Objective-C实际上更聪明,如果你想要根本没有.m文件,你可以将所有代码放在.h文件中。你也可以只在一个.m文件中定义一个类,并且没有.h文件,但是你不能真正制作这样的整个项目,因为没有什么能够访问其他任何东西。

但是,将声明与定义分开仍然是一种很好的做法。这就像在餐厅吃菜单而不必回到厨房,看看有什么做饭。 .h文件是其他模块如何使用模块内容的简短摘要。

为什么有些实例变量有属性而有些却没有?

正确,部分原因是实例变量不能自动用于其他类。默认属性是。但是,不一定。您可以将酒店设为私人。

您使用属性获得的另一件事是自动内存管理。如果使用retain属性,则在为属性赋值时,将增加值的保留计数,并减少先前值的保留计数(如果有)。它非常方便,避免了傻瓜。即使其他类不访问实例变量,它也很有用。如果不使用属性,则必须确保在实例方法中执行适当的保留和释放指令,以避免泄漏内存。您还可以在属性上获得其他自动行为,例如锁定或复制。

最后,您可以使用属性属性和@synthesize关键字获取内置行为,但您也可以决定不使用@synthesize关键字,并为您的属性编写自定义getter和setter。这些可以做很奇特的事情,比如在属性发生变化时更新相关的实例变量。

答案 4 :(得分:1)

如上所述,.h和.m文件的最初原因是C编译器单独处理每个源文件,然后仅在它们链接时才连接它们之间的点。因此,需要有一些声明可以传播的机制 - 以便可以单独检查每个文件的编译器错误和警告 - 但定义仍保留在一个位置 - 以便链接器可以确保公共资源最终位于公共位置。

从现代运行时开始,.h文件和.m文件之间的区别更好地被认为是接口和实现之间的区别。界面是您发布供所有人查看的内容。实现仅适用于该类的知识。您与外界的唯一合同是界面定义的合同。

与大多数面向对象语言一样,Objective-C采用对象属性的getter和setter概念。对象无法访问其他对象的实例变量,而是询问“这个值是什么?”或“请将其值设置为此”。在Objective-C 2.0之前,你必须自己编写getter和setter,这引入了大量重复的样板代码。 @property的最初目的是在界面中声明getter或setter。 @synthesize用于为声明为@property的内容生成默认实现。

从新运行时开始,不需要在接口中声明实例变量,您可以将它们完全保留在实现中。所以,例如:

SomeClass.h:

@interface SomeClass: NSObject

- (void)doSomeTask;

@end

SomeClass.m:

// declare a category with some unexposed properties
@interface SomeClass ()
@property (nonatomic, assign) NSMutableArray *arrayForMe;
@end

@implementation SomeClass

@synthesize arrayForMe; // you can now use the property self.arrayForMe,
                        // even though you didn't declare a backing
                        // instance variable

- (void)doSomePrecursorTask
{
    // ...
}

- (void)doSomeTask
{
    // as a fact of implementation, I need to do something else
    // first. Because it's an implementation specific, I don't
    // want to put it in the declared interface

    [self doSomePrecursorTask];
    // ...
}

@end

新的运行时可在iOS,Lion和64bit Snow Leopard上使用。作为一种良好的实践,现在将实例变量保留在头文件中可能是有意义的。只需将公共接口放在那里,并将它们视为形式化和通信的一种方式。我希望标题中的实例变量看起来很快就会成为NSEnumerator