what is difference between alloc and allocWithZone:? - objective-c

From forum discussion , seem like that the big difference is performance factor, allocWithZone: will alloc memory from particular memory area, which reduce cost of swapping.
In practice, almost get no chance to use allocWithZone: , anyone can give simple example to illustrate which case to use allocWithZone: ?
Thanks,

When one object creates another, it’s
sometimes a good idea to make sure
they’re both allocated from the same
region of memory. The zone method
(declared in the NSObject protocol)
can be used for this purpose; it
returns the zone where the receiver is
located.
This suggests to me that your ivars, and any objects your classes "create" themselves could make use of +allocWithZone: in this way, to make the instances they create in the same zone.
-(id)init {
if (self = [super init]) {
someIvar = [[SomeOtherClass allocWithZone:[self zone]] init];
}
return self;
}

From Apple's documentation:
This method exists for historical reasons; memory zones are no longer
used by Objective-C.

A good example for using allocWithZone: is when you are implementing the NSCopy protocol, which allows you make your custom objects copyable (deep copy / copy by value) like:
(1) ClassName *newObject = [currentObject copy]; //results in newObject being a copy of currentObject not just a reference to it
The NSCopy protocol ensures you implement a method:
(2) -(id)copyWithZone:(NSZone *)zone;
When copying an object the 'copy' message you send as above (1) when stated as 'copyWithZone sends a message to the method(2). aka you don't have to do anything to get a zone yourself.
Now as you have a 'zone' sent to this message you can use it to ensure a copy is made from memory in the same region as the original.
This can be used like:
-(id)copyWithZone:(NSZone *)zone
{
newCopy = [[[self class]allocWithZone:zone]init]; //gets the class of this object then allocates a new object close to this one and initialises it before returning
return(newCopy);
}
This is the only place I am aware allocWithZone is actually used.

I use allocWithZone in singleton. As Forrest mentioned, the variables created allocated from the same region of memory. Thus other classes can use or access them from the same zone of memory. Save memory space when you run your app.

In the Foundation Functions Reference, all of the Zone functions are now prefaced with the below warning that Zones will be ignored.
Zones are ignored on iOS and 64-bit runtime on OS X. You should not use zones in current development.
NSCreateZone
NSRecycleZone
NSSetZoneName
NSZoneCalloc
NSZoneFree
NSZoneFromPointer
NSZoneMalloc
NSZoneName
NSZoneRealloc
NSDefaultMallocZone

Even if the Apple's Documentation indicates that allocWithZone:
exists for historical reasons; memory zones are no longer used by Objective-C. You should not override this method.
and
Zones are ignored on iOS and 64-bit runtime on OS X. You should not use zones in current development.
in reality I overridden it in an Objective-C class (in a full Objective-C project) and the method is called when I do [[Mylass alloc] init] even if the build is running on an iPhone 6s.
But I think it's better to follow the documentation and override alloc method instead of this one because alloc can certainly do the same job.

Related

Fully deallocating an Objective-C singleton

