Reputation:
I'm a newbie to Objective-C but have extensive experience in C and C++. The first thing I have noticed is that there is a real void in basic tutorials out there as all assume you are developing for the iPhone or Mac and using Cocoa. I'm not using Cocoa or Gnustep. To the point:
As a simple example to get started I'm trying to wrap the C's File I/O functionality. My code starts as 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
And File.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
Then 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];
}
The compiler gives me a warning that my object "may not respond to '-release'". Then when running the program is results in a runtime error: "does not recognize release. This application has requested the Runtime to terminate" .. and so on.
I'm guessing I'm making a simple newbie error, but where? Or perhaps there is something missing? I'm hoping someone can point me in the right direction here. Thanks.
If this qst has been asked already then a reference would do too. I did try to find a reference but no luck.
FOLLOW UP:
changed release method to
- (void)release
{
fclose(pFile);
[super free];
}
and it appeared to work. Apparently free
is recognized in object.h
.
Upvotes: 2
Views: 247
Reputation: 8345
As others have said it is unusual to use Objective-C without the Foundation frameworks. However, the Object
class should implement release
, retain
etc. The Object
class included (but not used) in Apple's Objective-C Runtime certainly contains these basic methods.
Assuming your Object
class does contain these basic methods there are a couple of problems with your class as implemented.
First, you have created a new
instance method which simply calls [super init]
. The new
method by convention is a class method which is shorthand for calling alloc
and init
to create and initialise an object. new
is defined in Apple's Object
class. It is implemented as:
+ (id)new
{
id newObject = (*_alloc)((Class)self, 0);
Class metaClass = self->isa;
if (class_getVersion(metaClass) > 1)
return [newObject init];
else
return newObject;
}
Note that this method is a class method, signified by the +
instead of the -
. GNUStep implements new
as follows:
+ new
{
return [[self alloc] init];
}
The idiomatic way to use new
would be:
File *obj = [File new];
This is in fact what you have done, however, this is calling the class method new
not your instance method new
.
If you wanted to call your new
method you'd have to call:
File *obj = [[File alloc] new];
but as others have stated you'd need to return your object. Removing your new method would have no effect on your implementation as it isn't currently being called.
Secondly, you have placed your call to fclose
in your overriden release
method. This is wrong, certainly in Apple's implementation of Object
anyway, GNUstep appears to be different. release
could get called multiple times on a single instance of an object. retain
and release
are used to increment/decrement the objects retain count. Only when the retain count reaches zero should the file handle be closed. Normally, within Foundation you'd place the call to fclose
in a dealloc
method. dealloc
is Objective-C's destructor method. The dealloc
should look something like:
- (void)dealloc
{
fclose(pFile);
[super dealloc];
}
However, dealloc
doesn't appear to be implemented in either Apple's or GNUstep's Object
class. There is, as you point out in your question a free
method which seems to be a destructor.
It would appear that replacing the above dealloc
method with an equivalent free
method would work as a destructor, e.g.:
- (void)free
{
fclose(pFile);
[super free];
}
Apple's implementation of Object
contains retain
and release
methods but the GNUstep implementation does not. Neither implementation contains a dealloc
method.
The implementations of Object.m
and NSObject.m
for Apple and GNUstep can be found at the following locations:
Apple 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
Apple 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
Upvotes: 4
Reputation:
Is release
defined on class Object
? If it is not, then your call to
[super release];
will not work. (In cocoa, release is a member of NSObject
; your Object
class may or may not have it, and in fact the retain/release reference counting might not be there at all.)
You should confirm that your base class includes all methods called via super
.
Upvotes: 2
Reputation: 28786
As @xlc0212 pointed out, the reference counting style of memory management is included in NSObject.
NSObject is a part of CoreFoundation library for Cocoa, CocoaTouch and GnuStep. I would say you need to link to CoreFoundation.
One book that I've read and focuses on pure Objective-C (not necessarily Cocoa) is "Programming in Objective-C 2.0" by Steven G Kochan.
Upvotes: 1