Я работаю над примером настольного приложения для тестирования класса UndoManager
, которым я не часто пользуюсь. В любом случае, идея заключается в следующем.
- Я создаю два
NSView
вспомогательных объекта вида (красный и синий). Они добавляются к объекту NSView
, связанному с IBOutlet (panView). - Я добавляю жест панорамирования (
NSPanGestureRecognizer
) к этим двум объектам вспомогательного представления. - Приложения вызывают отмену менеджер, когда пользователь перемещает любой вспомогательный объект.
Ниже приведен весь мой код сверху вниз.
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
}
}
}
}
Работает. Это не cra sh. Просто мне нужно дважды нажать Ctrl + Z, чтобы отменить ход. И я должен нажать Ctrl + Shift + Z дважды, чтобы повторить ход. Так что я не знаю, откуда эта пауза. Что я делаю не так, ты знаешь? Спасибо.