I am revising an early project where I use tags to identify 1-of-5, 1-of-16 or 1-of-10 UIButtons
. I want to replace the tags with a customised property based on my understanding of this answer.
The property called myInfo
consists of a string followed by an integer. This may well be a tag by another name but it makes a message source uniquely identifiable in a way that a simple integer tag does not, clearing magic numbers from my code and, hopefully, improving the documentation.
The property is created using a category
UIView+CustomProperties.m
#import "UIView+CustomProperties.h"
@implementation UIView (MyInfo)
-(void)setMyInfo:(id)info
{
objc_setAssociatedObject(self, "_myInfo", info, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(id)myInfo
{
return objc_getAssociatedObject(self, "_myInfo") ;
}
@end
And myInfo
works when I import objc/runtime.h
UIView+CustomProperties.
#import <objc/runtime.h>
@interface UIView (MyInfo)
@property ( nonatomic, strong ) id myInfo;
@end
I call the category from the method (below) in the UIView where I create several sets of buttons.
// define type and number of 5, 16 or 10 buttons
switch (buttonCount) {
case 5:
roundButton.myInfo = [NSString stringWithFormat:@"transpose index %i", i ];
break;
case 16:
roundButton.myInfo = [NSString stringWithFormat:@"player index %i", i ];
break;
case 10:
roundButton.myInfo = [NSString stringWithFormat:@"note index %i", i ];
break;
default:
roundButton.myInfo = @“orphan button“;
break;
}
To identify a message source I have tried to strip away all non-numeric characters from myInfo
using this method. However a problem appears in my selector method forButtons
as I attempt to remove non-numeric characters
- (void)fromButtons:(UIButton*)button {
NSLog(@"Button %ld tapped", (long int)[button tag]);
NSLog(@"first, %@", button.myInfo);
NSString *newString = [[button.myInfo componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:@""];
NSLog(@"then, %@", newString);
NSLog(@"and %li", (long int)newString);
When I build and run and press button 1, the NSLog
statements above produce the following log
2017-05-25 18:27:33.147 SatGam3[930:607301] Button 1 tapped
2017-05-25 18:27:33.147 SatGam3[930:607301] first, transpose index 1
2017-05-25 18:27:33.148 SatGam3[930:607301] then, 1
2017-05-25 18:27:33.148 SatGam3[930:607301] and 2070247168
Note that the long int
value for the original tag is correct i.e. 1 whereas the long int
recovered from the customised property is 2070247168.
Q.1 Firstly, is this approach correct ?
Q.2 If so, can someone please explain why am I extracting a 9-digit numeric value from myInfo
?
Use below line of code :
Your approach is correct.
First, a problem that has nothing to do with your problem: Your use of
"_myInfo"
as the key here is slightly dangerous. In practice you're going to get away with it, but it relies on a compiler optimization that isn't promised. You're betting that the compiler (and possibly the linker) will ensure that all copies of the same constant string refer to the same memory location in the binary. That happens to be true, but it's not part of the language. Use a selector instead.But that's not your problem. Your problem is this:
newString
is (unsurprisingly) anNSString*
. So this points the address of that string. If you want to convert this into a number, you'll want to call-intValue
on it.That said, I wouldn't encode this data as a string. Encode it as a data object:
(or
name
could be an enum if there are fixed set of them)If you want to make this easier to read, add a
-description
method. Use the type system; it's there to help you. Don't try to encode a complicated type into a string.