Instance Variables for Objective C Categories

2020-01-29 04:21发布

I have a situation where it seems like I need to add instance variables to a category, but I know from Apple's docs that I can't do that. So I'm wondering what the best alternative or workaround is.

What I want to do is add a category that adds functionality to UIViewControllers. I would find it useful in all my different UIViewControllers, no matter what specific UIViewController subclass they extend, so I think a category is the best solution. To implement this functionality, I need several different methods, and I need to track data in between them, so that's what led me to wanting to create instance methods.

In case it's helpful, here's what I specifically want to do. I want to make it easier to track when the software keyboard hides and shows, so that I can resize content in my view. I've found that the only way to do it reliably is to put code in four different UIViewController methods, and track extra data in instance variables. So those methods and instance variables are what I'd like to put into a category, so I don't have to copy-paste them each time I need to handle the software keyboard. (If there's a simpler solution for this exact problem, that's fine too--but I would still like to know the answer to category instance variables for future reference!)

8条回答
祖国的老花朵
2楼-- · 2020-01-29 04:29

It mentioned in many document's online that you can't create create new variable in category but I found a very simple way to achieve that. Here is the way that let declare new variable in category.

In Your .h file

@interface UIButton (Default)

   @property(nonatomic) UIColor *borderColor;

@end  

In your .m file

#import <objc/runtime.h>
static char borderColorKey;

@implementation UIButton (Default)

- (UIColor *)borderColor
{
    return objc_getAssociatedObject(self, &borderColorKey);
}

- (void)setBorderColor:(UIColor *)borderColor
{
    objc_setAssociatedObject(self, &borderColorKey,
                             borderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    self.layer.borderColor=borderColor.CGColor;
}

@end

That's it now you have the new variable.

查看更多
Luminary・发光体
3楼-- · 2020-01-29 04:29

I believe it is possible to add variables to a class using the Obj-C runtime.
I found this discussion also.

查看更多
我只想做你的唯一
4楼-- · 2020-01-29 04:30

This is best achieved using the built-in ObjC feature Associated Objects (aka Associated References), in the example below just change to your category and replace associatedObject with your variable name.

NSObject+AssociatedObject.h

@interface NSObject (AssociatedObject)
@property (nonatomic, strong) id associatedObject;
@end

NSObject+AssociatedObject.m

#import <objc/runtime.h>

@implementation NSObject (AssociatedObject)
@dynamic associatedObject;

- (void)setAssociatedObject:(id)object {
     objc_setAssociatedObject(self, @selector(associatedObject), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (id)associatedObject {
    return objc_getAssociatedObject(self, @selector(associatedObject));
}

See here for the full tutorial:

http://nshipster.com/associated-objects/

查看更多
5楼-- · 2020-01-29 04:30

Depending on what you're doing, you may want to use Static Category Methods.

So, I assume you've got this kind of problem:

ScrollView has a couple of textedits in them. User types on text edit, you want to scroll the scroll view so the text edit is visible above the keyboard.

+ (void) staticScrollView: (ScrollView*)sv scrollsTo:(id)someView
{
  // scroll view to someviews's position or some such.
}

returning from this wouldn't necessarily require the view to move back, and so it doesn't need to store anything.

But that's all I can thinkof without code examples, sorry.

查看更多
爱情/是我丢掉的垃圾
6楼-- · 2020-01-29 04:31

Yes you can do this, but since you're asking, I have to ask: Are you absolutely sure that you need to? (If you say "yes", then go back, figure out what you want to do, and see if there's a different way to do it)

However, if you really want to inject storage into a class you don't control, use an associative reference.

查看更多
做个烂人
7楼-- · 2020-01-29 04:44

Why not simply create a subclass of UIViewController, add the functionality to that, then use that class (or a subclass thereof) instead?

查看更多
登录 后发表回答