Type extension e.g. variables

Is there a way to somehow emulate the behavior of a category for a class with respect to instance variables rather than methods?

I have a ClassA , and I want to keep its name after extending it with new methods AND ivars from another class ( ClassB ). Of course, I can inherit ClassA , but the resulting class will have a different name.

For adding methods, this is not a problem - a category would be a good solution.

UPDATE: ClassA used as the owner of the file for XIB, and these fields that need to be expanded are IBOutlet s. Therefore, I need them at the build stage.

+5
ios objective-c iphone
Feb 03 '11 at 13:57
source share
3 answers

I researched this question by playing around associative links (thanks to Ole ), with static variable methods, swizzling methods, and finally come up with this simple solution (no runtime). I just use the "categorized" class only to return a pointer to a derived class, which, of course, may contain additional ivars. As a result, I get one unexpected advantage: I can call methods of the super class, which is impossible when expanding into categories.

Class extension example ( verified ):

ClassA + ClassB.h

 @protocol _ClassB_Protocol @optional // to avoid warnings - (IBAction) onClick:(id)sender; @property (nonatomic, retain) IBOutlet UIButton *aButton; @end @interface ClassA (_ClassA_Category) <_ClassB_Protocol> @end @interface ClassB: ClassA <_ClassB_Protocol> { UIButton *aButton; // _ivar_ to add } @end 

ClassA + ClassB.m

 @implementation ClassA (_ClassA_Category) // this will be called first on [ClassA alloc] or [ClassA allocWithZone:(NSZone *)zone] +(id) alloc { if ([self isEqual: [ClassA class]]) { return [ClassB alloc]; } else { return [super alloc]; } } @end @implementation ClassB: ClassA @synthesize aButton; -(void) dealloc { [aButton release]; [super dealloc]; // this is impossible for an ordinary category } - (void) onClick:(id)sender { // some code here } @end 

Now we have the same time:

  • ClassB "extends" ClassA (category mode);
  • ClassB inherits ClassA ( ClassB can call ClassA methods);
  • ClassB can be obtained through the ClassA name (category method)
+3
Feb 04 '11 at 15:09
source share

Since iPhone uses the modern Objective-C runtime, you can use associative links to add data to instances without declaring instance variables. See the documentation for objc_setAssociatedObject etc.

If you transfer calls at run time to standard access methods, this will be very simple to use.

+6
Feb 03 2018-11-11T00:
source share

I put Martin's example in a trivial application replacing ClassA NSData, ClassB with XXData and onClick with getIvar and calling it (Mac OS X 10.6.6, Xcode 4 Final) with

 NSData * data = [NSData data]; NSLog(@"%@", [data getIvar]); 

It does not work with "- [NSConcreteData getIvar]: unrecognized selector sent to instance" ..

It failed because the above code "alloc" in the NSData category (which returns a pointer to a derived class) is not called. If instead, "alloc" is called explicitly, as in:

 NSData * data = [[NSData alloc] init]; NSLog(@"%@", [data getIvar]); 

then everything is fine.

+2
Mar 20 '11 at 17:27
source share



All Articles