0
votes

I have seen a class which implements a catagory on itself. The code is as follow:

.h file:

#import <UIKit/UIKit.h>
@interface BPTopTabBarViewController : UIViewController

@end

@interface UIViewController (BPTopTabBarViewController)
@property (nonatomic, readonly) BPTopTabBarViewController *topTabBarViewController;
@end

.m file:

#import "BPTopTabBarViewController.h"
#import <objc/runtime.h>
@implementation UIViewController (BPTopTabBarViewController)
- (BPTopTabBarViewController *)topTabBarViewController
{
    return objc_getAssociatedObject(self, BPTopTabBarViewControllerKey);
}

- (void)setTopTabBarViewController:(BPTopTabBarViewController *)topTabBarViewController
{
    objc_setAssociatedObject(self, BPTopTabBarViewControllerKey, topTabBarViewController, OBJC_ASSOCIATION_ASSIGN);
}
@end

@interface BPTopTabBarViewController () {
}

@end

@implementation BPTopTabBarViewController
...
@end

My Questions are:

  1. What is the point of introducing a getter and setter on itself with a category of UIViewController? According to me only the class of BPTopTabBarViewController or the subclass of it can see the category because there is no category header(#import "UIViewController + BPTopTabBarViewController") declared in .h file.

  2. I can see UINavigationController also have some structure like this:

    @interface UIViewController (UINavigationControllerItem)

Here we can always call a class of UIViewController or its subclass self.navigationController, how is the category exposed to UIViewController when it is written in UINavigationController class? I also don't see the category header in UINavigationController.h file:

//  Copyright (c) 2007-2014 Apple Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIViewController.h>
#import <UIKit/UIKitDefines.h>
#import <UIKit/UIInterface.h>
#import <UIKit/UIGeometry.h>
#import <UIKit/UIPanGestureRecognizer.h>
#import <UIKit/UITapGestureRecognizer.h>
  1. If I want to expose the category to specific UIViewController class, what should I do?

  2. If I want to expose the category globally, should I put #import "BPTopTabBarViewController.h" into project-Prefix.pch file?

2

2 Answers

1
votes

I'm struggling to figure out where you've gotten your information from because most of it seems to be from inaccurate sources since the questions don't make much sense. The point of the category is the be able to call this new method on any UIViewController or subclass thereof, even without access to its source code.

For example:

UIViewController *foo = [UIViewController new];
BPTopTabBarViewController *bar = foo.topTabBarViewController: //This will compile now

Part of the misunderstanding you may be having is what actually comes inside the parenthesis of a category. This is not the name of anything in particular, it is just an identifier. When you make a category, the class it gets added to is the class outside the parenthesis.

UIViewController (BPTopTabBarViewController) means a category named "BPTopTabBarViewController" which will affect UIViewController.

All you need to do to use it is #import "BPTopTabBarViewController.h" wherever you want to use it, or in your .pch file if you want to use it everywhere.

1
votes

Answers

  1. This will make UIViewController Class and its subclass have the ability to call the setter and getter on a property of topTabBarViewController.

  2. The same as 1.

  3. Just import BPTopTabBarViewController.h to .m or .h.

  4. Just include BPTopTabBarViewController.h in Prefix.pch file.