<NME> YoyoAction.swift
<BEF> //
//  YoyoAction.swift
//  TweenKit
//
//  Created by Steve Barnegren on 19/03/2017.
//  Copyright © 2017 Steve Barnegren. All rights reserved.
//

import Foundation

/** Animates inner action to end and then back to beginning */
public class YoyoAction: FiniteTimeAction {
    
    // MARK: - Types
    
    enum State {
        case idle
        case forwards
        case backwards
    }
    
    // MARK: - Public
    
    public var onBecomeActive: () -> () = {}
    public var onBecomeInactive: () -> () = {}
    
    public var reverse = false {
        didSet{
            if reverse != oldValue, state != .idle {
                action.reverse = !action.reverse
            }
        }
    }

    /**
     Create with action to yoyo
     - Parameter action: The action to yoyo
     */
    public init(action: FiniteTimeAction) {
    // MARK: - Private Properties
    
    public internal(set) var duration: Double
    let action: FiniteTimeAction
    var state = State.idle
    
    // MARK: - Private Methods
    public internal(set) var duration: Double
    var action: FiniteTimeAction
    var state = State.idle
    
    // MARK: - Private Methods
    
    public func willBecomeActive() {
        onBecomeActive()
        action.willBecomeActive()
    }

    public func didBecomeInactive() {
        onBecomeInactive()
        action.didBecomeInactive()
    }
    
    public func willBegin() {
        self.update(t: reverse ? 1.0 : 0.0)
    }
    
    public func didFinish() {
        
        self.update(t: reverse ? 0.0 : 1.0)
        action.didFinish()
        state = .idle
    }
    
    public func update(t: CFTimeInterval) {
        
        /*
         The order of state changes and setReverse is important here. The inner action should receive the following calls:
         
         - will begin
         - will finish
         - reverse = true
         - will begin
         - will finish
 
         The inner action is 'invoked twice' (two begin/finish calls), and it has the correct reverse state at the time of each call
         There are unit tests that test the call order, please run them after making changes
         */
        
        if t < 0.5 {
            
            if state == .idle {
                action.reverse = reverse
                action.willBegin()
            }
            
            if state == .backwards {
                action.didFinish()
                action.reverse = reverse
                action.willBegin()
            }
            
            let actionT = t * 2
            action.update(t: actionT)
            
            state = .forwards
        }
        else{
            
            if state == .idle {
                action.reverse = !reverse
                action.willBegin()
            }
            
            if state == .forwards {
                action.didFinish()
                action.reverse = !reverse
                action.willBegin()
            }

            let actionT = 1-((t - 0.5) * 2);
            action.update(t: actionT)
            
            state = .backwards
        }
    }
}

public extension FiniteTimeAction {
    
