-3

Possible Duplicate:
Subclass UIButton to add a property

I'm trying to find a way to extend UIButton so that it can have a property like

@property(assign, nonatomic) id userInfos;

without subclassing it...

Is this possible?

the button.tag is not enough in my situation...

Okay as always a better answer is available here

Subclass UIButton to add a property

Community
  • 1
  • 1
Nicolas Manzini
  • 8,379
  • 6
  • 63
  • 81
  • 1
    See [Subclass UIButton to add a property](http://stackoverflow.com/questions/5500327/subclass-uibutton-to-add-a-property/) – Joe Jan 04 '13 at 21:38
  • 4
    Out of interest what are you actually adding? This looks like a code smell to me. – Paul.s Jan 04 '13 at 21:39
  • 1
    I agree with Paul. It sounds like MVC separation isn't being followed here. Buttons shouldn't know anything about what's going on in the rest of the app. Buttons simply inform your view controller of state changes (pressed, released, etc). Your view controller that owns the button should handle these events and retrieve data itself. – Jack Lawrence Jan 04 '13 at 21:49
  • 1
    well as much as people use the tag property in a tableView to retrieve the indexPath.row of the button i think it's a nice way to be able to get on the selector the object I want to work with instead of forking it again in my class. especially as buttons are generated from a core data nsset in my case. – Nicolas Manzini Jan 04 '13 at 21:57
  • I'm not 100% sure this is your meaning from the last comment, but maybe you want to be using the `UIControl` instance method: `actionsForTarget:forControlEvent:`? – MaxGabriel Jan 04 '13 at 22:05
  • nope, simply pass some user info to the selector according to which button called it. – Nicolas Manzini Jan 04 '13 at 22:09
  • @NicolasManzini Do you mean pass the button to the method? Like this: `- (void)myButtonsAction:(UIButton *)senderButton`? – RileyE Jan 04 '13 at 22:15
  • 1
    yes that's what you do and usually if you have many button that call the same method you need to use the button.tag property to know which button called the selector and from the tag find the object you want to use but I think it's cleaner if you can pass user info with the button and have directly button.myObject available in the method. – Nicolas Manzini Jan 04 '13 at 22:19

3 Answers3

2

This is very easy using Objective-C associated objects:

In your header:

@interface UIButton (MyCustomProperty)
@property (readwrite, retain, nonatomic) id myCustomProperty;
@end

In your implementation file:

#include <objc/runtime.h>

/* Associated objects need a unique memory location to use as a key. */
static char MyCustomPropertyKey = 0;

@implementation UIButton (MyCustomProperty)
/* Use @dynamic to tell the compiler you're handling the accessors yourself. */
@dynamic myCustomProperty;

- (id)myCustomProperty {
    return objc_getAssociatedObject(self, &MyCustomPropertyKey);
}

- (void)setMyCustomProperty: (id)anObject {
    objc_setAssociatedObject(self, &MyCustomPropertyKey, anObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

That's it!

Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
  • I'm trying your answer right now get back to you in a minute. IT works! I however prefer OBJC_ASSOCIATION_ASSIGN my button must just be able to pass the object along its selector. :) Awesome – Nicolas Manzini Jan 04 '13 at 21:43
  • 2
    `OBJC_ASSOCIATION_ASSIGN` will only use a weak reference. If there is no other reference to your object, it will be deallocated, you will get a dangling pointer, and Bad Things™ will happen. Unless you have a specific reason to use `OBJC_ASSOCIATION_ASSIGN`, use `OBJC_ASSOCIATION_RETAIN_NONATOMIC`. – Jonathan Grynspan Jan 04 '13 at 23:05
0

You can use the objective-c runtime's associated objects functions to associate an object with another object:

void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)

id objc_getAssociatedObject(id object, void *key)

Also, voting to close. Duplicate of:

How to add properties to NSMutableArray via category extension?

Adding custom behavior and state to all my classes

among many others.

Edit:

I also agree with the comment on your question by @Paul.s. Attaching data to a button sounds messy. Without knowing what you're doing, I would suggest tagging the button and then have your view controller handle fetching whatever data you need based on the button's tag.

Community
  • 1
  • 1
Jack Lawrence
  • 10,664
  • 1
  • 47
  • 61
0

What you want is to create a UIButton category. Categories are designed as a way to extend the functionality of an existing class. Once created an set up, you only need to import the category and you can use its function on any instance of the class it's designed for.

Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281