swizzling a class to a subclass inorder to add ivars (& methods) to a class

  • The mantra for categories and posed class is that you cannot add
    ivars to a category or a posed class -- leaving you to fiddle with
    mutable dictionarys and tablemaps to implement extra variables. (ugh!)

    However, you can add ivars to a subclass -- so I got to thinking --
    can you redirect an allocation for a class to a subclass so that for
    all intents and purposes you can add ivars.

    In playing around, I found that by swizzling the classMethod:  +
    [NSObject alloc], you can redirect the allocation of a class to a
    subclass as follows:
    //----------------------------------------------------------------------
    ------------------------------------------------------------------

    @interface SubClass: AnyClass
    {
    NSString * extraIvar;
    }

    @end

    static IMP oldAlloc = NULL;
    @implementation NSObject (myCategory)
    +(id) MYalloc{
    id result;

    if(self == [AnyClass class]){
      self = objc_getClass("SubClass"); //restate the class as the subclass
      result = NSAllocateObject(self,0,nil);  // allocate the subclass
    }
    else
      result = oldAlloc(self,_cmd);
    return result;
    }

    + (void) load {
    oldAlloc = replaceClassMethod(@selector(alloc),self,@selector
    (MYalloc),self); // standard class method swizzle the alloc method of
    NSObject
    }
    //----------------------------------------------------------------------
    ------------------------------------------------------------------

    One catch would be that any  factory methods and any instance init
    methods may have to be reproduced in the subclass if you want to init
    your subclass ivars
    eg.

    (id) init___:(id) anObject{
    if ((self = [super init___:anObject])){
      extraIvar = [[NSString alloc] initWithString:@"test iVar"];
    }
    return self;
    }

    Another catch would be that any test directly for an instance's class
    type would fail (but tests for isKindOfClass: would be ok)

    In anycase -- technically this is possible -- I have it working on
    some test code

    However -- IS IT SAFE ??  -- if no -- why not ---
    if  "sorta" -- what are the gotchas and pitfalls?
  • Hi Scott, perhaps I'm being stupid here, but how about using
    poseAsClass: ?

    Mike.

    On 30 Oct 2006, at 04:08, Scott Morrison wrote:

    >
    > The mantra for categories and posed class is that you cannot add
    > ivars to a category or a posed class -- leaving you to fiddle with
    > mutable dictionarys and tablemaps to implement extra variables. (ugh!)
    >
    > However, you can add ivars to a subclass -- so I got to thinking --
    > can you redirect an allocation for a class to a subclass so that
    > for all intents and purposes you can add ivars.
    >
    > In playing around, I found that by swizzling the classMethod:  +
    > [NSObject alloc], you can redirect the allocation of a class to a
    > subclass as follows:
    > //--------------------------------------------------------------------
    > --------------------------------------------------------------------
    >
    > @interface SubClass: AnyClass
    > {
    > NSString * extraIvar;
    > }
    >
    > @end
    >
    > static IMP oldAlloc = NULL;
    > @implementation NSObject (myCategory)
    > +(id) MYalloc{
    > id result;
    >
    > if(self == [AnyClass class]){
    > self = objc_getClass("SubClass"); //restate the class as the
    > subclass
    > result = NSAllocateObject(self,0,nil);  // allocate the subclass
    > }
    > else
    > result = oldAlloc(self,_cmd);
    > return result;
    > }
    >
    > + (void) load {
    > oldAlloc = replaceClassMethod(@selector(alloc),self,@selector
    > (MYalloc),self); // standard class method swizzle the alloc method
    > of NSObject
    > }
    > //--------------------------------------------------------------------
    > --------------------------------------------------------------------
    >
    >
    > One catch would be that any  factory methods and any instance init
    > methods may have to be reproduced in the subclass if you want to
    > init your subclass ivars
    > eg.
    >
    > (id) init___:(id) anObject{
    > if ((self = [super init___:anObject])){
    > extraIvar = [[NSString alloc] initWithString:@"test iVar"];
    > }
    > return self;
    > }
    >
    >
    > Another catch would be that any test directly for an instance's
    > class type would fail (but tests for isKindOfClass: would be ok)
    >
    >
    > In anycase -- technically this is possible -- I have it working on
    > some test code
    >
    > However -- IS IT SAFE ??  -- if no -- why not ---
    > if  "sorta" -- what are the gotchas and pitfalls?
    >
    >
    >
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/mike.abdullah%
    > 40gmail.com
    >
    > This email sent to <mike.abdullah...>
  • I just reviewed a WWDC session that indicated that poseAsClass: was
    deprecated in 10.5 and would be going away.  It may even be removed in 64
    bit in 10.5.

    Michael

    > -----Original Message-----
    > From: cocoa-dev-bounces+lattam=<mac.com...> [mailto:cocoa-dev-
    > bounces+lattam=<mac.com...>] On Behalf Of Mike Abdullah
    > Sent: Monday, October 30, 2006 12:55 AM
    > To: Scott Morrison
    > Cc: <cocoa-dev...>
    > Subject: Re: swizzling a class to a subclass inorder to add ivars (&
    > methods) to a class
    >
    > Hi Scott, perhaps I'm being stupid here, but how about using
    > poseAsClass: ?
    >
    > Mike.
    >
    > On 30 Oct 2006, at 04:08, Scott Morrison wrote:
    >
    >>
    >> The mantra for categories and posed class is that you cannot add
    >> ivars to a category or a posed class -- leaving you to fiddle with
    >> mutable dictionarys and tablemaps to implement extra variables. (ugh!)
    >>
    >> However, you can add ivars to a subclass -- so I got to thinking --
    >> can you redirect an allocation for a class to a subclass so that
    >> for all intents and purposes you can add ivars.
    >>
    >> In playing around, I found that by swizzling the classMethod:  +
    >> [NSObject alloc], you can redirect the allocation of a class to a
    >> subclass as follows:
    >> //--------------------------------------------------------------------
    >> --------------------------------------------------------------------
    >>
    >> @interface SubClass: AnyClass
    >> {
    >> NSString * extraIvar;
    >> }
    >>
    >> @end
    >>
    >> static IMP oldAlloc = NULL;
    >> @implementation NSObject (myCategory)
    >> +(id) MYalloc{
    >> id result;
    >>
    >> if(self == [AnyClass class]){
    >> self = objc_getClass("SubClass"); //restate the class as the
    >> subclass
    >> result = NSAllocateObject(self,0,nil);  // allocate the
    > subclass
    >> }
    >> else
    >> result = oldAlloc(self,_cmd);
    >> return result;
    >> }
    >>
    >> + (void) load {
    >> oldAlloc = replaceClassMethod(@selector(alloc),self,@selector
    >> (MYalloc),self); // standard class method swizzle the alloc method
    >> of NSObject
    >> }
    >> //--------------------------------------------------------------------
    >> --------------------------------------------------------------------
    >>
    >>
    >> One catch would be that any  factory methods and any instance init
    >> methods may have to be reproduced in the subclass if you want to
    >> init your subclass ivars
    >> eg.
    >>
    >> (id) init___:(id) anObject{
    >> if ((self = [super init___:anObject])){
    >> extraIvar = [[NSString alloc] initWithString:@"test iVar"];
    >> }
    >> return self;
    >> }
    >>
    >>
    >> Another catch would be that any test directly for an instance's
    >> class type would fail (but tests for isKindOfClass: would be ok)
    >>
    >>
    >> In anycase -- technically this is possible -- I have it working on
    >> some test code
    >>
    >> However -- IS IT SAFE ??  -- if no -- why not ---
    >> if  "sorta" -- what are the gotchas and pitfalls?
    >>
    >>
    >>
    >>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will be ignored.
    >> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >> http://lists.apple.com/mailman/options/cocoa-dev/mike.abdullah%
    >> 40gmail.com
    >>
    >> This email sent to <mike.abdullah...>
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<lattam...>
    >
    > This email sent to <lattam...>
  • oh :(

    I can understand the reasoning (the whole process is a little
    dangerous for shipping apps), but for debugging purposes it can be
    damn handy!

    Mike.

    On 30 Oct 2006, at 16:53, Michael Latta wrote:

    > I just reviewed a WWDC session that indicated that poseAsClass: was
    > deprecated in 10.5 and would be going away.  It may even be removed
    > in 64
    > bit in 10.5.
    >
    > Michael
    >
    >
    >> -----Original Message-----
    >> From: cocoa-dev-bounces+lattam=<mac.com...>
    >> [mailto:cocoa-dev-
    >> bounces+lattam=<mac.com...>] On Behalf Of Mike Abdullah
    >> Sent: Monday, October 30, 2006 12:55 AM
    >> To: Scott Morrison
    >> Cc: <cocoa-dev...>
    >> Subject: Re: swizzling a class to a subclass inorder to add ivars (&
    >> methods) to a class
    >>
    >> Hi Scott, perhaps I'm being stupid here, but how about using
    >> poseAsClass: ?
    >>
    >> Mike.
    >>
    >> On 30 Oct 2006, at 04:08, Scott Morrison wrote:
    >>
    >>>
    >>> The mantra for categories and posed class is that you cannot add
    >>> ivars to a category or a posed class -- leaving you to fiddle with
    >>> mutable dictionarys and tablemaps to implement extra variables.
    >>> (ugh!)
    >>>
    >>> However, you can add ivars to a subclass -- so I got to thinking --
    >>> can you redirect an allocation for a class to a subclass so that
    >>> for all intents and purposes you can add ivars.
    >>>
    >>> In playing around, I found that by swizzling the classMethod:  +
    >>> [NSObject alloc], you can redirect the allocation of a class to a
    >>> subclass as follows:
    >>> //------------------------------------------------------------------
    >>> --
    >>> --------------------------------------------------------------------
    >>>
    >>> @interface SubClass: AnyClass
    >>> {
    >>> NSString * extraIvar;
    >>> }
    >>>
    >>> @end
    >>>
    >>> static IMP oldAlloc = NULL;
    >>> @implementation NSObject (myCategory)
    >>> +(id) MYalloc{
    >>> id result;
    >>>
    >>> if(self == [AnyClass class]){
    >>> self = objc_getClass("SubClass"); //restate the class as the
    >>> subclass
    >>> result = NSAllocateObject(self,0,nil);  // allocate the
    >> subclass
    >>> }
    >>> else
    >>> result = oldAlloc(self,_cmd);
    >>> return result;
    >>> }
    >>>
    >>> + (void) load {
    >>> oldAlloc = replaceClassMethod(@selector(alloc),self,@selector
    >>> (MYalloc),self); // standard class method swizzle the alloc method
    >>> of NSObject
    >>> }
    >>> //------------------------------------------------------------------
    >>> --
    >>> --------------------------------------------------------------------
    >>>
    >>>
    >>> One catch would be that any  factory methods and any instance init
    >>> methods may have to be reproduced in the subclass if you want to
    >>> init your subclass ivars
    >>> eg.
    >>>
    >>> (id) init___:(id) anObject{
    >>> if ((self = [super init___:anObject])){
    >>> extraIvar = [[NSString alloc] initWithString:@"test iVar"];
    >>> }
    >>> return self;
    >>> }
    >>>
    >>>
    >>> Another catch would be that any test directly for an instance's
    >>> class type would fail (but tests for isKindOfClass: would be ok)
    >>>
    >>>
    >>> In anycase -- technically this is possible -- I have it working on
    >>> some test code
    >>>
    >>> However -- IS IT SAFE ??  -- if no -- why not ---
    >>> if  "sorta" -- what are the gotchas and pitfalls?
    >>>
    >>>
    >>>
    >>>
    >>> _______________________________________________
    >>> Do not post admin requests to the list. They will be ignored.
    >>> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >>> Help/Unsubscribe/Update your Subscription:
    >>> http://lists.apple.com/mailman/options/cocoa-dev/mike.abdullah%
    >>> 40gmail.com
    >>>
    >>> This email sent to <mike.abdullah...>
    >>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will be ignored.
    >> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >> http://lists.apple.com/mailman/options/cocoa-dev/<lattam...>
    >>
    >> This email sent to <lattam...>
    >
  • They are making several changes in 64 bit to allow them more control over
    the metadata which gives them more room for performance optimizations and
    such.  They are replacing all metadata structures with APIs and hiding the
    implementation details (which is how it should be).

    One of the outcomes of this is that when a superclass grows in size it does
    not break subclasses that added ivars!  No more need to reserve space for
    future use.

    Michael

    > -----Original Message-----
    > From: Mike Abdullah [mailto:<mike.abdullah...>]
    > Sent: Monday, October 30, 2006 9:16 AM
    > To: Michael Latta
    > Cc: <cocoa-dev...>
    > Subject: Re: swizzling a class to a subclass inorder to add ivars (&
    > methods) to a class
    >
    > oh :(
    >
    > I can understand the reasoning (the whole process is a little
    > dangerous for shipping apps), but for debugging purposes it can be
    > damn handy!
    >
    > Mike.
    >
    > On 30 Oct 2006, at 16:53, Michael Latta wrote:
    >
    >> I just reviewed a WWDC session that indicated that poseAsClass: was
    >> deprecated in 10.5 and would be going away.  It may even be removed
    >> in 64
    >> bit in 10.5.
    >>
    >> Michael
    >>
    >>
    >>> -----Original Message-----
    >>> From: cocoa-dev-bounces+lattam=<mac.com...>
    >>> [mailto:cocoa-dev-
    >>> bounces+lattam=<mac.com...>] On Behalf Of Mike Abdullah
    >>> Sent: Monday, October 30, 2006 12:55 AM
    >>> To: Scott Morrison
    >>> Cc: <cocoa-dev...>
    >>> Subject: Re: swizzling a class to a subclass inorder to add ivars (&
    >>> methods) to a class
    >>>
    >>> Hi Scott, perhaps I'm being stupid here, but how about using
    >>> poseAsClass: ?
    >>>
    >>> Mike.
    >>>
    >>> On 30 Oct 2006, at 04:08, Scott Morrison wrote:
    >>>
    >>>>
    >>>> The mantra for categories and posed class is that you cannot add
    >>>> ivars to a category or a posed class -- leaving you to fiddle with
    >>>> mutable dictionarys and tablemaps to implement extra variables.
    >>>> (ugh!)
    >>>>
    >>>> However, you can add ivars to a subclass -- so I got to thinking --
    >>>> can you redirect an allocation for a class to a subclass so that
    >>>> for all intents and purposes you can add ivars.
    >>>>
    >>>> In playing around, I found that by swizzling the classMethod:  +
    >>>> [NSObject alloc], you can redirect the allocation of a class to a
    >>>> subclass as follows:
    >>>> //------------------------------------------------------------------
    >>>> --
    >>>> --------------------------------------------------------------------
    >>>>
    >>>> @interface SubClass: AnyClass
    >>>> {
    >>>> NSString * extraIvar;
    >>>> }
    >>>>
    >>>> @end
    >>>>
    >>>> static IMP oldAlloc = NULL;
    >>>> @implementation NSObject (myCategory)
    >>>> +(id) MYalloc{
    >>>> id result;
    >>>>
    >>>> if(self == [AnyClass class]){
    >>>> self = objc_getClass("SubClass"); //restate the class as the
    >>>> subclass
    >>>> result = NSAllocateObject(self,0,nil);  // allocate the
    >>> subclass
    >>>> }
    >>>> else
    >>>> result = oldAlloc(self,_cmd);
    >>>> return result;
    >>>> }
    >>>>
    >>>> + (void) load {
    >>>> oldAlloc = replaceClassMethod(@selector(alloc),self,@selector
    >>>> (MYalloc),self); // standard class method swizzle the alloc method
    >>>> of NSObject
    >>>> }
    >>>> //------------------------------------------------------------------
    >>>> --
    >>>> --------------------------------------------------------------------
    >>>>
    >>>>
    >>>> One catch would be that any  factory methods and any instance init
    >>>> methods may have to be reproduced in the subclass if you want to
    >>>> init your subclass ivars
    >>>> eg.
    >>>>
    >>>> (id) init___:(id) anObject{
    >>>> if ((self = [super init___:anObject])){
    >>>> extraIvar = [[NSString alloc] initWithString:@"test iVar"];
    >>>> }
    >>>> return self;
    >>>> }
    >>>>
    >>>>
    >>>> Another catch would be that any test directly for an instance's
    >>>> class type would fail (but tests for isKindOfClass: would be ok)
    >>>>
    >>>>
    >>>> In anycase -- technically this is possible -- I have it working on
    >>>> some test code
    >>>>
    >>>> However -- IS IT SAFE ??  -- if no -- why not ---
    >>>> if  "sorta" -- what are the gotchas and pitfalls?
    >>>>
    >>>>
    >>>>
    >>>>
    >>>> _______________________________________________
    >>>> Do not post admin requests to the list. They will be ignored.
    >>>> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >>>> Help/Unsubscribe/Update your Subscription:
    >>>> http://lists.apple.com/mailman/options/cocoa-dev/mike.abdullah%
    >>>> 40gmail.com
    >>>>
    >>>> This email sent to <mike.abdullah...>
    >>>
    >>> _______________________________________________
    >>> Do not post admin requests to the list. They will be ignored.
    >>> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >>> Help/Unsubscribe/Update your Subscription:
    >>> http://lists.apple.com/mailman/options/cocoa-dev/<lattam...>
    >>>
    >>> This email sent to <lattam...>
    >>
  • On 10/30/06, Michael Latta <lattam...> wrote:
    > They are making several changes in 64 bit to allow them more control over
    > the metadata which gives them more room for performance optimizations and
    > such.  They are replacing all metadata structures with APIs and hiding the
    > implementation details (which is how it should be).
    >
    > One of the outcomes of this is that when a superclass grows in size it does
    > not break subclasses that added ivars!  No more need to reserve space for
    > future use.

    Don't forget things are still under NDA.

    -Shawn
  • Given that the WWDC sessions were given to the public I assumed that content
    was not under NDA.  Was I incorrect?

    Michael

    > -----Original Message-----
    > From: Shawn Erickson [mailto:<shawnce...>]
    > Sent: Monday, October 30, 2006 9:38 AM
    > To: Michael Latta
    > Cc: Mike Abdullah; <cocoa-dev...>
    > Subject: Re: RE: swizzling a class to a subclass inorder to add ivars (&
    > methods) to a class
    >
    > On 10/30/06, Michael Latta <lattam...> wrote:
    >> They are making several changes in 64 bit to allow them more control
    > over
    >> the metadata which gives them more room for performance optimizations
    > and
    >> such.  They are replacing all metadata structures with APIs and hiding
    > the
    >> implementation details (which is how it should be).
    >>
    >> One of the outcomes of this is that when a superclass grows in size it
    > does
    >> not break subclasses that added ivars!  No more need to reserve space
    > for
    >> future use.
    >
    > Don't forget things are still under NDA.
    >
    > -Shawn
  • On Oct 30, 2006, at 12:46 PM, Michael Latta wrote:

    > Given that the WWDC sessions were given to the public I assumed that
    > content
    > was not under NDA.  Was I incorrect?

    You are incorrect.  All this information is still under NDA.  The
    sessions were only made available to those who have signed non-
    disclosure agreements (those with Select or Premier developer program
    status, or those who attended WWDC).
  • Thanks for the clarification.  I was unaware that WWDC attenees signed an
    NDA.

    Michael

    > -----Original Message-----
    > From: Scott Anguish [mailto:<scott...>]
    > Sent: Monday, October 30, 2006 9:58 AM
    > To: Michael Latta
    > Cc: 'Shawn Erickson'; <cocoa-dev...>
    > Subject: [moderator] Re: swizzling a class to a subclass inorder to add
    > ivars (& methods) to a class
    >
    >
    > On Oct 30, 2006, at 12:46 PM, Michael Latta wrote:
    >
    >> Given that the WWDC sessions were given to the public I assumed that
    >> content
    >> was not under NDA.  Was I incorrect?
    >
    >
    > You are incorrect.  All this information is still under NDA.  The
    > sessions were only made available to those who have signed non-
    > disclosure agreements (those with Select or Premier developer program
    > status, or those who attended WWDC).
  • On 10/30/06, Michael Latta <lattam...> wrote:
    > Thanks for the clarification.  I was unaware that WWDC attenees signed an
    > NDA.

    "Note that all information presented or provided to you by Apple
    through the Leopard Dev Center is considered Confidential Information
    and is subject to the terms and conditions of your ADC Membership
    Agreement with Apple."

    "Note that with the exception of the WWDC 2006 Keynote, all
    information presented or provided to you by Apple during WWDC 2006,
    including the information on the Attendee Site, is considered
    Confidential Information and is subject to the terms and conditions of
    your ADC Membership Agreement with Apple."

    -Shawn
  • Apart from all the WWDC NDA stuff -- (which is pretty hard to miss
    considering they have that on every opening slide of each
    presentation, and was  in reminders all over Moscone)  Lets get back
    to the original question.....

    Is it OK to swizzle the alloc method to return an allocated subclass
    rather than the superclass that was whose allocation was requested.
    What are problems associated with this? -- Yes -- there may be hidden
    implementation stuff that you are mucking about it.  but if you know
    the classes involved  -- is there a problem?

    From what I seen of some things (from google searches), this is done
    in a variety of situations (eg [NSDictionary  alloc] to return
    different private implementations depending on a variety of situations)

    Scott
  • On Oct 30, 2006, at 1:22 PM, Scott Morrison wrote:

    > Apart from all the WWDC NDA stuff -- (which is pretty hard to miss
    > considering they have that on every opening slide of each
    > presentation, and was  in reminders all over Moscone)  Lets get
    > back to the original question.....
    >
    >
    > Is it OK to swizzle the alloc method to return an allocated
    > subclass rather than the superclass that was whose allocation was
    > requested.  What are problems associated with this? -- Yes -- there
    > may be hidden implementation stuff that you are mucking about it.
    > but if you know the classes involved  -- is there a problem?
    >
    >
    >
    > From what I seen of some things (from google searches), this is
    > done in a variety of situations (eg [NSDictionary  alloc] to return
    > different private implementations depending on a variety of
    > situations)

    I am pretty sure this is a common occurrence in AppKit/Cocoa;
    NSString does it too.

    Other than the fact that introspection will return results that you
    might not have expected, it probably isn't a problem. (e.g. if you
    have code which checks the class name of an object to determine its
    behavior, that code might break.)
  • On 10/30/06, Scott Morrison <smorr...> wrote:
    > Apart from all the WWDC NDA stuff -- (which is pretty hard to miss
    > considering they have that on every opening slide of each
    > presentation, and was  in reminders all over Moscone)  Lets get back
    > to the original question.....
    >
    >
    > Is it OK to swizzle the alloc method to return an allocated subclass
    > rather than the superclass that was whose allocation was requested.
    > What are problems associated with this? -- Yes -- there may be hidden
    > implementation stuff that you are mucking about it.  but if you know
    > the classes involved  -- is there a problem?

    If you know all of the classes involved, there really isn't a problem.
    However, I can envisage some problems with ivar layout if you are
    trying to replace a class that itself has subclasses over which you
    have no control.

    --
    Clark S. Cox III
    <clarkcox3...>
  • Can you access:
    struct objc_ivar_list *ivars;
    from a class, taking it and an objc_ivar_list that you create, and
    set the "ivars" of the class to be a new objc_ivar_list created by
    appending the original, and the new ivars you wish to add?

    struct objc_ivar_list * newlist = (objc_ivar_list *) malloc (sizeof
    (original_list) + sizeof(new_list));
    then set all the ivars?

    Something like that?

    Dustin Kick

    On Oct 29, 2006, at 10:08 PM, Scott Morrison wrote:

    >
    > The mantra for categories and posed class is that you cannot add
    > ivars to a category or a posed class -- leaving you to fiddle with
    > mutable dictionarys and tablemaps to implement extra variables. (ugh!)
    >
    > However, you can add ivars to a subclass -- so I got to thinking --
    > can you redirect an allocation for a class to a subclass so that
    > for all intents and purposes you can add ivars.
    >
    > In playing around, I found that by swizzling the classMethod:  +
    > [NSObject alloc], you can redirect the allocation of a class to a
    > subclass as follows:
    > //--------------------------------------------------------------------
    > --------------------------------------------------------------------
    >
    > @interface SubClass: AnyClass
    > {
    > NSString * extraIvar;
    > }
    >
    > @end
    >
    > static IMP oldAlloc = NULL;
    > @implementation NSObject (myCategory)
    > +(id) MYalloc{
    > id result;
    >
    > if(self == [AnyClass class]){
    > self = objc_getClass("SubClass"); //restate the class as the
    > subclass
    > result = NSAllocateObject(self,0,nil);  // allocate the subclass
    > }
    > else
    > result = oldAlloc(self,_cmd);
    > return result;
    > }
    >
    > + (void) load {
    > oldAlloc = replaceClassMethod(@selector(alloc),self,@selector
    > (MYalloc),self); // standard class method swizzle the alloc method
    > of NSObject
    > }
    > //--------------------------------------------------------------------
    > --------------------------------------------------------------------
    >
    >
    > One catch would be that any  factory methods and any instance init
    > methods may have to be reproduced in the subclass if you want to
    > init your subclass ivars
    > eg.
    >
    > (id) init___:(id) anObject{
    > if ((self = [super init___:anObject])){
    > extraIvar = [[NSString alloc] initWithString:@"test iVar"];
    > }
    > return self;
    > }
    >
    >
    > Another catch would be that any test directly for an instance's
    > class type would fail (but tests for isKindOfClass: would be ok)
    >
    >
    > In anycase -- technically this is possible -- I have it working on
    > some test code
    >
    > However -- IS IT SAFE ??  -- if no -- why not ---
    > if  "sorta" -- what are the gotchas and pitfalls?
    >
    >
    >
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/mac_vieuxnez%
    > 40mac.com
    >
    > This email sent to <mac_vieuxnez...>
  • ooooooh  that sounds even more dangerous than swizzling +[NSObject
    alloc] !

    some problems with this that I could see is that happens after
    allocation and initialization assumedly  -- that you would have to
    copy all pointers/data over from oldList to new list and that you
    have to guard against leaks.

    Anything working with pointers to the ivars may be foobared.. and
    this is off the top of my head.

    I think that this is something you would want to do at instance
    creation -- not a reordering of things after the fact.

    On 1-Nov-06, at 10:39 PM, Dustin Robert Kick wrote:

    > Can you access:
    > struct objc_ivar_list *ivars;
    > from a class, taking it and an objc_ivar_list that you create, and
    > set the "ivars" of the class to be a new objc_ivar_list created by
    > appending the original, and the new ivars you wish to add?
    >
    > struct objc_ivar_list * newlist = (objc_ivar_list *) malloc (sizeof
    > (original_list) + sizeof(new_list));
    > then set all the ivars?
    >
    > Something like that?
    >
    >
    > Dustin Kick
    >
    >
    > On Oct 29, 2006, at 10:08 PM, Scott Morrison wrote:
    >
    >>
    >> The mantra for categories and posed class is that you cannot add
    >> ivars to a category or a posed class -- leaving you to fiddle with
    >> mutable dictionarys and tablemaps to implement extra variables.
    >> (ugh!)
    >>
    >> However, you can add ivars to a subclass -- so I got to thinking --
    >> can you redirect an allocation for a class to a subclass so that
    >> for all intents and purposes you can add ivars.
    >>
    >> In playing around, I found that by swizzling the classMethod:  +
    >> [NSObject alloc], you can redirect the allocation of a class to a
    >> subclass as follows:
    >> //-------------------------------------------------------------------
    >> ---------------------------------------------------------------------
    >>
    >> @interface SubClass: AnyClass
    >> {
    >> NSString * extraIvar;
    >> }
    >>
    >> @end
    >>
    >> static IMP oldAlloc = NULL;
    >> @implementation NSObject (myCategory)
    >> +(id) MYalloc{
    >> id result;
    >>
    >> if(self == [AnyClass class]){
    >> self = objc_getClass("SubClass"); //restate the class as the
    >> subclass
    >> result = NSAllocateObject(self,0,nil);  // allocate the subclass
    >> }
    >> else
    >> result = oldAlloc(self,_cmd);
    >> return result;
    >> }
    >>
    >> + (void) load {
    >> oldAlloc = replaceClassMethod(@selector(alloc),self,@selector
    >> (MYalloc),self); // standard class method swizzle the alloc method
    >> of NSObject
    >> }
    >> //-------------------------------------------------------------------
    >> ---------------------------------------------------------------------
    >>
    >>
    >> One catch would be that any  factory methods and any instance init
    >> methods may have to be reproduced in the subclass if you want to
    >> init your subclass ivars
    >> eg.
    >>
    >> (id) init___:(id) anObject{
    >> if ((self = [super init___:anObject])){
    >> extraIvar = [[NSString alloc] initWithString:@"test iVar"];
    >> }
    >> return self;
    >> }
    >>
    >>
    >> Another catch would be that any test directly for an instance's
    >> class type would fail (but tests for isKindOfClass: would be ok)
    >>
    >>
    >> In anycase -- technically this is possible -- I have it working on
    >> some test code
    >>
    >> However -- IS IT SAFE ??  -- if no -- why not ---
    >> if  "sorta" -- what are the gotchas and pitfalls?
    >>
    >>
    >>
    >>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will be ignored.
    >> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >> http://lists.apple.com/mailman/options/cocoa-dev/mac_vieuxnez%
    >> 40mac.com
    >>
    >> This email sent to <mac_vieuxnez...>
    >

    ________________________________
    Scott Morrison <smorr...>
    Creator of Mail Act-On and Mail Tags plug-ins for OS X Mail.app.
    <http://www.indev.ca/>
  • On Nov 1, 2006, at 7:39 PM, Dustin Robert Kick wrote:
    > Can you access:
    > struct objc_ivar_list *ivars;
    > from a class, taking it and an objc_ivar_list that you create, and
    > set the "ivars" of the class to be a new objc_ivar_list created by
    > appending the original, and the new ivars you wish to add?
    >
    > struct objc_ivar_list * newlist = (objc_ivar_list *) malloc (sizeof
    > (original_list) + sizeof(new_list));
    > then set all the ivars?
    >
    > Something like that?

    Well... you *could* do that, but it buys you very little.

    First, it'll break all subclasses.  Objective-C suffers from the
    fragile base class issue in regards to instance variables.  You
    simply can't change the layout of the ivars of a class without
    requiring all subclasses and categories (that access the ivars) to
    also be recompiled in light of that new layout.

    b.bum
  • I have some code that does just that. It hasn't been tested in real
    apps (and I wouldn't recommend it either), but it worked in a simple
    test app. The code is available from http://www.dpompa.com/?p=36
    under BSD license, so you can freely use it if you wish.

    Have fun, :)
    - Ofri

    - - - - - - - - - - - - - - - - - - -
    http://www.dpompa.com
    - - - - - - - - - - - - - - - - - - -

    On 02/11/2006, at 05:39, Dustin Robert Kick wrote:

    > Can you access:
    > struct objc_ivar_list *ivars;
    > from a class, taking it and an objc_ivar_list that you create, and
    > set the "ivars" of the class to be a new objc_ivar_list created by
    > appending the original, and the new ivars you wish to add?
    >
    > struct objc_ivar_list * newlist = (objc_ivar_list *) malloc (sizeof
    > (original_list) + sizeof(new_list));
    > then set all the ivars?
    >
    > Something like that?
    >
    >
    > Dustin Kick
    >
    >
    > On Oct 29, 2006, at 10:08 PM, Scott Morrison wrote:
    >
    >>
    >> The mantra for categories and posed class is that you cannot add
    >> ivars to a category or a posed class -- leaving you to fiddle with
    >> mutable dictionarys and tablemaps to implement extra variables.
    >> (ugh!)
    >>
    >> However, you can add ivars to a subclass -- so I got to thinking --
    >> can you redirect an allocation for a class to a subclass so that
    >> for all intents and purposes you can add ivars.
    >>
    >> In playing around, I found that by swizzling the classMethod:  +
    >> [NSObject alloc], you can redirect the allocation of a class to a
    >> subclass as follows:
    >> //-------------------------------------------------------------------
    >> ---------------------------------------------------------------------
    >>
    >> @interface SubClass: AnyClass
    >> {
    >> NSString * extraIvar;
    >> }
    >>
    >> @end
    >>
    >> static IMP oldAlloc = NULL;
    >> @implementation NSObject (myCategory)
    >> +(id) MYalloc{
    >> id result;
    >>
    >> if(self == [AnyClass class]){
    >> self = objc_getClass("SubClass"); //restate the class as the
    >> subclass
    >> result = NSAllocateObject(self,0,nil);  // allocate the subclass
    >> }
    >> else
    >> result = oldAlloc(self,_cmd);
    >> return result;
    >> }
    >>
    >> + (void) load {
    >> oldAlloc = replaceClassMethod(@selector(alloc),self,@selector
    >> (MYalloc),self); // standard class method swizzle the alloc method
    >> of NSObject
    >> }
    >> //-------------------------------------------------------------------
    >> ---------------------------------------------------------------------
    >>
    >>
    >> One catch would be that any  factory methods and any instance init
    >> methods may have to be reproduced in the subclass if you want to
    >> init your subclass ivars
    >> eg.
    >>
    >> (id) init___:(id) anObject{
    >> if ((self = [super init___:anObject])){
    >> extraIvar = [[NSString alloc] initWithString:@"test iVar"];
    >> }
    >> return self;
    >> }
    >>
    >>
    >> Another catch would be that any test directly for an instance's
    >> class type would fail (but tests for isKindOfClass: would be ok)
    >>
    >>
    >> In anycase -- technically this is possible -- I have it working on
    >> some test code
    >>
    >> However -- IS IT SAFE ??  -- if no -- why not ---
    >> if  "sorta" -- what are the gotchas and pitfalls?
    >>
    >>
    >>
    >>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will be ignored.
    >> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >> http://lists.apple.com/mailman/options/cocoa-dev/mac_vieuxnez%
    >> 40mac.com
    >>
    >> This email sent to <mac_vieuxnez...>
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/ofri.wolfus%
    > 40gmail.com
    >
    > This email sent to <ofri.wolfus...>
previous month october 2006 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today