diff --git a/Example-iOS/Source/Examples/SwiftUI/SwiftTouchEvents.swift b/Example-iOS/Source/Examples/SwiftUI/SwiftTouchEvents.swift index f8b6cd97..bb4e2ea4 100644 --- a/Example-iOS/Source/Examples/SwiftUI/SwiftTouchEvents.swift +++ b/Example-iOS/Source/Examples/SwiftUI/SwiftTouchEvents.swift @@ -37,7 +37,7 @@ struct SwiftTouchEvents: DismissableView { bearGuy.view() .aspectRatio(1, contentMode: .fit) - clock.controlsView() + clock.view() toggle.view() .aspectRatio(1, contentMode: .fit) diff --git a/Example-iOS/Source/Examples/SwiftUI/SwiftWidgets.swift b/Example-iOS/Source/Examples/SwiftUI/SwiftWidgets.swift index e82b6779..06054826 100644 --- a/Example-iOS/Source/Examples/SwiftUI/SwiftWidgets.swift +++ b/Example-iOS/Source/Examples/SwiftUI/SwiftWidgets.swift @@ -47,7 +47,7 @@ struct SwiftWidgets: DismissableView { VStack { Text("RiveProgressBar:") - rprogress.formattedView() + rprogress.view() Slider(value: Binding( get: { diff --git a/Example-iOS/Source/Examples/ViewModel/ClockViewModel.swift b/Example-iOS/Source/Examples/ViewModel/ClockViewModel.swift index 00f016ef..d1cdeafd 100644 --- a/Example-iOS/Source/Examples/ViewModel/ClockViewModel.swift +++ b/Example-iOS/Source/Examples/ViewModel/ClockViewModel.swift @@ -11,10 +11,13 @@ import RiveRuntime class ClockViewModel: RiveViewModel { private var timer: Timer! + private var hour: Int = 0 + private var minute: Int = 0 + private var second: Int = 0 - @Published var hours: Double = 0 { + @Published var time: Double = 0 { didSet { - try? setInput("isTime", value: hours > 12 ? hours-12 : hours) + setInput("isTime", value: time > 12 ? time-12 : time) } } @@ -25,11 +28,11 @@ class ClockViewModel: RiveViewModel { let date = Date() let calendar = Calendar.current - let hour = calendar.component(.hour, from: date) - let minute = calendar.component(.minute, from: date) - let second = calendar.component(.second, from: date) + self.hour = calendar.component(.hour, from: date) + self.minute = calendar.component(.minute, from: date) + self.second = calendar.component(.second, from: date) - self.hours = Double(hour) + Double(minute)/60 + Double(second)/1200 + self.time = Double(self.hour) + Double(self.minute)/60 + Double(self.second)/1200 } } else { timer?.invalidate() @@ -46,39 +49,42 @@ class ClockViewModel: RiveViewModel { timer?.invalidate() } - func controlsView() -> some View { - return ZStack { - Color.gray - - VStack { - view() - .aspectRatio(1, contentMode: .fit) + override func view() -> AnyView { + AnyView( + ZStack { + Color.gray - Button { - self.followTimer.toggle() - } label: { - ZStack { - Color.blue - Text(self.followTimer ? "Real Time" : "Manual") - .bold() + VStack { + super.view() + .aspectRatio(1, contentMode: .fit) + + Button { + self.followTimer.toggle() + } label: { + ZStack { + Color.blue + Text(self.followTimer ? "Real Time" : "Manual") + .bold() + } } - } - .foregroundColor(.white) - .frame(width: 200, height: 75, alignment: .center) - .cornerRadius(10) - .padding() - - Text("Hour: \(round(hours * 100) / 100)") .foregroundColor(.white) - .padding(.bottom) - - Slider(value: Binding( - get: { self.hours }, - set: { self.hours = round($0 * 100) / 100 } - ), in: 0...24, step: 0.01) - .padding() - .disabled(followTimer) + .frame(width: 200, height: 75, alignment: .center) + .cornerRadius(10) + .padding() + + let normalizedHour = hour%12 == 0 ? 12 : hour%12 + Text("Time: \(normalizedHour):\(minute):\(second)") + .foregroundColor(.white) + .padding(.bottom) + + Slider(value: Binding( + get: { self.time }, + set: { self.time = round($0 * 100) / 100 } + ), in: 0...24, step: 0.01) + .padding() + .disabled(followTimer) + } } - } + ) } } diff --git a/Example-iOS/Source/Examples/ViewModel/RiveButton.swift b/Example-iOS/Source/Examples/ViewModel/RiveButton.swift index c02bb029..17fa845f 100644 --- a/Example-iOS/Source/Examples/ViewModel/RiveButton.swift +++ b/Example-iOS/Source/Examples/ViewModel/RiveButton.swift @@ -25,7 +25,7 @@ class RiveButton: RiveViewModel { func touchBegan(onArtboard artboard: RiveArtboard?, atLocation location: CGPoint) { stop() - try? setInput(input, value: true) + setInput(input, value: true) } func touchEnded(onArtboard artboard: RiveArtboard?, atLocation location: CGPoint) { @@ -35,6 +35,6 @@ class RiveButton: RiveViewModel { } func touchCancelled(onArtboard artboard: RiveArtboard?, atLocation location: CGPoint) { - try? setInput(input, value: false) + setInput(input, value: false) } } diff --git a/Example-iOS/Source/Examples/ViewModel/RiveProgressBar.swift b/Example-iOS/Source/Examples/ViewModel/RiveProgressBar.swift index 6867fb73..9cf74567 100644 --- a/Example-iOS/Source/Examples/ViewModel/RiveProgressBar.swift +++ b/Example-iOS/Source/Examples/ViewModel/RiveProgressBar.swift @@ -12,7 +12,7 @@ import SwiftUI class RiveProgressBar: RiveViewModel { var progress: Double { didSet { - try? setInput("Energy", value: progress) + setInput("Energy", value: progress) } } @@ -21,8 +21,10 @@ class RiveProgressBar: RiveViewModel { super.init(fileName: "energy_bar_example", stateMachineName: "State Machine ", fit: .fitCover) } - func formattedView() -> some View { - super.view() - .aspectRatio(4, contentMode: .fill) + override func view() -> AnyView { + AnyView( + super.view() + .aspectRatio(4, contentMode: .fill) + ) } } diff --git a/Example-iOS/Source/Examples/ViewModel/RiveSlider.swift b/Example-iOS/Source/Examples/ViewModel/RiveSlider.swift index 1343fd6d..8298de59 100644 --- a/Example-iOS/Source/Examples/ViewModel/RiveSlider.swift +++ b/Example-iOS/Source/Examples/ViewModel/RiveSlider.swift @@ -12,7 +12,7 @@ import SwiftUI class RiveSlider: RiveViewModel { var progress: Double { didSet { - try? setInput("FillPercent", value: progress) + setInput("FillPercent", value: progress) } } diff --git a/Example-iOS/Source/ExamplesMaster.swift b/Example-iOS/Source/ExamplesMaster.swift index ec371a80..ec386829 100644 --- a/Example-iOS/Source/ExamplesMaster.swift +++ b/Example-iOS/Source/ExamplesMaster.swift @@ -84,7 +84,7 @@ extension ExamplesMasterTableViewController { // Views made by the ViewModels else if indexPath.section == 2 { - let anyView = AnyView(viewModels[indexPath.row].1.view()) + let anyView = viewModels[indexPath.row].1.view() controller = UIHostingController(rootView: anyView) } diff --git a/Source/Components/RiveViewModel.swift b/Source/Components/RiveViewModel.swift index 45f7ea85..5d0fde52 100644 --- a/Source/Components/RiveViewModel.swift +++ b/Source/Components/RiveViewModel.swift @@ -231,30 +231,44 @@ open class RiveViewModel: NSObject, ObservableObject, RiveFileDelegate, RiveStat ) } - open func triggerInput(_ inputName: String) throws { + + /// Provide the active StateMachine a `Trigger` input + /// - Parameter inputName: The name of a `Trigger` input on the active StateMachine + open func triggerInput(_ inputName: String) { riveModel?.stateMachine?.getTrigger(inputName).fire() play() } - open func setInput(_ inputName: String, value: Bool) throws { + /// Provide the active StateMachine a `Boolean` input + /// - Parameters: + /// - inputName: The name of a `Boolean` input on the active StateMachine + /// - value: A Bool value for the input + open func setInput(_ inputName: String, value: Bool) { riveModel?.stateMachine?.getBool(inputName).setValue(value) play() } - open func setInput(_ inputName: String, value: Float) throws { + /// Provide the active StateMachine a `Number` input + /// - Parameters: + /// - inputName: The name of a `Number` input on the active StateMachine + /// - value: A Float value for the input + open func setInput(_ inputName: String, value: Float) { riveModel?.stateMachine?.getNumber(inputName).setValue(value) play() } - open func setInput(_ inputName: String, value: Double) throws { - riveModel?.stateMachine?.getNumber(inputName).setValue(Float(value)) - play() + /// Provide the active StateMachine a `Number` input + /// - Parameters: + /// - inputName: The name of a `Number` input on the active StateMachine + /// - value: A Double value for the input + open func setInput(_ inputName: String, value: Double) { + setInput(inputName, value: Float(value)) } // MARK: - SwiftUI Helpers /// Makes a new `RiveView` for the instance property with data from model which will - /// replace any previous `RiveView`. This is called when first drawing a `StandardView`. + /// replace any previous `RiveView`. This is called when first drawing a `RiveViewRepresentable`. /// - Returns: Reference to the new view that the `RiveViewModel` will be maintaining open func createRiveView() -> RiveView { let view: RiveView @@ -271,7 +285,7 @@ open class RiveViewModel: NSObject, ObservableObject, RiveFileDelegate, RiveStat } /// Gives updated layout values to the provided `RiveView`. This is called in - /// the process of re-displaying `StandardView`. + /// the process of re-displaying `RiveViewRepresentable`. /// - Parameter rview: the `RiveView` that will be updated @objc open func update(view: RiveView) { view.fit = fit @@ -279,7 +293,7 @@ open class RiveViewModel: NSObject, ObservableObject, RiveFileDelegate, RiveStat } /// Assigns the provided `RiveView` to its rview property. This is called when creating a - /// `StandardView` + /// `RiveViewRepresentable` /// /// - Parameter view: the `Rview` that this `RiveViewModel` will maintain fileprivate func registerView(_ view: RiveView) { @@ -294,21 +308,8 @@ open class RiveViewModel: NSObject, ObservableObject, RiveFileDelegate, RiveStat } /// This can be added to the body of a SwiftUI `View` - open func view() -> some View { - return StandardView(viewModel: self) - } - - /// A simple View designed to display - public struct StandardView: View { - let viewModel: RiveViewModel - - init(viewModel: RiveViewModel) { - self.viewModel = viewModel - } - - public var body: some View { - RiveViewRepresentable(viewModel: viewModel) - } + open func view() -> AnyView { + return AnyView(RiveViewRepresentable(viewModel: self)) } // MARK: - UIKit Helper