I have a View called “TestDraw” where I can drag and drop UILables from the collectionView. On the “TestDraw”, free-drawing is also allowed. I have also set BarItems for clearing the canvas. However, for example, if I drag and drop two labels and draw a line then hit clear, and when I try to drag and drop again, the app crashes.
I am using Xcode 10.2, Swift 4.2. The console output when it crashes is:
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
This is the function of clearing the canvas and where it is called:
func ClearCanvas () {
path.removeAllPoints()
self.layer.sublayers = nil
self.setNeedsDisplay()
}
@IBAction func clear(_ sender: UIBarButtonItem) {
if TestDraw.path != nil{
TestDraw.ClearCanvas()
}
}
I will be very thankful if anyone can help me fix this or at least provide some clues and debugging skills that might help me. Many thanks!
Here is the code for implementing 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 []
}
}
...
}
Here is the code for implementing drag and drop on the canvas:
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)
}
...
}
Here is a screenshot of the main storyboard.
mainstoryboard
I have also created a repo on Github. Here is the link: GitHub - Feanor007/Swift_proj: Swift learning