У меня есть представление под названием «TestDraw», где я могу перетаскивать UILables из collectionView.На «TestDraw» также разрешено свободное рисование.Я также установил BarItems для очистки холста.Однако, например, если я перетаскиваю две метки и рисую линию, затем нажимаю кнопку «Очистить», и при повторной попытке перетаскивания приложение вылетает.
Я использую Xcode 10.2, Swift 4.2.Вывод консоли при сбое:
2019-04-07 12:52:24.346501+0800 TrailingTest[497:23125599] -[OS_dispatch_group convertPoint:fromLayer:]: unrecognized selector sent to instance 0x6000011b13b0
2019-04-07 12:52:24.389911+0800 TrailingTest[497:23125599] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[OS_dispatch_group convertPoint:fromLayer:]: unrecognized selector sent to instance 0x6000011b13b0'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e4786fb __exceptionPreprocess + 331
1 libobjc.A.dylib 0x000000010da1cac5 objc_exception_throw + 48
2 CoreFoundation 0x000000010e496ab4 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x000000010e47d443 ___forwarding___ + 1443
4 CoreFoundation 0x000000010e47f238 _CF_forwarding_prep_0 + 120
5 UIKitCore 0x0000000117b984e7 -[UIView(Geometry) convertPoint:fromView:] + 102
6 UIKitCore 0x0000000117b98126 __38-[UIView(Geometry) hitTest:withEvent:]_block_invoke + 102
7 CoreFoundation 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483
8 UIKitCore 0x0000000117b97ce8 -[UIView(Geometry) hitTest:withEvent:] + 460
9 UIKitCore 0x0000000117b981ea -[UIView(Geometry) _hitTest:withEvent:windowServerHitTestWindow:] + 87
10 UIKitCore 0x0000000117b98139 __38-[UIView(Geometry) hitTest:withEvent:]_block_invoke + 121
11 CoreFoundation 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483
12 UIKitCore 0x0000000117b97ce8 -[UIView(Geometry) hitTest:withEvent:] + 460
13 UIKitCore 0x0000000117b981ea -[UIView(Geometry) _hitTest:withEvent:windowServerHitTestWindow:] + 87
14 UIKitCore 0x0000000117b98139 __38-[UIView(Geometry) hitTest:withEvent:]_block_invoke + 121
15 CoreFoundation 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483
16 UIKitCore 0x0000000117b97ce8 -[UIView(Geometry) hitTest:withEvent:] + 460
17 UIKitCore 0x0000000117b981ea -[UIView(Geometry) _hitTest:withEvent:windowServerHitTestWindow:] + 87
18 UIKitCore 0x0000000117b98139 __38-[UIView(Geometry) hitTest:withEvent:]_block_invoke + 121
19 CoreFoundation 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483
20 UIKitCore 0x0000000117b97ce8 -[UIView(Geometry) hitTest:withEvent:] + 460
21 UIKitCore 0x0000000117b981ea -[UIView(Geometry) _hitTest:withEvent:windowServerHitTestWindow:] + 87
22 UIKitCore 0x0000000117b98139 __38-[UIView(Geometry) hitTest:withEvent:]_block_invoke + 121
23 CoreFoundation 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483
24 UIKitCore 0x0000000117b97ce8 -[UIView(Geometry) hitTest:withEvent:] + 460
25 UIKitCore 0x0000000117b981ea -[UIView(Geometry) _hitTest:withEvent:windowServerHitTestWindow:] + 87
26 UIKitCore 0x0000000117b98139 __38-[UIView(Geometry) hitTest:withEvent:]_block_invoke + 121
27 CoreFoundation 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483
28 UIKitCore 0x0000000117b97ce8 -[UIView(Geometry) hitTest:withEvent:] + 460
29 UIKitCore 0x0000000117b74223 -[UITransitionView hitTest:withEvent:] + 44
30 UIKitCore 0x0000000117b981ea -[UIView(Geometry) _hitTest:withEvent:windowServerHitTestWindow:] + 87
31 UIKitCore 0x0000000117b98139 __38-[UIView(Geometry) hitTest:withEvent:]_block_invoke + 121
32 CoreFoundation 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483
33 UIKitCore 0x0000000117b97ce8 -[UIView(Geometry) hitTest:withEvent:] + 460
34 UIKitCore 0x0000000117b981ea -[UIView(Geometry) _hitTest:withEvent:windowServerHitTestWindow:] + 87
35 UIKitCore 0x00000001177346bc -[UIWindow _hitTestLocation:inScene:withWindowServerHitTestWindow:event:] + 194
36 UIKitCore 0x0000000117734455 __70+[UIWindow _hitTestToPoint:forEvent:windowServerHitTestWindow:screen:]_block_invoke + 159
37 UIKitCore 0x0000000117734157 +[UIWindow _topVisibleWindowPassingTest:] + 506
38 UIKitCore 0x0000000117734358 +[UIWindow _hitTestToPoint:forEvent:windowServerHitTestWindow:screen:] + 245
39 UIKitCore 0x0000000117734571 +[UIWindow _globalHitTestForLocation:inWindowServerHitTestWindow:withEvent:] + 223
40 UIKitCore 0x00000001177c9424 -[_UIDragEventSample hitTestWithEvent:constrainToWindowServerHitTestContext:] + 250
41 UIKitCore 0x00000001177ca325 -[UIDragEvent _updateGesturesFromCurrentSample] + 202
42 UIKitCore 0x00000001177ca171 -[UIDragEvent _updateFromCurrentSample] + 649
43 UIKitCore 0x00000001177ca217 -[UIDragEvent _sendIfNeeded] + 72
44 UIKitCore 0x00000001171dd4ca __48-[_UIInternalDraggingSessionDestination connect]_block_invoke + 1010
45 UIKitCore 0x00000001171e2da9 __59-[_UIDruidDestinationConnection initWithSessionIdentifier:]_block_invoke.1547 + 679
46 libdispatch.dylib 0x0000000110ac2db5 _dispatch_client_callout + 8
47 libdispatch.dylib 0x0000000110ac62ba _dispatch_block_invoke_direct + 300
48 FrontBoardServices 0x0000000119750146 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
49 FrontBoardServices 0x000000011974fdfe -[FBSSerialQueue _performNext] + 451
50 FrontBoardServices 0x0000000119750393 -[FBSSerialQueue _performNextFromRunLoopSource] + 42
51 CoreFoundation 0x000000010e3dfbe1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
52 CoreFoundation 0x000000010e3df463 __CFRunLoopDoSources0 + 243
53 CoreFoundation 0x000000010e3d9b1f __CFRunLoopRun + 1231
54 CoreFoundation 0x000000010e3d9302 CFRunLoopRunSpecific + 626
55 GraphicsServices 0x0000000113bc62fe GSEventRunModal + 65
56 UIKitCore 0x00000001176e7ba2 UIApplicationMain + 140
57 TrailingTest 0x000000010d0f1c0b main + 75
58 libdyld.dylib 0x0000000110b37541 start + 1
59 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Это функция очистки холста и того, где он называется:
func ClearCanvas () {
path.removeAllPoints()
self.layer.sublayers = nil
self.setNeedsDisplay()
}
@IBAction func clear(_ sender: UIBarButtonItem) {
if TestDraw.path != nil{
TestDraw.ClearCanvas()
}
}
Я буду очень благодарен, если кто-нибудь сможет мне помочьисправить это или, по крайней мере, дать некоторые подсказки и навыки отладки, которые могут мне помочь.Большое спасибо!
Вот код для реализации collectionView:
class DocumentViewController: UIViewController,UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDragDelegate, UICollectionViewDropDelegate {
var numbersChoices = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"]
var numberOfCorrectMatches = 0
private var font: UIFont {
return UIFontMetrics(forTextStyle: .body).scaledFont(for: UIFont.preferredFont(forTextStyle: .body).withSize(60.0))
}
private var numberCardsSet: NumberCardsSet?{
get{
let cards = TestDraw.subviews.compactMap{$0 as? UILabel}.compactMap{NumberCardsSet.CardInfo(label: $0)}
return NumberCardsSet(numberCards: cards)
}
set{
TestDraw.subviews.compactMap{$0 as? UILabel}.forEach{$0.removeFromSuperview()}
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numbersChoices.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "numberCell", for: indexPath)
if let numberCell = cell as? numberCollectionViewCell{
let text = NSAttributedString(string: numbersChoices[indexPath.item], attributes: [.font:font])
numberCell.label.attributedText = text
}
return cell
}
func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] {
return dragItems(at: indexPath)
}
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
session.localContext = collectionView
return dragItems(at: indexPath)
}
func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool {
return session.canLoadObjects(ofClass: NSAttributedString.self)
}
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
let isSelf = (session.localDragSession?.localContext as? UICollectionView) == collectionView
return UICollectionViewDropProposal(operation: isSelf ? .move: .copy, intent: .insertAtDestinationIndexPath)
}
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
let destinationIndexPath = coordinator.destinationIndexPath ?? IndexPath(item: 0, section: 0)
for item in coordinator.items {
if let sourceIndexPath = item.sourceIndexPath{
if let attributedString = item.dragItem.localObject as? NSAttributedString{
collectionView.performBatchUpdates({numbersChoices.remove(at: sourceIndexPath.item)
numbersChoices.insert(attributedString.string, at: destinationIndexPath.item)
collectionView.deleteItems(at: [sourceIndexPath])
collectionView.insertItems(at: [destinationIndexPath])})
}
coordinator.drop(item.dragItem, toItemAt: destinationIndexPath)
}else{
let placeholderContext = coordinator.drop(item.dragItem, to: UICollectionViewDropPlaceholder(insertionIndexPath: destinationIndexPath, reuseIdentifier: "DropPlaceholderCell"))
item.dragItem.itemProvider.loadObject(ofClass: NSAttributedString.self){(provider, error) in DispatchQueue.main.sync {
if let attributedString = provider as? NSAttributedString{
placeholderContext.commitInsertion(dataSourceUpdates: {insertionIndexPath in
self.numbersChoices.insert(attributedString.string, at: insertionIndexPath.item)
})
}else {
placeholderContext.deletePlaceholder()
}
}
}
}
}
}
private func dragItems (at indexPath: IndexPath) -> [UIDragItem]{
if let attributedString = (numberCollectionView.cellForItem(at: indexPath) as? numberCollectionViewCell)?.label.attributedText{
let dragItem = UIDragItem(itemProvider: NSItemProvider(object: attributedString))
dragItem.localObject = attributedString
return [dragItem]
}else {
return []
}
}
...
}
Вот код для реализации перетаскивания на холсте:
class TrailingCanvas: UIView,UIDropInteractionDelegate {
var UserMatchingLocation = [CGFloat]()
var UILabelLocation = [CGFloat]()
required init?(coder aDecoder: NSCoder) {
super.init(coder:aDecoder)
setup()
}
private func setup() {
addInteraction(UIDropInteraction(delegate: self))
}
func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
return session.canLoadObjects(ofClass: NSAttributedString.self)
}
func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
return UIDropProposal(operation: .copy)
}
func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
session.loadObjects(ofClass: NSAttributedString.self){
providers in
let dropPoint = session.location(in: self)
for attributedString in providers as? [NSAttributedString] ?? []{
self.addLabel(with: attributedString, centeredAt: dropPoint)
}
}
}
private func addLabel (with attributedString:NSAttributedString, centeredAt point: CGPoint){
let label = UILabel()
label.backgroundColor = .clear
label.attributedText = attributedString
label.sizeToFit()
label.center = point
addSubview(label)
UILabelLocation.append(point.x)
print(point.x)
}
...
}
Вотскриншот основной раскадровки. mainstoryboard
Я также создал репо на Github.Вот ссылка: https://github.com/Feanor007/TrailingTest-repo