2016-09-18 7 views
4

Xcode 7/Swift 2.2のMac OS XプロジェクトをXcode 8/Swift 3に移行しています。私はView ControllerクラスでundoManagerを使用して問題に遭遇しました。 MyViewController:機能を元に戻します。Swift 3でNSUndoManagerと.prepare(withInvocationTarget :)を使用する

Xcodeで7 /スウィフト2.2、これはうまく働いた:

if let target = undoManager?.prepare(withInvocationTarget: self) as? MyViewController { 
    target.undo(data, moreData: moreData) 
    undoManager?. setActionName("Change Data") 
} 

undoManager?.prepareWithInvocationTarget(self).undo(data, moreData: moreData) 
undoManager?.setActionName("Change Data) 

Xcodeで8は/スイフト3、https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html

から推奨パターンを使用してこのように変更する必要があり

しかし、MyViewControllerへのダウンキャストは常に失敗し、取り消し操作は登録されません。

私はここで何かが分かりませんか、これはバグですか?

答えて

7

prepareWithInvocationTarget(_:)(またはSwift 3ではprepare(withInvocationTarget:))は、Swift 3ランタイムがうまく動作しない隠しプロキシオブジェクトを作成します。

(あなたはバグがあり、バグレポートを送っていることを呼び出すことができます。)

あなたの目的を達成するために、あなたはregisterUndo(withTarget:handler:)を使用することはできませんか?

undoManager?.registerUndo(withTarget: self) {targetSelf in 
    targetSelf.undo(data, moreData: moreData) 
} 
+0

ありがとうございました。私もそれを周りに遊んだ。残念ながら、それはOS10.10と互換性がありませんが、おそらくその上に移動する時間です。 – jbaraga

+1

OS 10.10の解決策: 'registerUndo(with:Target:selector:object:)'を使用してください。単一の値を保存するのに問題はありません。複数の値を保存するには、それらを辞書にパックし、それを「オブジェクト」パラメータに使用します。元に戻す操作のために、私は辞書から解凍します。 – jbaraga

+0

@jbaraga、ご報告いただきありがとうございます。しかし、なぜそれを別の答えとして投稿しないのですか? 10.10で作業する必要がある開発者にとっては、何らかの助けになるかもしれません。 – OOPer

1

OS 10.10との下位互換性のための解決策:registerUndo(with Target: selector: object:)を使用してください。単一の値を保存するのに問題はありません。複数の値を保存するには、それらを辞書にパックし、それを「オブジェクト」パラメータに使用します。取り消し操作では、辞書から解凍してから、それらの値でOS10.11 + undoメソッドを呼び出します。

+0

ありがとうございます。 "複数の値"のケースコードを含めることで、より多くの人が簡単にあなたの答えを見つけることができます便利です。それにはしばらく時間をかけてください。 – OOPer

2

私は同じ問題を抱えていました。私はiOS 8とMacOS 10.10のサポートを削除したり、Swift 2.3に戻ったりする用意がありませんでした。 registerUndo(withTarget:handler)構文はいえいいですので、私は基本的にはそれだけの私自身のバージョンロール:

/// An extension to undo manager that adds closure based 
/// handling to OS versions where it is not available. 
extension UndoManager 
{ 
    /// Registers an undo operation using a closure. Behaves in the same wasy as 
    /// `registerUndo(withTarget:handler)` but it compatible with older OS versions. 
    func compatibleRegisterUndo<TargetType : AnyObject>(withTarget target: TargetType, handler: @escaping (TargetType) ->()) 
    { 
     if #available(iOS 9.0, macOS 10.11, *) 
     { 
      self.registerUndo(withTarget: target, handler: handler) 
     } 
     else 
     { 
      let operation = BlockOperation { 
       handler(target) 
      } 
      self.registerUndo(withTarget: self, selector: #selector(UndoManager.performUndo(operation:)), object: operation) 
     } 
    } 

    /// Performs an undo operation after it has been registered 
    /// by `compatibleRegisterUndo`. Should not be called directly. 
    func performUndo(operation: Operation) 
    { 
     operation.start() 
    } 
} 

をうまくいけば、それはあまりにも他の誰かに便利です。

関連する問題