What is modern runtime? - objective-c

Note: Typically in a dealloc method you should release object instance variables directly (rather than invoking a set accessor and passing nilas the parameter), as illustrated in this example:
- (void)dealloc {
[property release];
[super dealloc];
}
If you are using the modern runtime and synthesizing the instance variable, however, you cannot access the instance variable directly, so you must invoke the accessor method:
- (void)dealloc {
[self setProperty:nil];
[super dealloc];
}
What is modern runtime in iOS application development exactly?

It is possible to access the ivar directly, under the same name as the synthesized property. The #synthesize directive creates the ivar on your behalf if one does not already exist, and since that is a compiler directive, the ivar is available at compile-time. See "Runtime Difference" in the Declared Properties chapter of The Objective-C Programming Language. As Abizern noted in a comment, it's also possible to specify whatever name you like for the ivar: #synthesize coffee=tea; -- here, tea is the ivar and coffee the property.
To use the ivar, simply refer to it like any other variable, without using the dot syntax. The following is all perfectly legal and works as expected:
#interface Grisby : NSObject {}
#property (retain) NSObject * obj;
#end
#implementation Grisby
#synthesize obj;
- (void) dealloc {
[obj release], obj = nil;
[super dealloc];
}
- (id) init {
self = [super init];
if( !self ) return nil;
obj = [NSObject new];
return self;
}
- (NSObject *) obj {
return [[obj retain] autorelease];
}
#end
The "modern runtime" was introduced with Mac OS X 10.5 (Leopard) as part of the transition to 64-bit. All versions of iOS use the modern runtime. Synthesized instance variables are a feature of the modern runtime, as noted in the link I provided above.
The other key difference, noted in "Runtime Versions and Platforms" of the Objective-C Runtime Programming Guide, is that instance variables are "non-fragile". There is a layer of indirection added to ivar storage and access which allows classes to add variables without affecting the storage of derived classes. It also presumably facilitates instance variable synthesis. Greg Parker has an explanation involving kittens, there's passing reference to it in Mike Ash's 2009 runtime writeup, and Bavarious here on SO has a swell post about ivar storage and class extensions.
You can see other things that changed, though without explanation, in the "Mac OS X Version 10.5 Delta" chapter of the Objective-C Runtime Reference.

Related

Should I dealloc a nonnull property; and if so, how?

I'm exposing a few properties from an Objective-C project to Swift (based on this repo), but have no experience in Objective-C, so I'm rather out of my depth here, so please bear with me.
I'm wondering how to correctly dealloc a nonnull property (or whether it's necessary at all!). I've provisionally dealloc'ed the nonnull property surface by setting it to null (in the same manner as is done for the nullable partOfSpeech). However, this prompts the following warning:
Null passed to a callee that requires a non-null argument
... so I wonder whether it's redundant. Is there anything I should do instead to handle my nonnull property, during the Node class's dealloc block?
Given the interface, node.h:
#interface Node : NSObject {
NSString *surface;
NSString *partOfSpeech;
}
#property (nonatomic, retain, nonnull) NSString *surface;
#property (nonatomic, retain, nullable) NSString *partOfSpeech;
- (nullable NSString *)partOfSpeech;
#end
... And the implementation, node.m:
#implementation Node
#synthesize surface;
#synthesize partOfSpeech;
// surface is assumed to be set post-initialisation.
- (void)setPartOfSpeech:(NSString *)value {
if (partOfSpeech) [partOfSpeech release];
partOfSpeech = value ? [value retain] : nil;
}
- (NSString *)partOfSpeech {
if (!features || [features count] < 1) return nil;
return [features objectAtIndex:0];
}
- (void)dealloc {
// WARNING: "Null passed to a callee that requires a non-null argument"
self.surface = nil;
self.partOfSpeech = nil;
[super dealloc];
}
#end
... And given that a Node's lifecycle is like this:
Node *newNode = [Node new];
newNode.surface = [[[NSString alloc] initWithBytes:node->surface length:node->length encoding:NSUTF8StringEncoding] autorelease];
// ... Do stuff with newNode (eg. add to array of Node)...
[newNode release];
First: The compiler can automatically synthesize instance variables and
setters/getters for your properties. So your interface should be just
// Node.h
#interface Node : NSObject
#property (nonatomic, retain, nonnull) NSString *surface;
#property (nonatomic, retain, nullable) NSString *partOfSpeech;
#end
and no #synthesize statements are needed in the implementation file.
The compiler will automatically create instance variables
_surface and _partOfSpeech, and also create accessor methods
- (NSString *) surface;
- (void)setSurface:(NSString *)value;
- (NSString *)partOfSpeech;
- (void)setPartOfSpeech:(NSString *)value;
which do "the right thing", with or without ARC. You can override
those methods if you want to implement some custom logic, but you don't have to implement a standard setter like your setPartOfSpeech.
If you use ARC (automatic reference counting) then that is all,
nothing more is needed. And
I would really recommend to do so. The compiler inserts the required retain/release calls at compile time, and is quite clever in avoiding
unnecessary calls. See for example
Confirmed: Objective-C ARC is slow. Don’t use it! (sarcasm off)
about some comparisons. With MRC (manual reference counting), your code might even be slower, or
have memory leaks.
But to answer your question: With MRC you have to release the
instance variables in dealloc
- (void)dealloc {
[_surface release];
[_partOfSpeech release];
[super dealloc];
}
as explained in Memory Management Policy in the "Advanced Memory Management Programming Guide".
You should not use the accessor methods in dealloc as in your
self.surface = nil;
self.partOfSpeech = nil;
see Don’t Use Accessor Methods in Initializer Methods and dealloc.
If you are using manual memory management you can just release the object stored in the properties backing variable. As you've named the backing variable the same as the property use the -> to clearly reference the backing variable:
[self->surface release];
Or if you want to do this with assignment just assign the empty string literal:
self.surface = #"";
The string literal is created at compile time, lives throughout the program execution, and takes up very little space. The assignment will caused the release (and deallocation if the reference count reaches zero) of the previous value in the property, just like assigning nil (or any other value).
HTH

