ios - 清理画布时拖放新的 UILables 时出现错误,如何解决?
问题描述
我有一个名为“TestDraw”的视图,我可以在其中从 collectionView 拖放 UILables。在“TestDraw”上,也允许自由绘图。我还设置了 BarItems 来清除画布。但是,例如,如果我拖放两个标签并画一条线然后点击清除,当我再次尝试拖放时,应用程序崩溃。
我正在使用 Xcode 10.2、Swift 4.2。崩溃时的控制台输出是:
2019-04-07 12:52:24.346501+0800 TrailingTest[497:23125599]-[OS_dispatch_group convertPoint:fromLayer:]:无法识别的选择器发送到实例 0x6000011b13b0 2019-04-07 12:52:24.389911+0800 TrailingTest[497:23125599] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[OS_dispatch_group convertPoint:fromLayer:]:无法识别的选择器发送到实例 0x6000011b13b0” *** 首先抛出调用堆栈: ( 0 核心基础 0x000000010e4786fb __exceptionPreprocess + 331 1 libobjc.A.dylib 0x000000010da1cac5 objc_exception_throw + 48 2核心基础0x000000010e496ab4-[NSObject(NSObject)不识别选择器:]+132 3 核心基础 0x000000010e47d443 ___forwarding___ + 1443 4 核心基础 0x000000010e47f238 _CF_forwarding_prep_0 + 120 5 UIKitCore 0x0000000117b984e7 -[UIView(几何)转换点:从视图:] + 102 6 UIKitCore 0x0000000117b98126 __38-[UIView(几何) hitTest:withEvent:]_block_invoke + 102 7 核心基础 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483 8 UIKitCore 0x0000000117b97ce8 -[UIView(几何) hitTest:withEvent:] + 460 9 UIKitCore 0x0000000117b981ea-[UIView(几何)_hitTest:withEvent:windowServerHitTestWindow:] + 87 10 UIKitCore 0x0000000117b98139 __38-[UIView(几何) hitTest:withEvent:]_block_invoke + 121 11 核心基础 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483 12 UIKitCore 0x0000000117b97ce8 -[UIView(几何) hitTest:withEvent:] + 460 13 UIKitCore 0x0000000117b981ea -[UIView(几何)_hitTest:withEvent:windowServerHitTestWindow:] + 87 14 UIKitCore 0x0000000117b98139 __38-[UIView(几何) hitTest:withEvent:]_block_invoke + 121 15 核心基础 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483 16 UIKitCore 0x0000000117b97ce8 -[UIView(几何) hitTest:withEvent:] + 460 17 UIKitCore 0x0000000117b981ea-[UIView(几何)_hitTest:withEvent:windowServerHitTestWindow:] + 87 18 UIKitCore 0x0000000117b98139 __38-[UIView(几何) hitTest:withEvent:]_block_invoke + 121 19 核心基础 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483 20 UIKitCore 0x0000000117b97ce8 -[UIView(几何) hitTest:withEvent:] + 460 21 UIKitCore 0x0000000117b981ea -[UIView(几何)_hitTest:withEvent:windowServerHitTestWindow:] + 87 22 UIKitCore 0x0000000117b98139 __38-[UIView(几何) hitTest:withEvent:]_block_invoke + 121 23 核心基础 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483 24 UIKitCore 0x0000000117b97ce8 -[UIView(几何) hitTest:withEvent:] + 460 25 UIKitCore 0x0000000117b981ea-[UIView(几何)_hitTest:withEvent:windowServerHitTestWindow:] + 87 26 UIKitCore 0x0000000117b98139 __38-[UIView(几何) hitTest:withEvent:]_block_invoke + 121 27 核心基础 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483 28 UIKitCore 0x0000000117b97ce8 -[UIView(几何) hitTest:withEvent:] + 460 29 UIKitCore 0x0000000117b74223 -[UITransitionView hitTest:withEvent:] + 44 30 UIKitCore 0x0000000117b981ea -[UIView(几何)_hitTest:withEvent:windowServerHitTestWindow:] + 87 31 UIKitCore 0x0000000117b98139 __38-[UIView(几何) hitTest:withEvent:]_block_invoke + 121 32 核心基础 0x000000010e3a4013 -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 483 33 UIKitCore 0x0000000117b97ce8 -[UIView(几何) hitTest:withEvent:] + 460 34 UIKitCore 0x0000000117b981ea -[UIView(几何)_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 连接]_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 前板服务 0x0000000119750146 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30 49 前板服务 0x000000011974fdfe -[FBSSerialQueue _performNext] + 451 50 前板服务 0x0000000119750393 -[FBSSerialQueue _performNextFromRunLoopSource] + 42 51 核心基础 0x000000010e3dfbe1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 52 核心基础 0x000000010e3df463 __CFRunLoopDoSources0 + 243 53 核心基础 0x000000010e3d9b1f __CFRunLoopRun + 1231 54 核心基础 0x000000010e3d9302 CFRunLoopRunSpecific + 626 55 图形服务 0x0000000113bc62fe GSEventRunModal + 65 56 UIKitCore 0x00000001176e7ba2 UIApplicationMain + 140 57 尾随测试 0x000000010d0f1c0b 主要 + 75 58 libdyld.dylib 0x0000000110b37541 开始 + 1 59 ???0x0000000000000001 0x0 + 1 ) libc++abi.dylib:以 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)
}
...
}
这是主故事板的屏幕截图。 主线故事板
我还在 Github 上创建了一个 repo。这是链接:https ://github.com/Feanor007/TrailingTest-repo
解决方案
推荐阅读
- node.js - 如何用猫鼬添加 GeoJson 数据?
- node.js - 使用 npm run 脚本时 Process.send 不是函数
- javascript - 如何动态分组数组文字中的多个制表符范围(通过使用通配符)?
- dart - dart 中第 2d 列列表的洗牌
- r - 在 cor.test 中查看描述性摘要
- configuration - 永久禁用 gdb 启动文本
- sql - Rails:一次加载关联与多个微小查询
- python - NetworkX 中的弯曲边缘
- discord.py - 我正在尝试向已设置频道的每个人发送消息,但发送消息时遇到问题
- python-3.x - 如何计算python中指数值的均值和标准差?