Objective c ObjC NSNumber存储指向对象的指针,而不是返回值
我编写了自己的Objective C类来处理2D向量Objective c ObjC NSNumber存储指向对象的指针,而不是返回值,objective-c,ios8,nsnumber,Objective C,Ios8,Nsnumber,我编写了自己的Objective C类来处理2D向量 @interface Vector2D : NSObject { struct _vecdata { double x; double y; double x_norm; double y_norm; } _data; } @property(nonatomic) double x; //custom getter + setter @property(nona
@interface Vector2D : NSObject {
struct _vecdata {
double x;
double y;
double x_norm;
double y_norm;
} _data;
}
@property(nonatomic) double x; //custom getter + setter
@property(nonatomic) double y; //custom getter + setter
@property(nonatomic, readonly) double xNormed; //custom getter
@property(nonatomic, readonly) double yNormed; //custom getter
+ (id)vectorWithX:(double)x_ext andY:(double)y_ext;
- (id)initWithX:(double)x_ext andY:(double)y_ext;
[...]
- (double)length;
@end
#import <math.h>
@implementation Vector2D
+ (id)vectorWithX:(double)x_ext andY:(double)y_ext{
return [[self alloc] initWithX:x_ext andY:y_ext];
}
- (id)initWithX:(double)x_ext andY:(double)y_ext {
if ((self = [super init])) {
_data.x = x_ext;
_data.y = y_ext;
[self normalize];
}
return self;
}
- (void)setX:(double)x {
_data.x = x;
[self normalize];
}
- (double)x {
return _data.x;
}
- (double)xNormed {
return _data.x_norm;
}
//setters and getter for y omitted (same as for x)
[...]
- (void)normalize {
double abs = [self length];
if (abs != 0) {
_data.x_norm = _data.x/abs;
_data.y_norm = _data.y/abs;
}
}
- (double)length {
return sqrt(_data.x*_data.x + _data.y*_data.y);
}
@end
由于后来我显示了aNSNum的值,我注意到,所有的值(以这种方式创建的所有NSNumbers的值)都在1.40537252E+14
(因为我后来调用[aNSNum floatValue])。
因此,我重新编译并重新运行应用程序,突然所有的值都在4.73280427E+14
左右
所以我想知道,因为向量的长度应该在0到20000之间,但不能超过。
我开始在调试器中四处玩,以了解发生了什么,并得到了以下结果:
(lldb) po [[Vector2D vectorWithX:someXValue andY:someYValue] length]
0x0000000000000001
(lldb) po (double)[[Vector2D vectorWithX:someXValue andY:someYValue] length]
84.693565280958623
(lldb) po (unsigned long)[[Vector2D vectorWithX:someXValue andY:someYValue] length]
1
(lldb) po @([[Vector2D vectorWithX:someXValue andY:someYValue] length])
84.69356528095862
(lldb) po @((double)[[Vector2D vectorWithX:someXValue andY:someYValue] length])
84.69356528095862
(lldb) po @((unsigned long)[[Vector2D vectorWithX:someXValue andY:someYValue] length])
1
(lldb) po aNSNum
140537282189312
(lldb) po [aNSNum floatValue]
1.40537286E+14
(lldb) po (unsigned long)[aNSNum doubleValue]
<Vector2D: 0x7fd162c85800>
(lldb) po (double)[(unsigned long)[aNSNum doubleValue] length]
84.693565280958623
但希望有人能帮我把它带回一艘客轮。或者有错误的线索…编辑:
编译器会感到困惑,因为
+(id)向量,带x:(双)x_ext安迪:(双)y_ext代码>
是id
;它不知道在运行时它将得到哪个length
方法。将声明更改为
+(instancetype)向量,带x:(双)x_ext安迪:(双)y_ext代码>
看看事情有多美好。
了解更多信息,请访问
您依赖于文本语法@(someNumber)来检测someNumber的类型并正确处理它,在本例中,是length方法的(double)返回值。数字文字的规则是
我认为安全的做法是,使用显式类型创建数字,而不是对变量进行类型转换,并希望编译器对其进行处理
NSNumber* aNSNum = [NSNumber numberWithDouble:[[Vector2D vectorWithX:someXValue andY:someYValue] length]];
NSNumber文本是常量等的很好的速记,但这似乎使代码更难理解,而不是更容易理解。这是否有效:double len=[[Vector2D vectorWithX:someXValue andY:someYValue]length];NSNumber*aNSNum=@(len)代码>?或者,这样做:NSNumber*aNSNum=[NSNumber numberWithDouble:[[Vector2D vectorWithX:someXValue andY:someYValue]length]代码>?我怀疑装箱表达式和其中的嵌套消息存在某些编译器错误。NSNumber*aNSNum=[NSNumber numberWithDouble:[[Vector2D vectorWithX:someXValue andY:someYValue]length]代码>似乎也没有帮助。仍然将指针作为NSNumber值获取。是的,这有点奇怪。当您尝试设置double vectorLength=[[Vector2D vectorWithX:someXValue andY:someYValue]length]时,您得到了什么值代码>?这可能与NSNumber毫无关系,更重要的是与具有某些奇怪行为的长度方法有关。NSNumber*aNSNum=[NSNumber numberWithDouble:[((Vector2D*)[Vector2D vectorWithX:someXValue andY:someYValue])length]代码>似乎起到了作用。。。似乎编译器不喜欢我的类…就像在调试器输出中一样,工作得很好:-)似乎当length
消息返回值作为NSNumber的参数出现时,可能会有一些奇怪的编译器增强功能?!见上文。这是因为您没有提供足够的关于类方法返回类型的信息。现在对我来说一切都有意义了!
static SEL lengthSEL;
static IMP lengthIMP;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
lengthSEL = @selector(length);
lengthIMP = class_getMethodImplementation([Vector2D class], lengthSEL);
});
Vector2D* vec = [Vector2D vectorWithX:someXValue andY:someYValue];
double len = ((double (*) (id,SEL))lengthIMP)(vec,lengthSEL);
NSNumber* aNSNum = @(len);
NSNumber* aNSNum = [NSNumber numberWithDouble:[[Vector2D vectorWithX:someXValue andY:someYValue] length]];