I'm new to writing singletons and I have to use one for a current iOS project. One of the requirements is that it can be killed. I know this goes against the design of a singleton, but is this something that should/could be done?
Of course it could be done, but if you're looking for an object that can be created, and then released when not needed... that sounds like a regular object. :)
Generally singletons control their own lifecycles. You're going to get one-sided discussion here unless you say more about the two requirements (one, that you use a singleton, and two, that it can be released at will), and why they both make sense in your case.
It might be because the singleton wraps some other resource that is inherently unique (like a file resource or network connection). If this is true, then generally the singleton is the "manager" of that resource, and you'd expose control of that resource via the singleton's interface.
Or it might be because the singleton object holds on to a ton of memory (a buffer of some sort), and you want to be sure that's flushed as necessary. If this is the case, then you can be smarter about each of its methods creating and releasing memory as necessary, or you can have the singleton listen for the low memory system notifications and behave appropriately.
Essentially, I'd be hard pressed to construct a case where it really made sense for the singleton object itself to be released. A single basic object takes only a handful of bytes in memory, and hurts no one by hanging around.
I know this goes against the design of a singleton
It also goes against the usual memory management patten in Objective-C. Normally, an object gets to retain another object to prevent it from being destroyed, and to release it to allow the object to be destroyed. Explicitly destroying an object, though, isn't something that other objects get to do.
Consider what would happen if object A gets the shared instance S1 of a singleton class S. If A retains S1, S1 will continue to exist even if some class method releases S and sets the global variable that points to the shared instance to nil. When the class later creates a new shared instance, S2, there will be two instances of S, namely S1 and S2. This violates the property that defines the singleton in the first place.
You might be able to get around this problem by overriding -retain and maybe swizzling -release, but that seems like a lot of complexity to solve a problem that shouldn't exist in the first place.
A possible alternative is to reset your shared object instead of trying to destroy it. You could set all it's attributes to some known (possibly invalid) state if you want, and then have a class method the re-initializes the shared object. Just be aware of the effect of all that on any objects that might be using the shared object.
Just about every singleton I've ever written (save for totally UI centric controllers) end up being refactored into not being singletons. Every. Single. One.
Thus, I've stopped writing singletons. I write classes that maintain state in instances, as any normal class should, and do so in isolation from other instances. If they are notification heavy, they always pass self as the notifying object. They have delegates. They maintain internal state. They avoid globals outside of truly global state.
And, often, there may be exactly one instance of said class in my app(s). That one instance acts like a singleton and, in fact, I might even create a convenient way of getting a hold of it, likely through the App's delegate or through a class method (that might even be named sharedInstance sometimes).
Said class includes tear-down code that is typically divided in two pieces; code to persist current state for restoration later and code that releases instance associated resources.
Convenient like a singleton. Ready to be multiply instantiated when needed.
Sure no problem. You provide a new class method: [MyClass killSingleton]; That method releases the singleton and sets its internal reference to nil. The next time someone asks [MyClass sharedSingleton], you go through the same steps you did before to create it.
EDIT: actually, in the old days such a routine could have overridden the release selector, and refused to go away. So as the first comment below states, this is an object with static scope - its kept alive through a static variable keeping a retain count of 1 on the object. However, by adding in a new class method to nil out that ivar (under ARC), thereby releasing it, achieves the desired result. Control over instantiating and releasing the static object is completely done via class methods, so is easy to maintain and debug.
It's against the concept of Singleton, but it can be implemented the following way for an ARC based project
//ARC
#interface Singleton : NSObject
+ (Singleton *)sharedInstance;
+ (void)selfDestruct;
#end
#implementation Singleton
static Singleton *sharedInstance = nil;
+ (Singleton *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[Singleton alloc] init];
}
return sharedInstance;
}
+ (void) selfDestruct {
sharedInstance = nil;
}
#end
//This can be implemented using bool variable. If bool no create new instance.
#interface Singleton : NSObject
+ (Singleton *)sharedInstance;
#end
#implementation Singleton
static Singleton *sharedInstance = nil;
+ (Singleton *)sharedInstance {
if (!keepInstance) {
sharedInstance = [[Singleton alloc] init];
keepInstance = YES;
}
return sharedInstance;
}
#end
I needed to clear out the singleton so I ended up doing the following:
- (void)deleteSingleton{
#synchronized(self) {
if (sharedConfigSingletone != nil) {
sharedConfigSingletone = nil;
}
}
}
Hope it helps.

can we override alloc and dealloc in objective C?

I know that this is rarely required to override the alloc or dealloc methods,but if required is it possible in iPhone programming?
You can and indeed, you should (if using manual memory management) override dealloc to release any resources you hold (not forgetting to call [super dealloc] when finished). Overriding alloc is possible but, as you say, rarely needed.
In general, overriding alloc is only done when you wish to, eg, allocate an object from a pool of available instances, or perhaps allocate a variable amount of storage for the object based on some external parameter. (In C++ you can access the new parameters and allocate based on them, but Objective-C does not give you access to the initXXX parameters.)
I've never attempted any of this, and I suspect that its a bit of a minefield -- you need to study up on the structures and be pretty careful.
As Adam said, you should ALWAYS (in a reference counted environment) override dealloc if there are any retained objects held by your object.
Update: An interesting thing you can do ... in RedClass or a superclass of it code something like:
+(id)alloc {
if (self == [RedClass class]) {
return [BlueClass alloc];
}
else {
return [super alloc];
}
}
The net result is that whenever you execute [RedClass alloc] a BlueCLass object will be returned. (NB: Presumably BlueClass is a subclass of RedClass, or things will get seriously mucked up shortly after the object is returned.)
Not saying that it's a good idea to do this, but it's possible (and I don't offhand know of any cases where it wouldn't work reliably for vanilla user-defined classes). And it does have a few possible uses.
Additional note: In some cases one might want to use [self isSubclassOf:[RedClass class]] rather than == (though that has some serious pitfalls).

