%d未正确显示整数

时间:2009-11-10 19:28:46

标签: objective-c cocoa cocoa-touch memory-management nslog

我试着写

NSLog(@"%d", myObject.myId);

其中myId为int,控制台会给出一些像70614496这样的高数字。当我使用@"%@"时,我会得到异常-[CFNumber respondsToSelector:]: message sent to deallocated instance 0x466c910。 为什么会这样?

这是myObject的定义:

@interface myObject : NSObject {
int myId;
NSString *title;
}

@property(nonatomic) int myId;
@property(nonatomic, retain) NSString *title;

@end

@implementation myObject

@synthesize myId, title;

- (void)dealloc {
[title release];

[super dealloc];
}

@end

6 个答案:

答案 0 :(得分:4)

这是一个示例,显示它应该以您第一次尝试它的方式工作,如果您的类/对象/实例变量都已正确设置:

#import <Foundation/Foundation.h>

@interface MyClass : NSObject
{
  int myId;
}

@property int myId;
@end

@implementation MyClass
@synthesize myId;
@end

int main (int argc, const char * argv[]) {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  MyClass *myObject = [[MyClass alloc] init];

  myObject.myId = 5;
  NSLog(@"%d", myObject.myId);

  [myObject release];
  [pool drain];
  return 0;
}

您的代码显示您执行的操作相当于此行:

NSLog(@"%d", MyClass.myId);

甚至没有编译,给出错误:

foundation.m:21: error: accessing unknown 'myId' class method

答案 1 :(得分:4)

Carl在尝试编译代码方面做得很好。关于%@格式说明符的另一个词,因为你的问题似乎意味着一些混乱。

在NSLog格式中使用%@时,实际上是在发送description消息的参数,并打印结果字符串。如果myId是int而不是NSObject的实例,则它不响应描述消息。使用%d表示int值,使用%@表示NSNumber实例。

答案 2 :(得分:1)

鉴于第二条错误消息,我认为%d工作正常,但在其他地方,当您应该分配整数时,您正在为myID属性分配CFNumber或NSNumber。

答案 3 :(得分:0)

看起来你的myObject实例在某个时候被自动释放,并且不再实际有效。这就是为什么当您尝试将其作为对象取消引用时,您会看到奇怪的NSNumber问题。当你只是要求一个整数时,你不会得到任何类型的错误,它只会显示指针强制转换为整数。

要查看myObject何时被取消分配,请尝试将类似内容添加到您班级的dealloc方法中:

- (void)dealloc
{
    NSLog(@"dealloc called on %@", self);
    [title release];
    [super dealloc];
}

我敢打赌,在看到myObject.myID的日志之前,你会发现这个日志记录是一个dealloc。

答案 4 :(得分:-1)

查看String Format Specifiers以了解如何格式化NSLog语句。使用NSLog很容易变得很懒,因为对象有一个内置的-description方法,它返回一个格式化的字符串。对于缩放器值,您必须使用正确的格式化程序。

由于从硬件转移到硬件时精度会发生变化,因此最好养成使用对象转换来记录值的习惯。在这种情况下:

NSLog(@“%@”,[[NSNumber numberFromInt:myObject.myId] stringValue]);

这将始终正确打印。


编辑#1:我道歉。当我写上面的内容时,我被剥夺了睡眠。我的意图是警告不要使用简单的intNSInteger以及使用NSNumber numberWithInteger:进行打印。

考虑以下在64位硬件上运行。

int x=pow(2,63);
NSLog(@"x=%d",x); //prints x=2147483647

NSInteger n=pow(2,63);
NSLog(@"n=%d",n); // prints n=-1
NSLog(@"n=%@",[[NSNumber numberWithInteger:n] stringValue]); // prints n=9223372036854775807

在8位系统的旧时代,你遇到了使用8位'int'的问题。运行超过256次迭代的for循环需要long。使用32位int,您将看不到这类问题,也不会养成跟踪int变量大小的习惯。

这可能会导致几乎不可能追踪的有害错误,因为它们只会在数据中出现非常特殊且罕见的值。

为iPhone(或其他未来的移动设备/平台)编写意味着在可能变化很大的硬件上编写,就像我们过去一样。最好在使用系统和API特定定义的早期习惯。


编辑#2:

  

其中myId是int,console给出了一些   高数,如70614496。

(1)如果每次运行时都打印一个不同的数字,那么你可能在设置时指定了一个指向int的指针。 NSLog正确地将指针的值打印为int。

(2)如果每次打印相同的数字,你可能会遇到溢出问题,就像我上面的第一次编辑一样。

在任何一种情况下,您都需要查看将值分配给id属性的代码,而不是打印它的位置。

答案 5 :(得分:-1)

我会尝试简单地改变这个:

@property(nonatomic) int myId;

到此:

@property(nonatomic, assign) int myId;

让我知道你的结果,我怀疑obj-c在为新的int分配旧的int时做了一些时髦的事情?