Objective-c中的一种奇怪类型转换

Objective-c中的一种奇怪类型转换,objective-c,ios,casting,uikit,Objective C,Ios,Casting,Uikit,我发现了一个使用如下类型转换的演示片段:(int)视图。“视图”是UIView对象的指针。我从来都不知道它可以用来铸造类型。有人能帮我解释一下吗? 在这里粘贴代码 - (CGPoint)accelerationForView:(UIView *)view { // return CGPoint accelecration; // get acceleration NSValue *pointValue = [self._accelerationsOfSubVie

我发现了一个使用如下类型转换的演示片段:(int)视图。“视图”是UIView对象的指针。我从来都不知道它可以用来铸造类型。有人能帮我解释一下吗? 在这里粘贴代码

- (CGPoint)accelerationForView:(UIView *)view
{
    // return
    CGPoint accelecration;

    // get acceleration
    NSValue *pointValue = [self._accelerationsOfSubViews objectForKey:
                                     [NSNumber numberWithInteger:(int)view]];
    if (pointValue == nil) {
        accelecration = CGPointZero;
    }
    else {
        [pointValue getValue:&accelecration];
    }

    return accelecration;
}

- (void)willRemoveSubview:(UIView *)subview
{
    [self._accelerationsOfSubViews removeObjectForKey:
                         [NSNumber numberWithInt:(int)subview]];
}
view
不是类型为
UIView
的对象,它是类型为
UIView*
的指针。上面的代码将指针强制转换为int,目的是将其存储在
NSNumber
中,显然是为了将其用作字典中的键。因为指针本身不是对象,所以不能将其用作字典键。但是,如果从指针创建
NSNumber
的实例,则可以将生成的对象用作键。人们有时做这类事情是为了跟踪一些他们想与许多对象(如视图)关联的信息,而这些对象本身并没有存储(如加速度)

正如我在下面的评论中提到的,这里的代码使用了
+numberWithInteger:
,这很好,因为该方法使用
NSInteger
,在32位系统中为32位,在64位系统中为64位。然而,作者随后通过强制转换为
int
,取消了这个好决定,即使在64位系统上,它通常也是32位的。演员阵容应该是
NSInteger
,如下所示:

[NSNumber numberWithInteger:(NSInteger)view]
(注意:这是基于@Caleb的答案,假设原始代码试图将
加速度
值与UIView关联)

我会通过一个类别向UIView添加一个加速属性,如下所示:

[NSNumber numberWithInteger:(NSInteger)view]
UIView+加速度。h:

@interface UIView ( Acceleration )
@property ( nonatomic ) CGPoint acceleration ;
@end
UIView+acceleration.m

#import <objc/runtime.h>

@implementation UIView ( Acceleration )

const char * kAccelerationKey = "acceleration" ; // should use something with a prefix just in case

-(void)setAcceleration:(CGPoint)acceleration
{
    objc_setAssociatedObject( self, kAccelerationKey, [ NSValue valueWithCGPoint:acceleration ], OBJC_ASSOCIATION_RETAIN_NONATOMIC ) ;
}

-(CGPoint)acceleration
{
    return [ objc_setAssociatedObject( self, kAccelerationKey ) CGPointValue ] ;
}

@end
#导入
@实现视图(加速)
const char*kAccelerationKey=“加速度”//应该使用带有前缀的东西以防万一
-(无效)设定加速度:(CGPoint)加速度
{
objc_setAssociatedObject(self,kaAccelerationKey,[NSValue valueWithCGPoint:acceleration],objc_ASSOCIATION_RETAIN_NONATOMIC);
}
-(CGPoint)加速度
{
返回[objc_setAssociatedObject(self,kAccelerationKey)CGPointValue];
}
@结束

删除
-accelerationForView:
-willRemoveSubview:
并使用
view.acceleration=
=view.acceleration

这些演示片段在哪里?您必须发布代码。您需要在此处显示实际片段以供检查。表面上看,这样做没有什么好的理由(甚至没有太多坏的理由)。@BenZotto:
sizeof(int)
不能保证等于
sizeof(id)
,所以就是这样。事实上,在64位Mac上,它显然不是。它们显然使用视图的地址作为密钥。提供64位地址是不可靠的,但从技术上讲是合法的。这是危险的。看起来原始工程师正试图使用对对象的弱引用作为字典的键。问题是,如果解除分配键对象(视图),最终将导致有效的内存泄漏。如果在内存中的同一点分配了另一个视图,那么您就有了与之关联的数据,而这些数据不应该被分配。更不用说
sizeof(id)
并不总是等于
sizeof(int)
,这意味着演员可以丢弃重要的部分。@JonathanGrynspan我不知道我是否会称之为危险——视图本身并不会被释放。只要字典跟踪的视图由一个对象(如包含视图或视图控制器)管理,我就不认为这是一件可怕的事情。不过,同意你的第二点——假设一个指针与
int
的大小相同是一个糟糕的计划。最初的作者使用
+numberwinteger:
的想法是正确的,因为
NSInteger
更接近指针的大小,但是强制转换应该是
NSInteger
,而不是
int
。如果您想使用弱键映射到对象,请同时查看nshashMap,如果要封装对象指针,请使用
+[NSValue valueWithPointer:
@nielsbot这就是人们喜欢Lisp的原因。由于只有一个数据结构,因此不会有选择错误数据结构的危险。;-)根据代码的编写时间,原始作者可能没有该选项。此外,将其添加到
UIView
中的一个缺点是,应用程序中的每个视图都会有加速,这可能会有些过头。更好的方法可能是创建一个跟踪加速的UIView子类。然后,您可以将其用作任何其他视图的容器。我更喜欢组合而不是子类化。这里的要点是显式地将
加速
添加到系统中的所有UIView中,这样就不必用子类替换所有的
UIView
s。(它只是普通的老版本
UIView
)资源消耗几乎为零,大约等于OP的当前代码。2种方法(每个进程存在一次),除已设置了
加速
的视图外,存储为零。