Defining a property in iOS class extension

此生再无相见时 提交于 2019-11-29 09:26:28

A class extension is used to declare additional interface -- methods and properties -- whose implementation contract will be met within the class's primary @implementaiton.

Which is exactly why you can't add storage -- add ivars -- via a class extension. A class extension is an interface, no more, no less. @synthesize is what creates storage for @property declarations, but @synthesize of an @property can only appear in the @implementation of the class (whether explicitly or as a default behavior of the compiler).

Since you can't recompile the framework class, you can't add ivars to it.

@prashat's answer is one way to add storage to an existing class. However, going that route is generally undesirable; hanging state off of framework classes willy-nilly is a sign of poor design and will make your application significantly more difficult to maintain over time.

Far better to revisit your design, understand why you currently require attaching state to an object that can't directly contain it, and refactoring that requirement away.

Try using a category with Associative References instead. It is much cleaner and will work on all instances of UIButton.

UIButton+Property.h

#import <Foundation/Foundation.h>

@interface UIButton(Property)

@property (nonatomic, retain) NSObject *property;

@end


UIButton+Property.m

#import "UIButton+Property.h"
#import <objc/runtime.h>

@implementation UIButton(Property)

static char UIB_PROPERTY_KEY;

@dynamic property;

-(void)setProperty:(NSObject *)property
{
  objc_setAssociatedObject(self, &UIB_PROPERTY_KEY, property, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSObject*)property
{
   return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY);
}

@end

//Example usage

#import "UIButton+Property.h"


UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.property = @"HELLO";
NSLog(@"Property %@", button1.property);
button1.property = nil;
NSLog(@"Property %@", button1.property);

The docs state:

Class extensions are like anonymous categories, except that the methods they declare must be implemented in the main @implementation block for the corresponding class.

When you use @property, it is roughly equivalent to declaring accessor methods. So this means you can only do such a thing if you are also the author of the "main" @implementation block of the class, which with UITableViewController, you are not.

Your only option here is Categories, which cannot add instance variables.

The docs link, and note the very last line of that page:

The implementation of the setValue: method must appear within the main @implementation block for the class (you cannot implement it in a category). If this is not the case, the compiler emits a warning that it cannot find a method definition for setValue:.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!