[英]Is there a method called in between touchesBegan and touchesEnded?
[英]How to track touches in a consistent way between touchesBegan: and touchesEnded:?
在一些多點觸控“在屏幕上繪圖”代碼的維護中,我遇到了一個關於如何在 touchesBegan:withEvent:、touchesMoved:withEvent: 和 touchesEnded:withEvent: 之間設置對 touches 實例的引用的錯誤。
代碼使用 NSDictionary 實例在 touchesBegan:withEvent: 中存儲觸摸的引用,如下所示:
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% 的時間。
現在上下文已設置,我的問題是:
知道為什么這段代碼有問題嗎? 我不確定為什么它不起作用,特別是因為錯誤頻率非常低
Apple 的一些文檔指出,使用 UITouch 對象的地址作為鍵是個好主意
:但這意味着使用 NSValue* 對象而不是 NSString* 對象(
因此使用 CFDictionaryRef 而不是 NSDictionary,因為 UITouch 沒有實現復制協議)。
為什么存儲地址的 NSString 表示而不是 NSValue 本身不是能夠使用 NSDictionary 的簡單解決方案?
更新:Apple 已經更新了頁面並刪除了通過 NSString 存儲 UITouch 的示例,並且只提到了 not-object-at-all CFDictionaryRef 解決方案。
恐怕我遠離 C 和指針的東西,需要幫助來理解這段代碼中存在錯誤的原因。
您可以對 ObjC 和 Swift 使用UITouch
屬性的hash
。 對於跨多個事件(向上、向下、移動等)的相同觸摸也是如此。 它是一個Int
但你可以將它轉換為String
當您使用 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];
}
真的沒有理由將自己局限於字符串鍵,除非您需要使用鍵值編碼或將字典序列化為屬性列表。
-(NSString * ) keyForTouch:(UITouch *) touch {
return [NSString stringWithFormat:@"%lu", (unsigned long)[touch hash]];
}
//Example method, how to use:
-(UIView *) getViewForTouch:(UITouch*) touch{
NSString * key = [self keyForTouch:touch];
return [self.myDictionary objectForKey:key];
}
不要使用
NSString *key = [NSString stringWithFormat:@"%@", touchValue];
為關鍵。 最好的方法是將觸摸指針值設置為鍵
id key = touch;
或者,如果您更喜歡字符串,請使用這種情況:
NSString *key = [NSString stringWithFormat:@"%x", touch]; // %x prints hex value of touch
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.