Release method not recognized at runtime (non Cocoa)

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.
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
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.
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.

Why rename synthesized properties in iOS with leading underscores? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?
When creating a new project in Xcode 4, the boilerplate code adds an underscore character when it synthesizes the ivars in the implementation file as:
#synthesize window = _window;
or:
#synthesize managedObjectContext = __managedObjectContext;
Can someone tell me what is being accomplished here? I'm not a complete nube, but this is one aspect of objective-C I don't understand.
Another point of confusion; in the app delegate implementation, after synthesizing the window iVar as above, in the application didFinishLaunchingWithOptions: method the window and viewController ivars are referred to using self:
self.window.rootViewController = self.viewController
[self.window makeKeyAndVisible];
but in the dealloc method it's _window, or _viewController
Thanks
This is an artifact of a previous version of the Objective-C runtime.
Originally, #synthesize was used to create accessors methods, but the runtime still required that instance variables had to be instantiated explicitly:
#interface Foo : Bar {
Baz *_qux;
}
#property (retain) Baz *qux;
#end
#implementation Foo
#synthesize qux = _qux;
- (void)dealloc {
[_qux release];
[super dealloc];
}
#end
People would prefix their instance variables to differentiate them from their properties (even though Apple doesn't want you to use underscores, but that's a different matter). You synthesize the property to point at the instance variable. But the point is, _qux is an instance variable and self.qux (or [self qux]) is the message qux sent to object self.
We use the instance variable directly in -dealloc; using the accessor method instead would look like this (though I don't recommend it, for reasons I'll explain shortly):
- (void)dealloc {
self.qux = nil; // [self setQux:nil];
[super dealloc];
}
This has the effect of releasing qux, as well as zeroing out the reference. But this can have unfortunate side-effects:
You may end up firing some unexpected notifications. Other objects may be observing changes to qux, which are recorded when an accessor method is used to change it.
(Not everyone agrees on this point:) Zeroing out the pointer as the accessor does may hide logic errors in your program. If you are ever accessing an instance variable of an object after the object has been deallocated, you are doing something seriously wrong. Because of Objective-C's nil-messaging semantics, however, you'll never know, having used the accessor to set to nil. Had you released the instance variable directly and not zeroed-out the reference, accessing the deallocated object would have caused a loud EXC_BAD_ACCESS.
Later versions of the runtime added the ability to synthesize instance variables in addition to the accessor methods. With these versions of the runtime, the code above can be written omitting the instance variables:
#interface Foo : Bar
#property (retain) Baz *qux;
#end
#implementation Foo
#synthesize qux = _qux;
- (void)dealloc {
[_qux release];
[super dealloc];
}
#end
This actually synthesizes an instance variable on Foo called _qux, which is accessed by getter and setter messages -qux and -setQux:.
I recommend against this: it's a little messy, but there's one good reason to use the underscore; namely, to protect against accidentally direct ivar access. If you think you can trust yourself to remember whether you're using a raw instance variable or an accessor method, just do it like this instead:
#interface Foo : Bar
#property (retain) Baz *qux;
#end
#implementation Foo
#synthesize qux;
- (void)dealloc {
[qux release];
[super dealloc];
}
#end
Then, when you want to access the instance variable directly, just say qux (which translates to self->qux in C syntax for accessing a member from a pointer). When you want to use accessors methods (which will notify observers, and do other interesting things, and make things safer and easier with respect to memory management), use self.qux ([self qux]) and self.qux = blah; ([self setQux:blah]).
The sad thing here is that Apple's sample code and template code sucks. Never use it as a guide to proper Objective-C style, and certainly never use it as a guide to proper software architecture. :)
Here is another reason. Without underscoring instance variables you frequently obtain warning with the parameters self.title = title and self.rating = rating:
#implementation ScaryBugData
#synthesize title;
#synthesize rating;
- (id)initWithTitle:(NSString *)title rating:(float)rating {
if (self = [super init]) {
self.title = title; // Warning. Local declaration hides instance variable
self.rating = rating; // Warning. Local declaration hides instance variable
}
return self;
}
#end
You avoid warning by underscoring instance variables:
#implementation ScaryBugData
#synthesize title = _title;
#synthesize rating = _rating;
- (id)initWithTitle:(NSString *)title rating:(float)rating {
if (self = [super init]) {
self.title = title; // No warning
self.rating = rating; // No warning
}
return self;
}
#end
in the application didFinishLaunchingWithOptions: method the window and viewController ivars are referred to using self
No, they're not. Those are references to the properties window and viewController. That's the point of the underscore, to make it clearer when the property is being used (no underscore) and when the ivar is being accessed directly (with underscore).
Yes, Its is just to differentiate the reference of object. That is , if the object is referred directly use it with underscore, otherwise use self to refer the object.

