2

我是 Objective-C 的新手,但在 C 和 C++ 方面拥有丰富的经验。我注意到的第一件事是基本教程中存在真正的空白,因为所有人都假设您正在为 iPhone 或 Mac 开发并使用 Cocoa。我没有使用 Cocoa 或 Gnustep。重点:

作为一个简单的入门示例,我正在尝试包装 C 的文件 I/O 功能。我的代码以 File.h 开头

#include <objc/Object.h>
#include <stdio.h>
@interface File:Object
{
    FILE *pFile;
    char *path;
}

@property FILE *pFile;
@property char *path;

- (void)new;
- (void)OpenReadText:(const char*)var1;
- (void)release;

@end

和文件.m

#include "File.h"

@implementation File

@synthesize pFile, path;

- (void)new
{
    self = [super init];
}
- (void)release
{
    fclose(pFile);
    [super release];
}

- (void)OpenReadText:(char*)var1
{
    path = var1;
    pFile = fopen(path,"r");
}

@end

然后 main.m

#include <stdio.h>
#import <objc/Object.h>
#include "File.h"

int main(void) {

File *Fileobj = [File new];

[Fileobj OpenReadText:"File.h"];

[Fileobj release];


}

编译器给我一个警告,我的对象“可能不响应'-release'”。然后在运行程序时会导致运行时错误:“无法识别发布。此应用程序已请求运行时终止”..等等。

我猜我犯了一个简单的新手错误,但是在哪里?或者也许缺少什么?我希望有人可以在这里为我指明正确的方向。谢谢。

如果这个 qst 已经被问过,那么参考也可以。我确实试图找到一个参考,但没有运气。

跟进:

将发布方法更改为

- (void)release
{
    fclose(pFile);
    [super free];
}

它似乎奏效了。显然free是被认可的object.h

4

3 回答 3

4

正如其他人所说,在没有 Foundation 框架的情况下使用 Objective-C 是不寻常的。但是,Object该类应该实现release等。Apple 的 Objective-C 运行时中包含(但未使用)retain的类当然包含这些基本方法。Object

假设您的Object类确实包含这些基本方法,那么您的类在实现时存在一些问题。

首先,您创建了一个new简单调用[super init]. 按照惯例,该new方法是一个类方法,它是调用allocinit创建和初始化对象的简写。 new在 Apple 的Object类中定义。它被实现为:

+ (id)new
{
        id newObject = (*_alloc)((Class)self, 0);
        Class metaClass = self->isa;
        if (class_getVersion(metaClass) > 1)
            return [newObject init];
        else
            return newObject;
}

请注意,此方法是一个类方法,由+代替表示-。GNUStep 实现new如下:

+ new
{
   return [[self alloc] init];
}

惯用的使用new方式是:

File *obj = [File new];

这实际上是您所做的,但是,这是调用类方法new而不是您的实例方法new

如果你想调用你的new方法,你必须调用:

File *obj = [[File alloc] new];

但正如其他人所说,您需要返回您的对象。删除您的新方法不会对您的实现产生影响,因为它当前没有被调用。

其次,您已将调用置于fclose覆盖的release方法中。这是错误的,Object无论如何,在Apple的实现中,GNUstep似乎有所不同。 release可以在对象的单个实例上多次调用。 retainrelease用于增加/减少对象保留计数。只有当保留计数达到零时,才应关闭文件句柄。通常,在 Foundation 中,您会将调用fclose放在一个dealloc方法中。 dealloc是 Objective-C 的析构方法。dealloc应该看起来像:

- (void)dealloc
{
    fclose(pFile);
    [super dealloc];
}

但是,dealloc似乎没有在 Apple 或 GNUstep 的Object类中实现。正如您在问题中指出的那样,有一种free方法似乎是析构函数。

dealloc用等效方法替换上述方法free似乎可以用作析构函数,例如:

- (void)free
{
    fclose(pFile);
    [super free];
}

Apple 的Objectcontainsretainrelease方法的实现,但 GNUstep 的实现没有。两种实现都不包含dealloc方法。

Object.mApple和GNUstep的实现NSObject.m可以在以下位置找到:

苹果 Object.m: http: //opensource.apple.com/source/objc4/objc4-532.2/runtime/Object.m

GNUstep Object.m:https ://github.com/gnustep/gnustep-libobjc/blob/master/Object.m

苹果NSObject.mm:http://opensource.apple.com/source/objc4/objc4-532.2/runtime/NSObject.mm

GNUstep NSObject.m:https ://github.com/gnustep/gnustep-base/blob/master/Source/NSObject.m

于 2013-02-24T03:31:26.380 回答
2

release在类上定义的Object吗?如果不是,那么您致电

[super release];

不管用。(在 cocoa 中,release 是 的成员NSObject;您的Object班级可能有也可能没有,事实上,保留/释放引用计数可能根本不存在。)

您应该确认您的基类包括通过调用的所有方法super

于 2013-02-24T02:12:31.343 回答
1

正如@xlc0212 所指出的,内存管理的引用计数样式包含在 NSObject 中。

NSObject 是 Cocoa、CocoaTouch 和 GnuStep 的 CoreFoundation 库的一部分。我会说你需要链接到CoreFoundation。

我读过的一本专注于纯 Objective-C(不一定是 Cocoa)的书是 Steven G Kochan 的“Objective-C 2.0 编程”。

于 2013-02-24T02:09:59.240 回答