0

当我尝试写

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
4

6 回答 6

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
于 2009-11-10T19:46:55.583 回答
4

Carl 在尝试编译您的代码方面做得很好。%@ 格式说明符只是另一个词,因为您的问题似乎暗示了一些混淆。

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

于 2009-11-10T19:50:37.043 回答
1

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

于 2009-11-10T23:06:55.193 回答
0

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

dealloc要查看您的 myObject 何时被释放,请尝试在您的类中的方法中添加类似这样的内容:

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

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

于 2009-11-11T04:56:32.603 回答
-1

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

因为当您从硬件转移到硬件时精度会发生变化,所以最好养成使用对象转换为日志值的习惯。在这种情况下:

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

这将始终正确打印。


编辑#1:我道歉。当我写上面的时候,我被剥夺了睡眠。我真正的意图是警告不要使用简单的intvsNSInteger以及使用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,控制台会给出一些高数,例如 70614496。

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

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

无论哪种情况,您都需要查看将值分配给id属性的代码,而不是打印它的位置。

于 2009-11-10T20:32:11.437 回答
-1

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

@property(nonatomic) int myId;

对此:

@property(nonatomic, assign) int myId;

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

于 2009-11-11T17:35:11.523 回答