如果这是在 Objective C 中使用自定义字符串 属性 的正确方法,为什么我不能提取正确的数值?

If this is the right way to use a customised string property in Objective C, why can’t I extract the correct numeric value?

我正在修改一个早期项目,我在其中使用标签来识别 1-of-5、1-of-16 或 1-of-10 UIButtons。根据我对 this answer.

的理解,我想用自定义的 属性 替换标签

名为 myInfo 的 属性 由一个字符串和一个整数组成。这很可能是另一个名称的标签,但它使消息源以一种简单的整数标签所不能的方式唯一可识别,从我的代码中清除幻数,并希望改进文档。

属性 是使用类别创建的

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

并且 myInfo 在我导入 objc/runtime.h

时有效

UIView+CustomProperties.

    #import <objc/runtime.h>

    @interface UIView (MyInfo)
    @property ( nonatomic, strong ) id myInfo;

    @end

我从 UIView 中的方法 (下文) 调用类别,我在其中创建了几组按钮。

    // 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;
   }

为了识别消息源,我尝试使用 this methodmyInfo 中去除所有非数字字符。但是,当我尝试删除非数字字符

时,我的选择器方法 forButtons 出现了问题
- (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);

当我构建 运行 并按下按钮 1 时,上面的 NSLog 语句产生以下日志

    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

请注意,原始标签的 long int 值是正确的,即 1,而从自定义 属性 恢复的 long int 是 2070247168。

Q.1 首先,这种做法是否正确?

Q.2 如果是这样,有人能解释一下为什么我要从 myInfo 中提取一个 9 位数的数值吗?

首先,一个与你的问题无关的问题:你在这里使用"_myInfo"作为key有点危险。在实践中你会逃脱它,但它依赖于未承诺的编译器优化。您打赌编译器(可能还有链接器)将确保同一常量字符串的所有副本都引用二进制文件中的同一内存位置。这恰好是真的,但它不是语言的一部分。 Use a selector instead.

但这不是你的问题。你的问题是:

NSLog(@"and %li", (long int)newString);

newString 是(不出所料)一个 NSString*。所以这指向该字符串的地址。如果你想把它转换成一个数字,你会想在上面调用 -intValue

也就是说,我不会将此数据编码为字符串。将其编码为数据对象:

@interface ButtonInfo
@property (copy) NSString *name;
@property (assign) NSInteger index;
@end

(或者 name 可以是一个枚举,如果它们有固定的集合的话)

如果您想让它更易于阅读,请添加 -description 方法。使用类型系统;它可以帮助你。不要尝试将复杂的类型编码为字符串。

使用下面的代码行:

NSLog(@"and %li", [newString intValue]);

你的做法是正确的。