always mandatory or sometimes optional?

As i was reading through the book on Objective-C, i came across an example that initialized a class as follows:
ClassName *p = [[ClassName alloc] init];
While it makes sense that first we need to allocate memory to store data ClassName has before initializing, the following works just as well:
ClassName *p = [ClassName alloc];
Is init always needed?
In theory, it's not technically required. That's because NSObject's init method is effectively just return self;. However, in practice, it's absolutely essential. Objects perform internal setup inside the init method - creating internal state, allocating private members, and generally getting ready for action. The init method may not even return the same object as you allocated.
Think of it in two phases: alloc allocates memory, but that's it - it's analogous to Java's new. init configures the state of the memory so that the object can perform it's tasks - analogous to Java calling the constructor. Don't leave it out!
Good question. And you're right. Strictly speacking "init" is not required.
"alloc" does three important things to create an object:
- allocate enough memory to hold all instance variables
- initialize the "isa" instance variable
- all other instances are set to 0
Consider that the "root" Cocoa object, NSObject, simply returns "self" in its init method.
But, if you want to be a good Obj-C citizen, you must use "init". It is part of the "contract" between you, the developer, and the environment.
You should always call one of the initializer methods especially when the class isn't your own. The pointer returned from init isn't necessarily the same as returned by alloc.
Read the documentation:
http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/doc/uid/20000050-init

Why are alloc and init called separately in Objective-C?

