在Swift中使用NSUndomanager在命令模式中实现撤消/重做

时间:2019-04-17 23:01:50

标签: swift undo undo-redo command-pattern nsundomanager

我正在尝试在Swift中为macOS编写的简单绘画程序中实现撤消/重做选项。我遇到过NSUndoManager,但无法使其与Command-Pattern(在程序中实现的协议)结合使用

我为命令模式实现了以下协议:

import Foundation

protocol Command {
    func execute()

    func unexecute()
}

为了简化问题,我简化了ViewController:

我的ViewController:

class ViewController: NSViewController {
    var brect = true
    var startPoint: NSPoint?
    var endPoint: NSPoint?

    lazy var window: NSWindow = self.view.window!
    var mouseLocation: NSPoint {
        return NSEvent.mouseLocation
    }

    var location: NSPoint {
        return window.mouseLocationOutsideOfEventStream
    }

    override func mouseDown(with event: NSEvent) {
        startPoint = event.locationInWindow
    }

    override func mouseUp(with event: NSEvent) {
        endPoint = event.locationInWindow

        let x = min(endPoint!.x, startPoint!.x)
        let y = min(endPoint!.y, startPoint!.y)
        let w = abs((endPoint?.x)! - (startPoint?.x)!)
        let h = abs((endPoint?.y)! - (startPoint?.y)!)

        let positions = NSMakeRect(0, 0, 0, 0)

        DrawShape(x: x, y: y, w: w, h: h, positions: positions, drawRect: brect, view: view).execute()
    }

    class DrawShape: Command {
        let x: CGFloat
        let y: CGFloat
        let w: CGFloat
        let h: CGFloat
        let positions: NSRect
        let brect: Bool
        let v: NSView

        init(x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat, positions: NSRect, drawRect: Bool, view: NSView) {
            self.x = x
            self.y = y
            self.w = w
            self.h = h
            self.positions = positions
            brect = drawRect
            v = view
        }

        func execute() {
            let frame = NSRect(x: x, y: y, width: w, height: h)

            if frame.width > 0, frame.height > 0 {
                Drawing(frame: frame, positions: positions, drawRect: brect, view: v)
            }
        }

        func unexecute() {
            print(" ")
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(frameBoxInfo)

    }

    override var representedObject: Any? {
        didSet {
            // Update the view, if already loaded.
        }
    }
}

我尝试添加

undoManager?.registerUndo(withTarget: self, selector: #selector(readd), object: frame)

到DrawShape类中的execute函数,但不幸的是,我收到以下错误:

Instance member 'undoManager' of type 'NSResponder' cannot be used on instance of nested type 'ViewController.DrawShape'

预期/期望的结果是能够迅速在CommandPattern实现中使用undoManager注册撤消(用于撤消和重做命令)。实际结果是我无法越过该错误并且能够撤消/重做任何事情。

0 个答案:

没有答案