gpt4 book ai didi

swift - 撤消和重做 NSPanGestureRecognizer 进行的 NSView 对象移动

转载 作者:行者123 更新时间:2023-11-30 10:28:45 28 4
gpt4 key购买 nike

我正在开发一个示例桌面应用程序来测试 UndoManager 类,但我不经常使用该类。无论如何,以下是想法。

  1. 我创建了两个 NSView subview 对象(红色和蓝色)。它们被添加到 IBOutlet 连接的 NSView 对象 (panView)。
  2. 我将平移手势 (NSPanGestureRecognizer) 添加到这两个 subview 对象。
  3. 当用户移动任一 subview 对象时,应用程序调用撤消管理器。

以下是我从上到下的整个代码。

 import Cocoa

class ViewController: NSViewController {
// MARK: - Variables
var myView1 = NSView()
var myView2 = NSView()
var uuid1 = String()
var uuid2 = String()


// MARK: - IBOutlet
@IBOutlet weak var panView: NSView!


// MARK: - Life cycle
override func viewDidLoad() {
super.viewDidLoad()

/* myView */
uuid1 = UUID().uuidString
myView1 = NSView(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 100, height: 100)))
myView1.identifier = NSUserInterfaceItemIdentifier(rawValue: uuid1)
myView1.wantsLayer = true
if let myLayer1 = myView1.layer {
myLayer1.backgroundColor = NSColor.red.cgColor
}
panView.addSubview(myView1)

uuid2 = UUID().uuidString
myView2 = NSView(frame: CGRect(origin: CGPoint(x: 400, y: 200), size: CGSize(width: 100, height: 100)))
myView2.identifier = NSUserInterfaceItemIdentifier(rawValue: uuid2)
myView2.wantsLayer = true
if let myLayer2 = myView2.layer {
myLayer2.backgroundColor = NSColor.blue.cgColor
}
panView.addSubview(myView2)

/* pangesture */
let panRecognizer1 = NSPanGestureRecognizer.init(target: self, action: #selector(panPictureView(_:)))
let panRecognizer2 = NSPanGestureRecognizer.init(target: self, action: #selector(panPictureView(_:)))
myView1.addGestureRecognizer(panRecognizer1)
myView2.addGestureRecognizer(panRecognizer2)
}

// MARK: - Pan gesture
@objc func panPictureView(_ sender: NSPanGestureRecognizer) {
let translation = sender.translation(in: self.view)
if let movingObject = sender.view {
let newPosition = CGPoint(x: movingObject.frame.origin.x + translation.x, y: movingObject.frame.origin.y + translation.y)
movingObject.setFrameOrigin(newPosition)
sender.setTranslation(CGPoint.zero, in: self.view)
if sender.state == .began {
if let rawID = sender.view?.identifier?.rawValue {
let dict = ["point": movingObject.frame.origin, "rawID": rawID] as [String : Any]
redoMoveObject(dict)
}
}
else if sender.state == .ended {
if let rawID = sender.view?.identifier?.rawValue {
let dict = ["point": movingObject.frame.origin, "rawID": rawID] as [String : Any]
undoMoveObject(dict)
}
}
}
}


// MARK: - Undoing move
@objc func undoMoveObject(_ newObject: [String : Any]) {
undoManager?.registerUndo(withTarget: self, selector: #selector(redoMoveObject(_:)), object: newObject)
undoManager?.setActionName("Move Object")
if let point = newObject["point"] as? CGPoint, let rawID = newObject["rawID"] as? String {
if rawID == uuid1 {
myView1.frame.origin = point
}
else {
myView2.frame.origin = point
}
}
}

@objc func redoMoveObject(_ newObject: [String : Any]) {
undoManager?.registerUndo(withTarget: self, selector: #selector(undoMoveObject(_:)), object: newObject)
undoManager?.setActionName("Move Object")
if let point = newObject["point"] as? CGPoint, let rawID = newObject["rawID"] as? String {
if rawID == uuid1 {
myView1.frame.origin = point
}
else {
myView2.frame.origin = point
}
}
}
}

enter image description here

它有效。它不会崩溃。只是我必须按 Command + Z 两次才能撤消移动。我必须按 Command + Shift + Z 两次才能重做移动。所以我不知道这个停顿从何而来。我做错了什么你知道吗?谢谢。

最佳答案

撤消注册了两次:在 redoMoveObject 中的 sender.state == .begansender.state == .ending undoMoveObject(dict)undoMoveObjectredoMoveObject 做同样的事情并互相注册,它们可以合并为一个注册自身的函数。

示例:

// MARK: - Pan gesture
@objc func panPictureView(_ sender: NSPanGestureRecognizer) {
if let movingObject = sender.view {
if sender.state == .began { // register undo before first move
if let rawID = movingObject.identifier?.rawValue {
let dict = ["point": movingObject.frame.origin, "rawID": rawID] as [String : Any]
undoMoveObject(dict)
}
}
let translation = sender.translation(in: self.view)
sender.setTranslation(CGPoint.zero, in: self.view)
let newPosition = CGPoint(x: movingObject.frame.origin.x + translation.x, y: movingObject.frame.origin.y + translation.y)
movingObject.setFrameOrigin(newPosition)
}
}

// MARK: - Undoing move
@objc func undoMoveObject(_ newObject: [String : Any]) {
if let point = newObject["point"] as? CGPoint, let rawID = newObject["rawID"] as? String {
var movingObject: NSView
if rawID == uuid1 {
movingObject = myView1
}
else {
movingObject = myView2
}
// register current frame origin for redo/undo
let dict = ["point": movingObject.frame.origin, "rawID": rawID] as [String : Any]
undoManager?.registerUndo(withTarget: self, selector: #selector(undoMoveObject(_:)), object: dict)
undoManager?.setActionName("Move Object")
// undo/redo
movingObject.frame.origin = point
}
}

关于swift - 撤消和重做 NSPanGestureRecognizer 进行的 NSView 对象移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59610266/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com