Documentation Index
Fetch the complete documentation index at: https://mintlify.com/rive-app/rive-ios/llms.txt
Use this file to discover all available pages before exploring further.
The Rive iOS Runtime supports custom fonts and provides a powerful fallback font system to handle missing characters gracefully. This ensures your text renders correctly even when the embedded Rive font doesn’t contain all necessary glyphs.
Overview
Rive files can embed fonts, but these fonts might not contain all characters your application needs. The fallback font system allows you to specify system fonts or custom fonts to use when characters are missing from the embedded font.
Fallback Font Providers
The iOS Runtime provides two ways to specify fallback fonts:
RiveFallbackFontDescriptor
Descriptors generate system fonts with specific attributes:
import RiveRuntime
public class RiveFallbackFontDescriptor {
init(
design: UIFontDescriptor.SystemDesign = .default,
weight: UIFont.Weight = .regular,
width: UIFont.Width = .standard
)
}
UIFont Directly
You can also use any UIFont instance as a fallback font provider.
Setting Global Fallback Fonts
Set fallback fonts that will be used for all Rive text:
import RiveRuntime
// Set global fallback fonts
RiveFont.fallbackFonts = [
// System font descriptor
RiveFallbackFontDescriptor(
design: .default,
weight: .regular,
width: .standard
),
// Explicit system font
UIFont.systemFont(ofSize: 12, weight: .heavy),
// Custom font by name
UIFont(name: "Times New Roman", size: 12)!
]
Fallback fonts are tried in order until a font with the required glyph is found.
Style-Specific Fallback Fonts
For more control, set a callback that returns different fonts based on text style:
import RiveRuntime
RiveFont.fallbackFontsCallback = { (style: RiveFontStyle) -> [RiveFallbackFontProvider] in
switch style.weight {
case .ultraLight:
return [
RiveFallbackFontDescriptor(weight: .ultraLight),
UIFont.systemFont(ofSize: 20, weight: .ultraLight)
]
case .regular:
return [
RiveFallbackFontDescriptor(),
UIFont.systemFont(ofSize: 20, weight: .regular)
]
case .bold:
return [
RiveFallbackFontDescriptor(weight: .bold),
UIFont.systemFont(ofSize: 20, weight: .bold)
]
case .black:
return [
RiveFallbackFontDescriptor(weight: .black),
UIFont.systemFont(ofSize: 20, weight: .black)
]
default:
return [RiveFallbackFontDescriptor()]
}
}
Note: If fallbackFontsCallback is set, fallbackFonts is ignored.
Complete SwiftUI Example
import SwiftUI
import RiveRuntime
struct FallbackFontsView: View {
@StateObject private var viewModel = RiveViewModel(
fileName: "fallback_fonts",
fit: .fill
)
private var runBinding: Binding<String> {
Binding {
return self.viewModel.getTextRunValue("ultralight") ?? ""
} set: { text in
try? self.viewModel.setTextRunValue("ultralight", textValue: text)
try? self.viewModel.setTextRunValue("regular", textValue: text)
try? self.viewModel.setTextRunValue("bold", textValue: text)
try? self.viewModel.setTextRunValue("black", textValue: text)
self.viewModel.play()
}
}
var body: some View {
VStack {
viewModel.view().scaledToFit()
Text(
"The included Rive font only contains characters in the set A...G. " +
"Fallback font(s) will be used to draw missing characters with the correct weight."
)
.fixedSize(horizontal: false, vertical: true)
.font(.caption)
.padding()
TextField("Add text with missing characters", text: runBinding)
.textFieldStyle(.roundedBorder)
.padding()
Spacer()
}
.onAppear {
setupFallbackFonts()
}
}
private func setupFallbackFonts() {
// Option 1: Set fallback fonts for all styles
RiveFont.fallbackFonts = [
RiveFallbackFontDescriptor(
design: .default,
weight: .regular,
width: .standard
),
UIFont.systemFont(ofSize: 12, weight: .heavy),
UIFont(name: "Times New Roman", size: 12)!
]
// Option 2: Or use a callback for style-specific fonts
RiveFont.fallbackFontsCallback = { (style: RiveFontStyle) -> [RiveFallbackFontProvider] in
switch style.weight {
case .ultraLight:
return [
RiveFallbackFontDescriptor(weight: .ultraLight),
UIFont.systemFont(ofSize: 20, weight: .ultraLight)
]
case .regular:
return [
RiveFallbackFontDescriptor(),
UIFont.systemFont(ofSize: 20, weight: .regular)
]
case .bold:
return [
RiveFallbackFontDescriptor(weight: .bold),
UIFont.systemFont(ofSize: 20, weight: .bold)
]
case .black:
return [
RiveFallbackFontDescriptor(weight: .black),
UIFont.systemFont(ofSize: 20, weight: .black)
]
default:
return [RiveFallbackFontDescriptor()]
}
}
}
}
UIKit Example
import UIKit
import RiveRuntime
class FontViewController: UIViewController {
@IBOutlet weak var riveView: RiveView!
override func viewDidLoad() {
super.viewDidLoad()
// Configure fallback fonts
RiveFont.fallbackFonts = [
RiveFallbackFontDescriptor(weight: .regular),
UIFont.systemFont(ofSize: 14, weight: .regular)
]
let viewModel = RiveViewModel(fileName: "text_with_fonts")
viewModel.setView(riveView)
}
}
Font Weight Matching
The RiveFontStyle provides weight information to match fonts:
RiveFont.fallbackFontsCallback = { (style: RiveFontStyle) -> [RiveFallbackFontProvider] in
let weight: UIFont.Weight
switch style.weight {
case .ultraLight: weight = .ultraLight
case .light: weight = .light
case .regular: weight = .regular
case .medium: weight = .medium
case .bold: weight = .bold
case .black: weight = .black
default: weight = .regular
}
return [
RiveFallbackFontDescriptor(weight: weight),
UIFont.systemFont(ofSize: 16, weight: weight)
]
}
System Font Design
Use different system font designs:
// Default system font
RiveFallbackFontDescriptor(design: .default)
// Monospaced design
RiveFallbackFontDescriptor(design: .monospaced)
// Rounded design
RiveFallbackFontDescriptor(design: .rounded)
// Serif design
if #available(iOS 13.0, *) {
RiveFallbackFontDescriptor(design: .serif)
}
Font Width Options
// Standard width (default)
RiveFallbackFontDescriptor(width: .standard)
// Condensed
RiveFallbackFontDescriptor(width: .condensed)
// Compressed
RiveFallbackFontDescriptor(width: .compressed)
// Expanded
RiveFallbackFontDescriptor(width: .expanded)
Using Custom Font Files
To use custom font files in your app:
- Add the font file to your Xcode project
- Include it in your app’s Info.plist under “Fonts provided by application”
- Reference it by name:
if let customFont = UIFont(name: "YourCustomFont-Regular", size: 16) {
RiveFont.fallbackFonts = [customFont]
}
RiveFallbackFontProvider Protocol
Both RiveFallbackFontDescriptor and UIFont conform to RiveFallbackFontProvider:
public protocol RiveFallbackFontProvider {
var fallbackFont: RiveNativeFont { get }
var allowsSuggestedFonts: Bool { get }
}
You can implement this protocol for custom fallback font logic.
Best Practices
- Set Fallbacks Early: Configure fallback fonts in your app delegate or before loading Rive files
- Test Missing Characters: Test with text that contains characters not in your embedded font
- Weight Matching: Match fallback font weights to Rive text styles for consistent appearance
- Fallback Order: List fonts in order of preference; the first font with the glyph will be used
- Global vs. Callback: Use global
fallbackFonts for simplicity, callbacks for fine-grained control
- Font Availability: Check font availability before using custom fonts by name
Common Use Cases
Multilingual Support
// Support multiple languages
RiveFont.fallbackFonts = [
UIFont.systemFont(ofSize: 14), // Default system font with wide character support
UIFont(name: "NotoSansCJK-Regular", size: 14)! // CJK characters
]
Emoji Support
// Ensure emoji rendering
RiveFont.fallbackFonts = [
UIFont.systemFont(ofSize: 14), // System font includes emoji
RiveFallbackFontDescriptor()
]
Special Characters
// Support mathematical or special symbols
RiveFont.fallbackFonts = [
UIFont(name: "Menlo", size: 14)!, // Monospace with good symbol support
UIFont.systemFont(ofSize: 14)
]
Troubleshooting
Missing Characters Still Not Rendering
- Verify fallback fonts are set before creating
RiveView
- Check that fallback fonts contain the required glyphs
- Ensure custom fonts are properly added to your project
Font Weight Not Matching
- Use the
fallbackFontsCallback to match weights precisely
- Test different font weights to find the best match
- Limit the number of fallback fonts in the array
- Use font descriptors instead of loading many font instances
See Also