Note: I'm relatively new to Objective-C and am coming from Java and PHP.
Could someone explain to me why I always have to first allocate and then initialize an instance?
Couldn't this be done in the init methods like this:
+ (MyClass*)init {
MyClass *instance = [MyClass alloc];
[instance setFoo:#"bla"];
return instance;
}
+ (MyClass*)initWithString:(NSString*)text {
MyClass *instance = [MyClass init];
[instance setFoo:text];
return instance;
}
...
Is this just a relict from the old C days or is there something that I'm not seeing?
I know this isn't a problem as I could as well always call alloc and init, but since it's a bit tedious I'd like to at least know why I'm doing it.
I'm liking the expressiveness of the language so far, but this is something that I want to fully understand in order to think the Objective-C way.
Thank you!
+new ends up sending an +alloc message to the class and an -init message to whatever comes back from +alloc.
The reason that NeXT departed from Stepstone's convention of using the +new message (which was a Smalltalk idea) is that early on, they encountered situations where they wanted to be able to initialize the same object more than once.
Because creating an instance and initializing an instance are two separate jobs.
You send an alloc message to the class to get an uninitialized instance. You must then initialize the instance, and you often have several ways to do that. For example:
myStr = [[NSString alloc] init]; //Empty string
myStr = [[NSString alloc] initWithFormat:#"%#.%#", parentKeyPath, key];
myStr = [[NSString alloc] initWithData:utf16data encoding:NSUnicodeStringEncoding error:&error];
myStr = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error];
Each of these initializes the string in a completely different way. How you initialize the string depends on what you want to initialize it from.
Of course, nobody likes writing alloc and then init and then autorelease every time, so you usually have convenience methods (e.g., stringWithFormat:) that do all three steps for you.
Edit: For more on this topic, including essential insights from commenters, see my blog post “Reunification”.
See NSZone.
+alloc is a shortcut cut for +allocWithZone:, which is a mechanism Cocoa provides for optimizing memory allocation.
So you have the option to do something like this:
foo = [[NSString allocWithZone:MyZone] initWithString:#"Foo"];
foo2 = [foo copyWithZone:MyZone];
The idea behind memory zones is that if you have a large number of similar objects that are frequently allocated and deallocated it may more efficient to use a separate memory zone for those objects.
In order for zoning to be effective you'd want to have +allocWithZone: available to every NSObject subclass, hence you need to separate allocation and initialization. You can create and use all the shortcuts you want, like +new, but underneath it all you need an -init method that initializes an object that has already been allocated.
"Separating the allocation and initialization stages of instance creation provides many benefits. It’s possible to use any variation of the +alloc class method to allocate an instance and then use any available initializer with the new instance.This makes it possible to create your own initialization methods without needing to provide alternate implementations of all allocation methods.
New allocation methods are seldom created because the existing methods meet almost every need. However, one or more new initializers are created for almost every class. Due to the separation of allocation and initialization stages, initializer implementations only have to deal with the variables of new instances and can completely ignore the issues sur- rounding allocation.The separation simplifies the process of writing initializers. Furthermore, Cocoa standard initializers like -initWithCoder: work with instances regardless of the way memory for the instance was allocated.
One negative consequence of the separation of allocation and initialization is the need to be aware of conventions such as the designated initializer.You must know which methods are designated initializers and how to create and document new initializers in sub- classes. In the long run, using designated initializers simplifies software development, but there is an argument to be made that theTwo-Stage Creation pattern adds to the early learning curve for Cocoa developers."
(c) Cocoa Design Patterns by Erik M. Buck and Donald A. Yacktman
You don't have to. You can use [MyClass new]. This is similar to your hypothetical init method.
Basically, Objective-C, which didn't have garbage collection initially, separates the concept of memory allocation and class initialization. That's why there are two distinct methods. When you call alloc, you are explicitly allocating memory.
Most classes have what you are asking for. You have gotten answers before on why this is like it is and why you wouldn't always want to use this all the time but if you read the documentation to classes you will see many class methods that act this way and they are often used.
For NSString you have, for example:
+ (id)string // (Empty string)
+ (id)stringWithFormat:... // Formatted string (like you use)
+ (id)stringWithContentsOfURL:... // String populated with contents of URL
And so on. And you would then use this like: NSString *myString = [NSString stringWithFormat:#"Hello %#\n", userName];
Most other classes have this, like NSArray:
+ (id)array
+ (id)arrayWithContentsOfFile:...
+ (id)arrayWithContentsOfURL:...
+ (id)arrayWithObjects:...
You just need to read the documentation. :) And read the other replies on why you don't want to use this too much.
alloc : Memory is allocated/given to the object-reference. Now reference has the possession of the memory but has not done anything yet. This memory be empty(rarest case) or with some anonymous data.
alloc and init : Allocated memory is cleaned/emptied. Memory is initiated by zero bit.
alloc and initwithdata... : Allocated memory is initiated with desired data respected to properties of the class.
For example when you purchase a plot you get the possession. This plot is given to you as it is, ruined bricks or old house may be there. This is alloc.
When you clean your plot and remove all dirt and litter. This is alloc with init.
When you build that into some valuable house it becomes more meaningful to you. And it is alloc initwith...

What's the deal with NSZoneFree in -(void)dealloc?

In Apple's NSObject documentation, NSZoneFree is called in the - (void)dealloc example code:
- (void)dealloc {
[companion release];
NSZoneFree(private, [self zone])
[super dealloc];
}
You can find it in context over here.
I never had the notion that I should be calling NSZoneFree in my own NSObject subclasses (or what NS_WhateverClass_ subclasses) and can't find anything conclusive on the topic anywhere in the docs.
All I can find about using NSZoneFree is a brief mention in the Memory Management Programming Guide, and an explanation of the function in the Foundation Functions Reference, but none of these docs make it clear to me whether I should worry about it in the context of a dealloc method.
Can anybody clarify when I should put an NSZoneFree call in my own classes' dealloc implementations?
Edit: Thanks for your replies, it's clearer to me now :) — Dirk
NSZoneFree() balances out a call to NSZoneMalloc(), just like -release balances a call to -alloc or -copy and CFRelease() balances a call to CFRetain() or CF*Create*() or, for that matter, free() balances a call to malloc() or calloc().
Given the allocator(s) that the C library uses on Mac OS X, much of this is academic, but best practices say that you release your hold on memory the same way you got it, and in the case of that class, the instance variable private had previously been allocated with NSZoneMalloc().
According to the Foundation Reference:
Returns memory to the zone from which it was allocated. The standard C function free does the same, but spends time finding which zone the memory belongs to.
So, you basically use NSZoneFree(), instead of free(), when cleaing up malloc'd and calloc'd memory. You generally don't need to call it, however.