我试着写
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
答案 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:我道歉。当我写上面的内容时,我被剥夺了睡眠。我的意图是警告不要使用简单的int
与NSInteger
以及使用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时做了一些时髦的事情?