使用%i格式化NSUInteger

时间:2014-11-11 18:23:11

标签: ios objective-c ipad ios7 ios8

我正在查看以前的员工代码,其中大约有20个警告出现:

Values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead

出现这种情况的代码的一部分是:

NSUInteger Length;

使用:

- (NSString *) description {

    // If no value was given, display type
    if([Value length] == 0)
    {
        NSString *type = @"";

        switch (Type) {
            case DTCompType_Year: type = @"year";
                break;
            case DTCompType_Month: type = @"month";
                break;            
            case DTCompType_Day: type = @"day";
                break;            
            case DTCompType_Hour: type = @"hour";
                break;            
            case DTCompType_Minute: type = @"minute";
                break;            
            case DTCompType_Second: type = @"second";
                break;            
            case DTCompType_Meridiem: type = @"meridiem";
                break;            
            case DTCompType_MonthName: type = @"month_name";
                break;
            case DTCompType_DayOfTheWeek: type = @"day_of_the_week";
                break;
            case DTCompType_Undefined: type = @"undefined";
                break;            
        }

        return Length == 0 ? [NSString stringWithFormat:@"[%@]", type] : 
        [NSString stringWithFormat:@"[%@:%i]", type, Length];
    }

我在Apple文档中找不到%i

Apple's Documentation

之前我从未使用过Objective-C,现在我必须更新这个应用程序。我知道这需要成为一个无条件的长期,但我不想在不知道原因的情况下开始改变事物。该应用程序工作正常,所以有没有任何固有的后果将这些更改为无符号长?甚至将格式说明符从%i更改为%lu

从我读过的内容来看,这可能是平台的问题。 (32位与64位)

这是为iOS7中的iPad 2开发的,我们刚刚将SDK升级到iOS8。

我发现这篇文章: NSUInteger should not be used in format strings? 这给了我一些指导,但我需要更多澄清。

2 个答案:

答案 0 :(得分:1)

%i相当于%d。从技术上讲,你应该一直使用%u。正如您所怀疑的那样,问题是32位与64位; NS[U]Integer在32位版本上为[unsigned] int,在64位版本上为[unsigned] long。因为iPhone是小端的,所以它会工作"只要%i/d/u是指定的最后一种格式,但它仍然是错误的。您应该将参数转换为格式说明符所期望的类型(int / long / unsigned / unsigned long),如警告消息所示。

来自< objc / NSObjCRuntime.h>:

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

答案 1 :(得分:1)

您可以使用盒装文字来允许编译器和NSNumber类处理各种数字类型及其字符串表示之间的转换细节。例如,给定以下变量定义......

NSUInteger foo = 42;

...您可以按如下方式创建NSNumber的实例:

NSNumber *myNumber = @(foo);

然后,只要需要格式化%@的值,就可以使用myNumber格式说明符。当然,它可以很容易地将原始数值直接包装在行中:

NSString *s = [NSString stringWithFormat:@"The answer is %@", @(foo)];