Question

Im working on a xcode5 development for iPad where I needed a custom button type with custom properties, so I added a custom class like so...

CarouselButton.h

#import <Foundation/Foundation.h>

@interface UIButton(Property)

@property (nonatomic, retain) NSString *typeOfContent;
@property (nonatomic, retain) NSString *pdfDocumentName;

@end

CarouselButton.m

#import "CarouselButton.h"
#import <objc/runtime.h>

@implementation UIButton(Property)

static char UIB_PROPERTY_KEY_1;
static char UIB_PROPERTY_KEY_2;

@dynamic typeOfContent;
@dynamic pdfDocumentName;

-(void)setTypeOfContent:(NSObject *)typeOfContent{
    objc_setAssociatedObject(self, &UIB_PROPERTY_KEY_1, typeOfContent, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSObject*)typeOfContent{
    return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY_1);
}

-(void)setPdfDocumentName:(NSObject *)pdfDocumentName{
    objc_setAssociatedObject(self, &UIB_PROPERTY_KEY_2, pdfDocumentName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSObject*)pdfDocumentName{
    return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY_2);
}

@end

and the way to fill and call those properties for manipulation:

#import "CarouselButton.h"


UIButton *button = (UIButton *)view;
button          = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
button.typeOfContent    = [[itemsCarouselTop objectAtIndex:index] objectForKey:@"typeOfContent"];
button.pdfDocumentName  = [[itemsCarouselTop objectAtIndex:index] objectForKey:@"pdfDocumentName"];

this works fine, now I can store any info NSString type but I want to store a NSArray type, so I did this:

CarouselButton.h

#import <Foundation/Foundation.h>

@interface UIButton(Property)

@property (nonatomic, retain) NSString *typeOfContent;
@property (nonatomic, retain) NSString *pdfDocumentName;
@property (nonatomic, retain) NSArray *viewControllerParameters;

@end

CarouselButton.m

#import "CarouselButton.h"
#import <objc/runtime.h>

@implementation UIButton(Property)

static char UIB_PROPERTY_KEY_1;
static char UIB_PROPERTY_KEY_2;
static char UIB_PROPERTY_KEY_3;

@dynamic typeOfContent;
@dynamic pdfDocumentName;
@dynamic viewControllerParameters;

-(void)setTypeOfContent:(NSObject *)typeOfContent{
    objc_setAssociatedObject(self, &UIB_PROPERTY_KEY_1, typeOfContent, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSObject*)typeOfContent{
    return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY_1);
}

-(void)setPdfDocumentName:(NSObject *)pdfDocumentName{
    objc_setAssociatedObject(self, &UIB_PROPERTY_KEY_2, pdfDocumentName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSObject*)pdfDocumentName{
    return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY_2);
}

-(void)setviewControllerParameters:(NSObject *)viewControllerParameters{
    objc_setAssociatedObject(self, &UIB_PROPERTY_KEY_3, viewControllerParameters, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSObject*)viewControllerParameters{
    return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY_3);
}

@end

And I use it this way:

#import "CarouselButton.h"


UIButton *button = (UIButton *)view;
button          = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
button.typeOfContent    = [[itemsCarouselTop objectAtIndex:index] objectForKey:@"typeOfContent"];
button.pdfDocumentName  = [[itemsCarouselTop objectAtIndex:index] objectForKey:@"pdfDocumentName"];
button.viewControllerParameters = [NSArray arrayWithArray:[[itemsCarouselTop objectAtIndex:index] objectForKey:@"viewControllerParameters"]];

but I get this error:

2014-04-08 18:36:37.320 [10222:60b] -[UIButton setViewControllerParameters:]: unrecognized selector sent to instance 0x16591420 2014-04-08 18:36:37.323 eSelect[10222:60b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton setViewControllerParameters:]: unrecognized selector sent to instance 0x16591420' * First throw call stack: (0x308f8f03 0x3b4e2ce7 0x308fc837 0x308fb12f 0x3084a0d8 0xeaa7d 0x110b0f 0x1111d9 0x10f6d3 0x1103c1 0x10a43d 0xe97af 0x3312ca53 0x331d730d 0x331d7223 0x331d6801 0x331d6529 0x331d6299 0x331d6231 0x33128305 0x32da431b 0x32d9fb3f 0x32dceb4d 0x331a489f 0x331a2ea9 0x331a20e7 0x331a206f 0x331a2007 0x3319a681 0x3312e697 0x331a1d59 0x331a1829 0x33133615 0x3319982b 0x12220b 0x11a09d 0x332467f3 0x332f8cb3 0x331a7e09 0x33120b57 0x308c4031 0x308c19bf 0x308c1d0b 0x3082c7a9 0x3082c58b 0x357736d3 0x3318b891 0x120361 0x3b9e0ab7) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)

Was it helpful?

Solution

-(void)setviewControllerParameters:(NSObject *)viewControllerParameters{
    objc_setAssociatedObject(self, &UIB_PROPERTY_KEY_3, viewControllerParameters, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

In the above setter method change the 'v' to a capital 'V'.

E.g. setViewControllerParameters: not setviewControllerParameters:

OTHER TIPS

Unless you want every button in your application to have these properties, you should be subclassing UIButton into a CarouselButton class rather than creating a 'Property' category on UIButton.

All those contortions about AssociatedObjects are really only for categories, not necessary for subclasses. You don't need any of that code inside your implementation; default setters and getters are created automatically for you by the @property (nonatomic, retain)

CarouselButton.h

@interface CarouselButton: UIButton

@property (nonatomic, retain) NSString *typeOfContent;
@property (nonatomic, retain) NSString *pdfDocumentName;
@property (nonatomic, retain) NSArray *viewControllerParameters;

@end

CarouselButton.m

#import "CarouselButton.h"

@implementation CarouselButton

@end

And use it this way:

#import "CarouselButton.h"

CarouselButtton *button = [CarouselButtton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
button.typeOfContent    = [[itemsCarouselTop objectAtIndex:index] objectForKey:@"typeOfContent"];
button.pdfDocumentName  = [[itemsCarouselTop objectAtIndex:index] objectForKey:@"pdfDocumentName"];
button.viewControllerParameters = [NSArray arrayWithArray:[[itemsCarouselTop objectAtIndex:index] objectForKey:@"viewControllerParameters"]];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top