    func yoyo() -> YoyoAction {
        return YoyoAction(action: self)
    }
}

<MSG> Actions now structs instead of classes

<DFF> @@ -40,7 +40,7 @@ public class YoyoAction: FiniteTimeAction {
     // MARK: - Private Properties
     
     public internal(set) var duration: Double
-    let action: FiniteTimeAction
+    var action: FiniteTimeAction
     var state = State.idle
     
     // MARK: - Private Methods

{'commit': 'diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift\nindex 20a5a97..5d9b60b 100644\n--- a/Example/Example/ViewController.swift\n+++ b/Example/Example/ViewController.swift\n@@ -47,7 +47,7 @@ class ViewController: UIViewController {\n     \n     \n      // COMPLEX\n-    /*\n+    \n     func startTheAnimation() {\n         \n         print("Start the animation!")\n@@ -94,11 +94,11 @@ class ViewController: UIViewController {\n         animation.run()\n         \n     }\n-    */\n+ \n     \n     \n      // SEQUENCE\n-    \n+    /*\n     func startTheAnimation() {\n         \n         print("Start the animation!")\n@@ -127,7 +127,7 @@ class ViewController: UIViewController {\n         let animation = Animation(action: sequence)\n         animation.run()\n     }\n- \n+ */\n \n     \n     // GROUP\ndiff --git a/TweenKit/TweenKit/Action.swift b/TweenKit/TweenKit/Action.swift\nindex 8986505..3ac6168 100644\n--- a/TweenKit/TweenKit/Action.swift\n+++ b/TweenKit/TweenKit/Action.swift\n@@ -10,7 +10,7 @@ import Foundation\n \n // MARK: - Shedulable Action\n \n-public protocol SchedulableAction: class {\n+public protocol SchedulableAction {\n     \n     var onBecomeActive: () -> () {get set}\n     var onBecomeInactive: () -> () {get set}\n@@ -49,3 +49,21 @@ extension TriggerAction {\n public protocol InfiniteTimeAction : SchedulableAction {\n     func update(elapsedTime: CFTimeInterval)\n }\n+\n+\n+// MARK: - ****** FiniteTimeActionClassWrapper ******\n+\n+// Some of the container actions rely on identiy comparison (===), so will wrap the action in a class\n+class FiniteTimeActionClassWrapper{\n+    var action: FiniteTimeAction\n+    \n+    init(action: FiniteTimeAction) {\n+        self.action = action\n+    }\n+}\n+\n+extension FiniteTimeAction {\n+    func inClassWrapper() -> FiniteTimeActionClassWrapper {\n+        return FiniteTimeActionClassWrapper(action: self)\n+    }\n+}\ndiff --git a/TweenKit/TweenKit/Group.swift b/TweenKit/TweenKit/Group.swift\nindex 84365b5..2faee9a 100644\n--- a/TweenKit/TweenKit/Group.swift\n+++ b/TweenKit/TweenKit/Group.swift\n@@ -18,7 +18,10 @@ public class Group: FiniteTimeAction, SchedulableAction {\n     \n     public var reverse = false {\n         didSet {\n-            wrappedActions.forEach{ $0.action.reverse = reverse }\n+            wrappedActions = wrappedActions.map{ wrapped in\n+                wrapped.action.reverse = reverse\n+                return wrapped\n+            }\n         }\n     }\n     \n@@ -149,7 +152,7 @@ class GroupActionWrapper {\n         self.action = action\n     }\n     \n-    let action: FiniteTimeAction\n+    var action: FiniteTimeAction\n     \n     var state = State.notStarted {\n         didSet{\ndiff --git a/TweenKit/TweenKit/RepeatAction.swift b/TweenKit/TweenKit/RepeatAction.swift\nindex c3c76b4..b7df555 100644\n--- a/TweenKit/TweenKit/RepeatAction.swift\n+++ b/TweenKit/TweenKit/RepeatAction.swift\n@@ -29,7 +29,7 @@ public class RepeatAction: FiniteTimeAction {\n     }\n \n     public internal(set) var duration: Double\n-    let action: FiniteTimeAction\n+    var action: FiniteTimeAction\n     let repeats: Int\n     var lastRepeatNumber = 0\n     \ndiff --git a/TweenKit/TweenKit/ReverseAction.swift b/TweenKit/TweenKit/ReverseAction.swift\nindex 902a63c..172d8f3 100644\n--- a/TweenKit/TweenKit/ReverseAction.swift\n+++ b/TweenKit/TweenKit/ReverseAction.swift\n@@ -21,7 +21,7 @@ public class ReverseAction: FiniteTimeAction {\n     }\n     \n     // MARK: - Private Properties\n-    let action: FiniteTimeAction\n+    var action: FiniteTimeAction\n     \n     // MARK: - Private Methods\n     \ndiff --git a/TweenKit/TweenKit/Sequence.swift b/TweenKit/TweenKit/Sequence.swift\nindex 68f4743..d56c6e5 100644\n--- a/TweenKit/TweenKit/Sequence.swift\n+++ b/TweenKit/TweenKit/Sequence.swift\n@@ -17,7 +17,7 @@ public class Sequence: FiniteTimeAction {\n     \n     public var reverse = false {\n         didSet {\n-            actions.forEach{ $0.reverse = reverse }\n+            wrappedActions.forEach{ $0.action.reverse = reverse }\n         }\n     }\n \n@@ -37,7 +37,7 @@ public class Sequence: FiniteTimeAction {\n     }\n \n     public func add(action: FiniteTimeAction) {\n-        actions.append(action)\n+        wrappedActions.append( action.inClassWrapper() )\n         calculateDuration()\n         calculateOffsets()\n     }\n@@ -46,22 +46,22 @@ public class Sequence: FiniteTimeAction {\n     \n     public private(set) var duration = Double(0)\n     \n-    private var actions = [FiniteTimeAction]()\n+    private var wrappedActions = [FiniteTimeActionClassWrapper]()\n     private var offsets = [Double]()\n-    private var lastRunAction: FiniteTimeAction?\n+    private var lastRunAction: FiniteTimeActionClassWrapper?\n     \n     // MARK: - Private Methods\n \n     private func calculateDuration() {\n-        duration = actions.reduce(0) { $0 + $1.duration }\n+        duration = wrappedActions.reduce(0) { $0 + $1.action.duration }\n     }\n     \n     private func calculateOffsets() {\n         offsets = [Double]()\n         var offsetPos = 0.0\n         offsets.append(offsetPos)\n-        actions.dropLast().forEach{\n-            offsetPos += $0.duration\n+        wrappedActions.dropLast().forEach{\n+            offsetPos += $0.action.duration\n             offsets.append(offsetPos)\n         }\n     }\n@@ -81,9 +81,9 @@ public class Sequence: FiniteTimeAction {\n     public func didFinish() {\n         \n         // finish the final action\n-        if let lastAction = reverse ? actions.first : actions.last {\n-            lastAction.didFinish()\n-            lastAction.didBecomeInactive()\n+        if let lastAction = reverse ? wrappedActions.first : wrappedActions.last {\n+            lastAction.action.didFinish()\n+            lastAction.action.didBecomeInactive()\n         }\n         \n     }\n@@ -91,7 +91,7 @@ public class Sequence: FiniteTimeAction {\n     public func update(t: CFTimeInterval) {\n         \n         let elapsedTime = t * duration\n-        let enumeratedActions = reverse ? actions.reversed().enumerated() : actions.enumerated()\n+        let enumeratedActions = reverse ? wrappedActions.reversed().enumerated() : wrappedActions.enumerated()\n         \n         // Get the last run action index\n         var lastRunIndex = -1\n@@ -104,7 +104,7 @@ public class Sequence: FiniteTimeAction {\n         }\n         \n         // Update actions\n-        for (index, action) in enumeratedActions {\n+        for (index, wrapper) in enumeratedActions {\n             \n             let offset = reverse ? offsets.reversed()[index] : offsets[index]\n             \n@@ -114,31 +114,31 @@ public class Sequence: FiniteTimeAction {\n             }\n             \n             // Start the action?\n-            if action !== lastRunAction {\n-                action.willBecomeActive()\n-                action.willBegin()\n+            if wrapper !== lastRunAction {\n+                wrapper.action.willBecomeActive()\n+                wrapper.action.willBegin()\n             }\n             \n             // Update the action\n-            let actionT = ((elapsedTime - offset) / action.duration)\n+            let actionT = ((elapsedTime - offset) / wrapper.action.duration)\n                 .constrained(min: 0, max: 1.0)\n             \n-            action.update(t: actionT)\n-            lastRunAction = action\n+            wrapper.action.update(t: actionT)\n+            lastRunAction = wrapper\n             \n             // Continue to the next action?\n             let continueToNext: Bool\n             \n             if reverse {\n-                continueToNext = elapsedTime < offset && index != actions.count - 1\n+                continueToNext = elapsedTime < offset && index != wrappedActions.count - 1\n             }\n             else{\n-                continueToNext = elapsedTime > offset + action.duration && index != actions.count - 1\n+                continueToNext = elapsedTime > offset + wrapper.action.duration && index != wrappedActions.count - 1\n             }\n             \n             if continueToNext {\n-                action.didFinish()\n-                action.didBecomeInactive()\n+                wrapper.action.didFinish()\n+                wrapper.action.didBecomeInactive()\n             }\n             else{\n                 break\ndiff --git a/TweenKit/TweenKit/YoyoAction.swift b/TweenKit/TweenKit/YoyoAction.swift\nindex b6b5646..dc735d1 100644\n--- a/TweenKit/TweenKit/YoyoAction.swift\n+++ b/TweenKit/TweenKit/YoyoAction.swift\n@@ -40,7 +40,7 @@ public class YoyoAction: FiniteTimeAction {\n     // MARK: - Private Properties\n     \n     public internal(set) var duration: Double\n-    let action: FiniteTimeAction\n+    var action: FiniteTimeAction\n     var state = State.idle\n     \n     // MARK: - Private Methods\ndiff --git a/TweenKit/TweenKitTests/SequenceTests.swift b/TweenKit/TweenKitTests/SequenceTests.swift\nindex d32e047..deb27a7 100644\n--- a/TweenKit/TweenKitTests/SequenceTests.swift\n+++ b/TweenKit/TweenKitTests/SequenceTests.swift\n@@ -10,14 +10,7 @@ import XCTest\n @testable import TweenKit\n \n class SequenceTests: XCTestCase {\n-    \n-    enum ActionEvents: Equatable {\n-        case actionBecomeActive(FiniteTimeAction)\n-        case actionBegin(FiniteTimeAction)\n-        case actionFinish(FiniteTimeAction)\n-        case actionBecomeInactive(FiniteTimeAction)\n-    }\n-    \n+   \n     var scheduler: Scheduler!\n     \n     override func setUp() {\n@@ -145,19 +138,3 @@ class SequenceTests: XCTestCase {\n \n     \n }\n-\n-func ==(lhs: SequenceTests.ActionEvents, rhs: SequenceTests.ActionEvents) -> Bool {\n-    \n-    switch (lhs, rhs) {\n-    case let (.actionBecomeActive(leftAction), .actionBecomeActive(rightAction)):\n-        return leftAction === rightAction\n-    case let (.actionBegin(leftAction), .actionBegin(rightAction)):\n-        return leftAction === rightAction\n-    case let (.actionFinish(leftAction), .actionFinish(rightAction)):\n-        return leftAction === rightAction\n-    case let (.actionBecomeInactive(leftAction), .actionBecomeInactive(rightAction)):\n-        return leftAction === rightAction\n-    default:\n-        return false\n-    }\n-}\n', 'commit_subject': 'Actions now structs instead of classes', 'repo_name': 'SteveBarnegren/TweenKit', 'committer': {'name': 'Steve Barnegren', 'email': 'bc5139fd53148e14269e5cfe4dc04c6e15304d53@gmail.com', 'time_sec': '1490188349', 'tz_offset': '0', 'date': {'seconds': '1490188349'}}, 'commit_tree': 'ae1b6b75c7b0100f6fbfaab75cc70f5ccdcf4ed7', 'commit_message': 'Actions now structs instead of classes\n', 'language_name': 'Swift', 'license': 'mit', 'hunks': '@@ -40,7 +40,7 @@ public class YoyoAction: FiniteTimeAction {\n     // MARK: - Private Properties\n     \n     public internal(set) var duration: Double\n-    let action: FiniteTimeAction\n+    var action: FiniteTimeAction\n     var state = State.idle\n     \n     // MARK: - Private Methods\n', 'addition_count': 1, 'deletion_count': 1, 'src_file': 'a/TweenKit/TweenKit/YoyoAction.swift', 'tgt_file': 'b/TweenKit/TweenKit/YoyoAction.swift', 'file_extension': '.swift', 'before_file': "//\n//  YoyoAction.swift\n//  TweenKit\n//\n//  Created by Steve Barnegren on 19/03/2017.\n//  Copyright © 2017 Steve Barnegren. All rights reserved.\n//\n\nimport Foundation\n\n/** Animates inner action to end and then back to beginning */\npublic class YoyoAction: FiniteTimeAction {\n    \n    // MARK: - Types\n    \n    enum State {\n        case idle\n        case forwards\n        case backwards\n    }\n    \n    // MARK: - Public\n    \n    public var onBecomeActive: () -> () = {}\n    public var onBecomeInactive: () -> () = {}\n    \n    public var reverse = false {\n        didSet{\n            if reverse != oldValue, state != .idle {\n                action.reverse = !action.reverse\n            }\n        }\n    }\n\n    /**\n     Create with action to yoyo\n     - Parameter action: The action to yoyo\n     */\n    public init(action: FiniteTimeAction) {\n    // MARK: - Private Properties\n    \n    public internal(set) var duration: Double\n    let action: FiniteTimeAction\n    var state = State.idle\n    \n    // MARK: - Private Methods\n    public internal(set) var duration: Double\n    var action: FiniteTimeAction\n    var state = State.idle\n    \n    // MARK: - Private Methods\n    \n    public func willBecomeActive() {\n        onBecomeActive()\n        action.willBecomeActive()\n    }\n\n    public func didBecomeInactive() {\n        onBecomeInactive()\n        action.didBecomeInactive()\n    }\n    \n    public func willBegin() {\n        self.update(t: reverse ? 1.0 : 0.0)\n    }\n    \n    public func didFinish() {\n        \n        self.update(t: reverse ? 0.0 : 1.0)\n        action.didFinish()\n        state = .idle\n    }\n    \n    public func update(t: CFTimeInterval) {\n        \n        /*\n         The order of state changes and setReverse is important here. The inner action should receive the following calls:\n         \n         - will begin\n         - will finish\n         - reverse = true\n         - will begin\n         - will finish\n \n         The inner action is 'invoked twice' (two begin/finish calls), and it has the correct reverse state at the time of each call\n         There are unit tests that test the call order, please run them after making changes\n         */\n        \n        if t < 0.5 {\n            \n            if state == .idle {\n                action.reverse = reverse\n                action.willBegin()\n            }\n            \n            if state == .backwards {\n                action.didFinish()\n                action.reverse = reverse\n                action.willBegin()\n            }\n            \n            let actionT = t * 2\n            action.update(t: actionT)\n            \n            state = .forwards\n        }\n        else{\n            \n            if state == .idle {\n                action.reverse = !reverse\n                action.willBegin()\n            }\n            \n            if state == .forwards {\n                action.didFinish()\n                action.reverse = !reverse\n                action.willBegin()\n            }\n\n            let actionT = 1-((t - 0.5) * 2);\n            action.update(t: actionT)\n            \n            state = .backwards\n        }\n    }\n}\n\npublic extension FiniteTimeAction {\n    \n    func yoyo() -> YoyoAction {\n        return YoyoAction(action: self)\n    }\n}\n", 'message': 'Actions now structs instead of classes\n', 'author_name': 'Steve Barnegren', 'lang': 'swift'}