Should I release this property?

I'm a objective c newbie, and i'm having a bit of problems with memory management, I've read the apple's memory management policies, however i need a bit of clarification here, this is pretty simple i guess, but i would like to ask you if I'm right:
Given this property:
#interface Test : NSObject {
NSArray *property1;
}
#property (nonatomic,retain) NSArray* property1;
#end
...
//And its implementation:
#implementation Test
#synthetize property1;
-(id) init {
if (self=[super init]) {
self.property1=[[[NSArray alloc] initWithCapacity:5] autorelease];
}
return self;
}
-(void) dealloc {
[super dealloc];
[property1 release];
}
#end
Is it right to issue an Autorelease message to the allocated object in the init method?, i do this cause in apple's document, says that every allocated object should be released by the developer, then, I think, alloc sets retain count to 1, then the property (nonatomic, retain) adds 1, so retain==2, then autorelease substracts 1, and when the dealloc method is called, property1 is released and retain count==0, am I right?
You have your memory management right, though Apple (and a lot of other people) generally recommend not using accessors in your initialization methods because accessors can have side effects beyond simply setting an instance variable that your class might not be set up to handle yet. And in that case, you wouldn't want to autorelease since you'd want ownership of the object.
one side note: in your dealloc, you need to release the property before calling [super dealloc], because [super dealloc] eventually deallocates the memory of the object, which includes the memory containing the property1 variable, so it is invalid to refer to that variable after you call [super dealloc]. It should be:
-(void) dealloc {
[property1 release];
[super dealloc];
}
One of the nice things about using properties is that you can encapsulate all of your "releasing" behavior regardless of whether your property is set to retain, copy, assign, or whatever by just doing this:
self.property1 = nil;
Personally I've gotten in the habit of setting all properties to nil (using self.property, not just accessing the member variable directly) in dealloc so that even if I change how the memory management works for the member variable it works correctly.

Objective-C 2.0; Assigning a Property; Leaking Memory?

I'm still learning about Objective-C memory management. I'm trying to implement several simple classes in an example program that I'm building.
As an example, say I have the following class definition:
#import <UIKit/UIKit.h>
#interface customViewController : UIViewController
{
customObject *myCustomObject;
}
#property (retain) customObject *myCustomObject;
- (void)replaceCustomObject:(customObject *)newObject;
#end
For the property, I use the standard synthesize keyword...
#synthesize myCustomObject;
Then please assume that in the instance of customViewController the myCustomObject is already set with a valid value and is in use. Then the method replaceCustomObject is defined as:
- (void)replaceCustomObject:(customObject *)newObject
{
//Does this cause a memory leak because I just assign over
//the existing property?
self.myCustomObject = newObject;
}
As the comment asks, does this leak memory? Or is this the valid way to replace a previous object with a new object?
Thank you,
Frank
As others have mentioned, your code is perfectly valid and won't leak memory when assigning to the property.
If you have forgotten to implement a proper dealloc method, the last object assigned will be leaked when your customViewController is destroyed. A proper dealloc implementation would look like so:
- (void)dealloc
{
self.myCustomObject = nil;
[super dealloc];
}
That's perfectly valid, and does not leak memory. The synthesized accessors manage retain counts correctly.
(As an aside, you don't need that replaceCustomObject: method; since your property is readwrite by default, you have an auto-generated setCustomObject: method that clients of your class can use, and which follows the normal Cocoa naming conventions.)
According to this, if you use (retain) in your declaration, the synthesized method will release the old value first, then retain the new one:
if (property != newValue) {
[property release];
property = [newValue retain];
}
the property accessor syntax
self.x = y;
has the same effect as calling the setter method explicitly:
[self setX:y];
The accessor method will do whatever it has been written to do. In your case, for a #property(retain) property that has been #synthesized, the accessor will release the old object and retain the new one.
So, calling the setter, whether explicitly or through the '.' syntax, will do the right thing - including the right memory management.
So in short: no, this will not leak memory.