RiveView is a native view that renders Rive animations. It handles the render loop, touch interactions, and provides low-level control over playback.
For most use cases, you should use RiveViewModel which provides a higher-level interface. Use RiveView directly when you need fine-grained control over rendering and playback.
Initializers
Default Initializer
Minimalist constructor. Call setModel() to configure the RiveView later.
Example:
let riveView = RiveView()
Initialize with Model
public convenience init(model: RiveModel, autoPlay: Bool = true)
The RiveModel instance containing the Rive file data
Whether the animation or state machine should start playing automatically
Example:
let model = try RiveModel(fileName: "hero")
let riveView = RiveView(model: model, autoPlay: true)
Properties
isPlaying
internal private(set) var isPlaying: Bool
Returns true if the animation or state machine is currently playing. Read-only.
fit
internal var fit: RiveFit
How the Rive content should fit within the view bounds. Defaults to .contain.
alignment
internal var alignment: RiveAlignment
How the Rive content should align within the view bounds. Defaults to .center.
layoutScaleFactor
internal var layoutScaleFactor: Double
The scale factor to apply when using the layout fit. By default, this value is -1, where Rive will determine the correct scale for your device. To override this default behavior, set this value to a value greater than 0.
If the scale factor is less than or equal to 0, nothing will be drawn.
forwardsListenerEvents
internal var forwardsListenerEvents: Bool
Sets whether the Rive view should forward Rive listener touch/click events to any next responders. When true, touch/click events will be forwarded to any next responder(s). When false, only the Rive view will handle touch/click events. Defaults to false.
On iOS, this is handled separately from isExclusiveTouch.
offscreenBehavior
public var offscreenBehavior: OffscreenBehavior
Sets whether the view should continue drawing while offscreen. Options:
.playAndDraw - Continue playing and drawing when offscreen
.playAndNoDraw - Continue playing but don’t draw when offscreen
Defaults to .playAndNoDraw.
drawOptimization
public var drawOptimization: DrawOptimization
Sets whether the view should always draw, or skip drawing if the artboard is unchanged. Options:
.alwaysDraw - Draw on every frame
.drawOnChanged - Only draw when the artboard has changed
Defaults to .drawOnChanged.
playerDelegate
public weak var playerDelegate: RivePlayerDelegate?
Delegate that receives playback events (play, pause, stop, loop, advance).
stateMachineDelegate
public weak var stateMachineDelegate: RiveStateMachineDelegate?
Delegate that receives state machine events (input changes, state changes, touch events, Rive events).
showFPS
Shows or hides the FPS counter on this RiveView.
showFPSCounters
public static var showFPSCounters: Bool
Shows or hides the FPS counters on all RiveViews.
Methods
setModel
open func setModel(_ model: RiveModel, autoPlay: Bool = true) throws
This resets the view with the new model. Useful when the RiveView was initialized without one.
The RiveModel instance to set
Whether to start playing automatically
Example:
let model = try RiveModel(fileName: "hero")
try riveView.setModel(model, autoPlay: true)
setPreferredFramesPerSecond
open func setPreferredFramesPerSecond(preferredFramesPerSecond: Int)
Hints to underlying CADisplayLink the preferred FPS to run at.
Integer number of frames per second to set preferred FPS at
Example:
riveView.setPreferredFramesPerSecond(preferredFramesPerSecond: 60)
setPreferredFrameRateRange
@available(iOS 15, macOS 14, tvOS 15, visionOS 1, *)
open func setPreferredFrameRateRange(preferredFrameRateRange: CAFrameRateRange)
Hints to underlying CADisplayLink the preferred frame rate range.
Example:
if #available(iOS 15.0, *) {
let range = CAFrameRateRange(minimum: 60, maximum: 120, preferred: 120)
riveView.setPreferredFrameRateRange(preferredFrameRateRange: range)
}
play
Starts the render loop.
Example:
pause
Asks the render loop to stop on the next cycle.
Example:
stop
Asks the render loop to stop on the next cycle and resets the animation.
Example:
reset
Resets the animation to its initial state.
Example:
advance
open func advance(delta: Double)
Advances the Artboard and either a StateMachine or an Animation. Also fires any remaining events in the queue.
Elapsed seconds since the last advance
Example:
riveView.advance(delta: 0.016) // ~60fps
drawRive
open func drawRive(_ rect: CGRect, size: CGSize)
This is called in the middle of drawRect. Override this method to implement custom draw logic.
The size of the drawable area
Enums
OffscreenBehavior
public enum OffscreenBehavior {
case playAndDraw
case playAndNoDraw
}
Defines how the view behaves when offscreen.
DrawOptimization
public enum DrawOptimization {
case alwaysDraw
case drawOnChanged
}
Defines the drawing optimization strategy.
RiveTouchEvent
public enum RiveTouchEvent: Int {
case began
case moved
case ended
case cancelled
case exited
}
An enum of possible touch or mouse events when interacting with an animation.
Protocols
RiveStateMachineDelegate
public protocol RiveStateMachineDelegate: AnyObject {
@objc optional func touchBegan(onArtboard artboard: RiveArtboard?, atLocation location: CGPoint)
@objc optional func touchMoved(onArtboard artboard: RiveArtboard?, atLocation location: CGPoint)
@objc optional func touchEnded(onArtboard artboard: RiveArtboard?, atLocation location: CGPoint)
@objc optional func touchCancelled(onArtboard artboard: RiveArtboard?, atLocation location: CGPoint)
@objc optional func touchExited(onArtboard artboard: RiveArtboard?, atLocation location: CGPoint)
@objc optional func stateMachine(_ stateMachine: RiveStateMachineInstance, receivedInput input: StateMachineInput)
@objc optional func stateMachine(_ stateMachine: RiveStateMachineInstance, didChangeState stateName: String)
@objc optional func stateMachine(_ stateMachine: RiveStateMachineInstance, didReceiveHitResult hitResult: RiveHitResult, from event: RiveTouchEvent)
@objc optional func onRiveEventReceived(onRiveEvent riveEvent: RiveEvent)
}
Delegate protocol for receiving state machine events.
RivePlayerDelegate
public protocol RivePlayerDelegate: AnyObject {
func player(playedWithModel riveModel: RiveModel?)
func player(pausedWithModel riveModel: RiveModel?)
func player(loopedWithModel riveModel: RiveModel?, type: Int)
func player(stoppedWithModel riveModel: RiveModel?)
func player(didAdvanceby seconds: Double, riveModel: RiveModel?)
}
Delegate protocol for receiving player events.
Usage Examples
Basic Usage
import UIKit
import RiveRuntime
class ViewController: UIViewController {
let riveView = RiveView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(riveView)
riveView.frame = view.bounds
let model = try! RiveModel(fileName: "hero")
try! riveView.setModel(model, autoPlay: true)
}
}
With Delegates
import UIKit
import RiveRuntime
class ViewController: UIViewController, RivePlayerDelegate, RiveStateMachineDelegate {
let riveView = RiveView()
override func viewDidLoad() {
super.viewDidLoad()
riveView.playerDelegate = self
riveView.stateMachineDelegate = self
view.addSubview(riveView)
riveView.frame = view.bounds
let model = try! RiveModel(fileName: "hero")
try! riveView.setModel(model)
}
func player(playedWithModel riveModel: RiveModel?) {
print("Animation started")
}
func player(pausedWithModel riveModel: RiveModel?) {
print("Animation paused")
}
func player(loopedWithModel riveModel: RiveModel?, type: Int) {
print("Animation looped")
}
func player(stoppedWithModel riveModel: RiveModel?) {
print("Animation stopped")
}
func player(didAdvanceby seconds: Double, riveModel: RiveModel?) {
// Called on every frame
}
func stateMachine(_ stateMachine: RiveStateMachineInstance, didChangeState stateName: String) {
print("State changed to: \(stateName)")
}
func onRiveEventReceived(onRiveEvent riveEvent: RiveEvent) {
print("Rive event received: \(riveEvent.name())")
}
}
Custom Drawing Optimization
import UIKit
import RiveRuntime
class ViewController: UIViewController {
let riveView = RiveView()
override func viewDidLoad() {
super.viewDidLoad()
riveView.drawOptimization = .alwaysDraw
riveView.offscreenBehavior = .playAndNoDraw
view.addSubview(riveView)
riveView.frame = view.bounds
let model = try! RiveModel(fileName: "hero")
try! riveView.setModel(model)
}
}