Note that there are some explanatory texts on larger screens.

plurals
  1. POAccessing NSObject's (superclass) version of allocWithZone while bypassing overriding (subclass) version of allocWithZone
    primarykey
    data
    text
    <p>In iOS Programming Book from Big Nerd Ranch (3rd ed) they say on pg.194 ..a knowledgeable programmer could still create an instance of BNRItemStore via allocWithZone:, which would bypass our sneaky alloc trap.To prevent this possibility, override allocWithZone: in BNRItemStore.m to return the single BNRItemStore instance.</p> <pre><code>+(id) allocWithZone:(NSZone *)zone { return [self sharedStore]; } </code></pre> <p>This statement seems confusing to me. Doesn't this following code not prove this wrong in a way- </p> <pre><code>#import &lt;Foundation/Foundation.h&gt; @interface BNRItemStore : NSObject +(BNRItemStore *)sharedStore; +(id)retrieveObject; @end @implementation BNRItemStore +(BNRItemStore *)sharedStore{ static BNRItemStore *sharedStore=nil; if (!sharedStore){ NSLog(@"Test2"); sharedStore= [[super allocWithZone:nil] init]; } NSLog(@"sharedStore-&gt; %@",sharedStore); return sharedStore; } +(id)allocWithZone:(NSZone *)zone{ NSLog(@"Test1"); return [self sharedStore]; } +(id)alloc{ NSLog(@"Retrieving super object"); NSLog(@"%@", [super allocWithZone:nil]);//Bypassing the subclass version of allocWithZone. return [super allocWithZone:nil]; } @end int main(){ [[BNRItemStore alloc] init]; //the alloc message triggers a call to the subclass (overriding) version of +(id)alloc method } </code></pre> <p>The output is:</p> <ul> <li>2013-10-18 18:24:40.132 BNRItemStore[381:707] Retrieving super object</li> <li>2013-10-18 18:24:40.134 BNRItemStore[381:707] BNRItemStore:0x7f8c72c091e0</li> </ul> <p>If the call [super allocWithZone:nil] inside of subclass 'alloc' method would have triggered a call to subclass allocWithZone,the console would be logging "Test1" and "Test2" and finally would lead to static pointer getting allocated. But this did not happen. This means that if we directly call [NSObject allocWithZone:nil] or [super allocWithZone:nil], the message would not redirect to the overriding version (subclass version) of allocWithZone but will give direct access to NSAllocateObject() function which does the actual allocation. The code of +(id)allocWithZone in NSObject must look somewhat like this-</p> <pre><code>+(id)allocWithZone:(NSZone *)zone{ return NSAllocateObject(); } </code></pre> <p>Had this implementation(NSObject's allocWithZone:) included something like [self allocWithZone], the message dispatch mechanism would have included the subclass version of allocWithZone which would then make us go through the "sneaky" trap involving a call to sharedStore method.Following is the case that I'm talking about. Now if this were the case the code would definitely have infinite-looped.Clearly this isn't the case.</p> <pre><code>+(id)allocWithZone:(NSZone *)zone{ if([self allocWithZone:zone]) //this would trigger a call to subclass ver. which would call sharedStore method which would then have [super allocWithZone:nil].Infinite Loop return NSAllocateObject(); } </code></pre> <p>So can someone clear up this query about this so called "sneaky" trap. Was the trap meant for blocking anyone from instantiating separately .i.e not being able to use NSObject's allocWithZone except when inside of sharedStore method ? Pls clarify..</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload