2010-09-28 70 views
1

這個問題真的有我難倒...崩潰而CALayer的-hitTest:

我有使用UIPanGestureRecognizer和我用我的handlePanGesture內的下列方法調用一個iPad項目:

- (AIEnemyUnit *) hitTestForEnemyUnit:(CGPoint)where { 
    CALayer * layer = [self hitTest:where]; 

    while (layer) { 
     if ([layer isKindOfClass:[AIEnemyUnit class]]) { 
      return (AIEnemyUnit *)layer; 
     } else { 
      layer = layer.superlayer; 
     } 
    } 

    return nil; 
} 

一旦我「找到」一個AIEnemyUnit層,我繼續拖動,一切正常。除了關於圍繞6日至10日「拖」我與調試器崩潰中只有CALayer的-hitTest深:

modifying layer that is being finalized - 0x124530 
*** -[NSCFSet hitTest:]: unrecognized selector sent to instance 0x124530 
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: 
'*** -[NSCFSet hitTest:]: unrecognized selector sent to instance 0x124530' 

回答

1

從它看起來像你的症狀有CALayer的的過度釋放。

兩個領域,你應該檢查:

1)你是「拯救」這個CALayer中的變量,而不保留它?如果你碰到任何autorelease池(包括主線程中提供的那個),那麼這些層可能會無意中被釋放。正如評論中指出的那樣,由於這些不是自動釋放的,所以這可能發生在沒有觸及池的情況下。然而,當您持有參考文件時,CALayer可以在任何時候發生。

2)稍後你明確地在這個層上調用release。既然你給這個圖層原樣(hitTest:superlayer返回對象沒有額外的保留計數),你沒有所有權,因此不應該釋放它。

另一個有用的調試工具是使用NSZombies和其他一些鏈接在那裏的技術。 NSZombies基本上允許你的應用程序在你訪問一個釋放對象的時刻崩潰,希望能給你一個更有意義的堆棧跟蹤。

+0

很好的答案。有一件事:'hitTest:'和'superlayer'返回的圖層不是自動發佈的,但它們也不會被保留。這可能會導致崩潰:'CALayer * sublayer = [[layer sublayers] objectAtIndex:0]; [sublayer removeFromSuperlayer]; [sublayer superlayer];' – rpetrich 2010-09-28 08:51:20

+0

謝謝,我不太確定,但知道他們不屬於主叫方。修復。 – bobDevil 2010-09-28 15:03:32

+0

謝謝你的修復!我已經從'@synthesize dragItem'切換過來了;'到一個手動設置器並忘記設置'dragItem = [newDragItem retain];'。我在其他帖子中看到「修改正在定稿的圖層」消息與保留計數問題有關,但是我的錯誤消息完全不同,所以我不確定這是否是答案。但由於其他職位,我仔細檢查了我的代碼,看看我調用了多少次-release和-removeFromSuperlayer。我非常專注於發佈方面,我沒有考慮保留,所以謝謝 – 2010-09-28 16:28:26

0

我認爲hitTest文檔實際上存在一些「錯誤信息」。我遇到了一個類似的問題,我把4個子類視圖的實例放到窗口上,每個子視圖都有4個子層。 4個視圖子類中的每一個都有一個touchesBegan:withEvent方法和一個touchesEnded:withEvent方法。我發現如果我的觸摸着陸或結束在最左上角的視圖中,我的hitTest返回了一個有效的子圖層。但是,其他三個視圖中的任何hitTest都返回nil給子圖層。和你一樣,我完全被困住了,直到我決定用視窗的座標系統替換視圖座標系統中的接觸點,然後全部工作。我重現了hitTest方法的文檔:

hitTest: 返回包含指定點的層次結構(包括它本身)中接收器的最遠後代。

- (CALayer *)hitTest:(CGPoint)thePoint 

參數 thePoint 接收機superlayer的座標系中的一個點。 返回值 包含Point的圖層,或者如果點位於接收方的邊界矩形之外,則爲nil。

可用性 適用於Mac OS X v10.5及更高版本。 聲明 CALayer.h

根據我的觀察,我會爭辯說'thePoint'的解釋是錯誤的。我認爲它應該是'包含接收器的窗口的座標系中的一個點。「我認爲左上角視圖提供有效hitTests的唯一原因是觸摸的座標 - 在該位置 - 與窗口中觸摸的座標相同。不知道這是否對你有幫助,但是這有助於我的邏輯工作。 V.V.