I have a custom class/object that handles gestures and conducts animations for a given view using a CADisplayLink. In its simplest form my class looks something like follows:
@interface SomeClass : NSObject
@property (strong) UIView *someView;
@end
When I add the following code to my view controller....
- (void)viewDidLoad
{
[super viewDidLoad];
SomeClass *someClass = [[SomeClass alloc] init];
someClass.someView = someView;
}
... I was anticipating my someClass object would be retained for the life of the view controller, since I am using a strong reference to someView.
However someClass is immediately deallocated.
I am already aware that I can overcome the deallocation simply by adding someClass as a property (or indeed iVar) of the view controller however I would ideally like to avoid this extra work...
so is there anyway I can have my class retained until either the view or view controller its associated with are deallocated?
EDIT
UIGestureRecognizer objects are an exmaple of a class that doesn't get deallocated when I associate them with a view...
- (void)viewDidLoad
{
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
[someView addGestureRecognizer:gestureRecognizer];
}
// tapGestureRecognizer still lives
Presumably this is because the UIView takes owner ship of the UIGestureRecognizer object. Is there anyway to achieve this with my class and a UIView category? I.e....
- (void)viewDidLoad
{
[super viewDidLoad];
SomeClass *someClass = [[SomeClass alloc] init];
[someView addSomeClass:someClass];
}
If you want to associate the object with a UIView in the same way a UIGestureRecognizer does then this is technically possible using associatedObjects as follows (but I'm not sure I'd advocate this approach since associatedObjects are often frowned upon)...
SomeClass.h
@class SomeClass;
@interface UIView (SomeClass)
- (void)addSomeClass:(SomeClass *)someClass;
- (void)removeSomeClass:(SomeClass *)someClass;
@end
@interface SomeClass : NSObject
@property (strong) UIView *someView;
@end
SomeClass.m
#import "SomeClass.h"
#import <objc/runtime.h>
@implementation UIView (AssociatedObject)
- (void)addSomeClass:(SomeClass *)someClass
{
NSMutableArray *someClasses = [self someClasses];
if (someClasses == nil) {
someClasses = [[NSMutableArray alloc] init];
[self setSomeClasses:someClasses];
}
[someClasses addObject:someClass];
}
- (void)removeSomeClass:(SomeClass *)someClass
{
NSMutableArray *someClasses = [self someClasses];
if (someClasses != nil) {
[someClasses removeObject:someClass];
if (someClasses.count == 0) {
[self setSomeClasses:nil];
}
}
}
#pragma mark - Private Methods
- (NSMutableArray *)someClasses
{
return (NSMutableArray *)objc_getAssociatedObject(self, @selector(someClasses));
}
- (void)setSomeClasses:(NSMutableArray *)someClasses
{
objc_setAssociatedObject(self, @selector(someClasses), someClasses, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
@implementation SomeClass
@end
Implementation
- (void)viewDidLoad
{
[super viewDidLoad];
SomeClass *someClass = [[SomeClass alloc] init];
someClass.someView = someView;
[someView addSomeClass:someClass];
}
Some further reading on associatedObjects from NSHipster...