Ken M. Haggerty Ken M. Haggerty - 1 year ago 90
Objective-C Question

Any way to apply Objective-C category only to current class (or equivalent effect)?

Let's say I have a custom subclass of UIView called

. Let's also say that I have a category on UIView called
that adds an NSDictionary property called
to every UIView.

If I were to import
then every view referenced within
would have this added
property, which in many situations is exactly the desired behavior.

However, if I wanted
applied only to
itself and not to every UIView referenced within
, is there a way to do so (or achieve a similar effect)?

I'd like to avoid making
a subclass of another custom subclass (e.g.,
), as I'd ideally like to be able to import multiple categories for something akin to multiple inheritance (e.g.,

In my actual own scenario, I've written a category to automatically implement a custom UINavigationBar in a view controller, but I'd like that category to apply only to the view controller into which I am importing the category and not any other view controllers that may be referenced in that file.

Any and all insights are appreciated! And I apologize in advance as I am fairly certain there are more correct terminologies for the effect described above.

Answer Source

As Josh pointed out, any methods added in categories are basically inert unless you call them. The issue that I was having was for generated properties and swizzled methods in categories (since, as Josh also pointed out, there are no mixins in Objective-C).

I was able to solve this by adding in a custom BOOL in my category that defaults to NO and acts as a "switch" for whatever category methods and properties I want to specify.

E.g., if I wanted my dictionary property to be lazily instantiated but only within MyCustomView, I could do the following:

// UIView+Dictionary.h

@interface UIView (Dictionary)
@property (nonatomic) BOOL enableDictionary;
@property (nonatomic, strong) NSDictionary *dictionary;

// UIView+Dictionary.m

#import "UIViewController+CustomNavigationBar.h"
#import <objc/runtime.h>

@implementation UIView (Dictionary)

- (void)setEnableDictionary:(BOOL)enableDictionary {
    objc_setAssociatedObject(self, @selector(enableDictionary), @(enableDictionary), OBJC_ASSOCIATION_RETAIN_NONATOMIC);

- (BOOL)enableDictionary {
    NSNumber *enableDictionaryValue = objc_getAssociatedObject(self, @selector(enableDictionary));
    if (enableDictionaryValue) {
        return enableDictionaryValue.boolValue;

    objc_setAssociatedObject(self, @selector(enableDictionary), @NO, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    return self.enableDictionary;

- (void)setDictionary:(NSDictionary *)dictionary {
    objc_setAssociatedObject(self, @selector(dictionary), dictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

- (NSDictionary *)dictionary {
    if (!self.enableDictionary) {
        return nil;

    NSDictionary *dictionary = objc_getAssociatedObject(self, @selector(dictionary));
    if (dictionary) {
        return dictionary;

    objc_setAssociatedObject(self, @selector(dictionary), @{}, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    return self.dictionary;


And then within -[MyCustomView viewDidLoad] I could simply call self.enableDictionary = YES. That way, only instances of MyCustomView will have a non-nil lazily instantiated NSDictionary. (Note that, in this example, all instances of UIViews will still respond to the selector @selector(dictionary), but our behavior will differ based on whether enableDictionary is YES or NO.)

While that is a trivial example, the same strategy can be used for methods that are swizzled within categories. (Again, swizzling methods within categories is probably bad form but a necessary evil in certain scenarios.)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download