在一些多点触控“屏幕上绘图”代码的维护中,我遇到了一个错误,相对于如何在touchesBegan:withEvent:,touchesMoved:withEvent:和touchesEnded:withEvent:。
之间设置对触摸实例的引用。代码使用NSDictionary实例在touchesBegan:withEvent:中存储touches的引用,如下所示:
for (UITouch *touch in touches]) {
NSValue *touchValue = [NSValue valueWithPointer:touch];
NSString *key = [NSString stringWithFormat:@"%@", touchValue];
[myTouches setValue:squiggle forKey:key];
}
并以touchesEnded:withEvent检索它们:这样:
for (UITouch *touch in touches) {
NSValue *touchValue = [NSValue valueWithPointer:touch];
NSString *key = [NSString stringWithFormat:@"%@", touchValue];
NSObject *valueFromDictionary = [myTouches valueForKey:key];
[myTouches removeObjectForKey:key];
}
在最后一段代码中,valueFromDictionary偶尔会出现nil,因为字典不知道密钥。偶尔,我的意思是大约1%的时间。
现在设定了上下文,我的问题是:
知道为什么这个代码有问题吗?我不确定为什么它不起作用,特别是因为错误频率很低
Some doc from Apple声明使用UITouch对象的地址作为键是个好主意:但这意味着使用NSValue *对象而不是NSString *对象(,因此使用CFDictionaryRef而不是NSDictionary,因为UITouch没有实现复制协议。 如何存储地址的NSString表示而不是NSValue本身不能成为能够使用NSDictionary的简单解决方案? 更新:Apple已更新页面并删除了存储示例通过NSString创建一个UITouch,只是提到了非对象的CFDictionaryRef解决方案。
我担心我离C和指针很远,需要帮助才能理解这段代码中存在错误的原因。
答案 0 :(得分:4)
当你使用stringWithFormat将NSValue实例转换为字符串时,我相信你实际上是在调用[touchValue description],我不确定它是否保证一致的结果。例如,如果描述包含指向NSValue实例本身的指针,那么会有多少个对象呢?在这种情况下,存储完全相同指针的两个不同的NSValue实例将产生不同的字符串键。
我有兴趣看看运行以下代码时会发生什么:
for (UITouch *touch in touches) {
NSValue *touchValue = [NSValue valueWithPointer:touch];
NSString *key = [NSString stringWithFormat:@"%@", touchValue];
NSObject *valueFromDictionary = [myTouches valueForKey:key];
if (valueFromDictionary == nil) {
NSLog(@"%@", [myTouches allKeys]);
NSLog(@"%@", key);
}
[myTouches removeObjectForKey:key];
}
这将告诉我们关于密钥的确切变化。但是如果你只是想解决你遇到的问题,我敢打赌,如果你直接使用NSValue对象作为密钥,它会起作用,因为它确实符合NSCopying协议。本质上,指针(UITouch *)只是一个唯一标识UITouch实例存储在内存中的位置的数字。 NSValue以与NSNumber相同的方式封装此数字,因此您可以将其视为数组中的数字键。只要触摸继续占据内存中的相同位置(正如Apple建议的那样),它应该完美地作为键,并且您的代码将更简单:
(的touchesBegan:withEvent:方法)
for (UITouch *touch in touches]) {
NSValue *key = [NSValue valueWithPointer:touch];
[myTouches setValue:squiggle forKey:key];
}
(touchesEnded:withEvent:方法)
for (UITouch *touch in touches) {
NSValue *key = [NSValue valueWithPointer:touch];
NSObject *valueFromDictionary = [myTouches valueForKey:key];
[myTouches removeObjectForKey:key];
}
除非您需要使用键值编码或将字典序列化到属性列表,否则没有理由将自己局限于字符串键。
答案 1 :(得分:4)
您可以将hash
UITouch
属性用于ObjC和Swift。对于跨多个事件(向上,向下,移动等)的相同触摸,它是相同的。它是Int
,但您可以将其转换为String
答案 2 :(得分:0)
g1 = 0 if self.getValue(g1) > 20 else self.getBenifit(g1)
g2 = 0 if self.getValue(g2) > 20 else self.getBenifit(g2)
答案 3 :(得分:-1)
不要使用
NSString *key = [NSString stringWithFormat:@"%@", touchValue];
为钥匙。最好的方法是将触摸指针值设置为键
id key = touch;
或者如果你喜欢字符串,请使用这种情况:
NSString *key = [NSString stringWithFormat:@"%x", touch]; // %x prints hex value of touch