Skip to content

Commit 780479f

Browse files
mfazekasclaude
andcommitted
fix: improve error handling and fix import cycle
- Fix import cycle by extracting NitroRiveView to separate file - Make error types human-readable in logs (show enum names instead of numbers) - Improve iOS error detection using RiveErrorCode enum values instead of string comparisons - Rename NativeRiveError to NitroRiveError for consistency with Nitro Modules naming - Make detectErrorType return tuple with both error type and message - Add NitroRiveError.fileNotFound case for asset loading errors - Remove non-existent error types (TextRunNotFoundError, IncorrectAnimationName) - Map instanceNotFound errors to DataBindingError type 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 84ac9b5 commit 780479f

7 files changed

Lines changed: 54 additions & 56 deletions

File tree

ios/HybridRiveView.swift

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,9 @@ extension HybridRiveView {
194194
do {
195195
return try fn()
196196
} catch (let e) {
197-
let errorType = detectErrorType(e)
198-
let errorMessage = "[RIVE] \(tag) \(note ?? "") \(e)"
197+
let (errorType, errorDescription) = detectErrorType(e)
198+
let noteString = note.map { " \($0)" } ?? ""
199+
let errorMessage = "[RIVE] \(tag)\(noteString) \(errorDescription)"
199200

200201
let riveError = RiveError(
201202
message: errorMessage,
@@ -205,35 +206,33 @@ extension HybridRiveView {
205206
}
206207
}
207208

208-
private func detectErrorType(_ error: Error) -> RiveErrorType {
209-
if case NativeRiveError.instanceNotFound = error {
210-
return .databindingerror
209+
private func detectErrorType(_ error: Error) -> (RiveErrorType, String) {
210+
switch error {
211+
case NitroRiveError.instanceNotFound(let message):
212+
return (.databindingerror, message)
213+
case NitroRiveError.fileNotFound(let message):
214+
return (.filenotfound, message)
215+
default:
216+
break
211217
}
212218

213219
let nsError = error as NSError
214-
guard let errorName = nsError.userInfo["name"] as? String else {
215-
return .unknown
216-
}
217-
218-
switch errorName {
219-
case "NoArtboardFound":
220-
return .incorrectartboardname
221-
case "NoStateMachineFound":
222-
return .incorrectstatemachinename
223-
case "NoAnimationFound":
224-
return .incorrectanimationname
225-
case "Malformed":
226-
return .malformedfile
227-
case "FileNotFound":
228-
return .filenotfound
229-
case "NoStateMachineInputFound":
230-
return .incorrectanimationname
231-
case "TextRunNotFoundError":
232-
return .textrunnotfounderror
233-
case "DataBindingError":
234-
return .databindingerror
220+
let message = nsError.localizedDescription
221+
222+
// RiveErrorCode from RiveRuntime
223+
switch nsError.code {
224+
case RiveErrorCode.noArtboardFound.rawValue:
225+
return (.incorrectartboardname, message)
226+
case RiveErrorCode.noStateMachineFound.rawValue:
227+
return (.incorrectstatemachinename, message)
228+
case RiveErrorCode.noAnimationFound.rawValue:
229+
return (.incorrectanimationname, message)
230+
case RiveErrorCode.malformedFile.rawValue:
231+
return (.malformedfile, message)
232+
case RiveErrorCode.noStateMachineInputFound.rawValue:
233+
return (.incorrectanimationname, message)
235234
default:
236-
return .unknown
235+
return (.unknown, message)
237236
}
238237
}
239238
}

ios/ReferencedAssetLoader.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,14 @@ func createIncorrectRiveURL(_ url: String) -> NSError {
2323
])
2424
}
2525

26-
func createAssetFileError(_ assetName: String) -> NSError {
27-
return NSError(
28-
domain: RiveErrorDomain, code: 801,
29-
userInfo: [
30-
NSLocalizedDescriptionKey: "Could not load Rive asset: \(assetName)", "name": "FileNotFound",
31-
])
26+
func createAssetFileError(_ assetName: String) -> NitroRiveError {
27+
return NitroRiveError.fileNotFound(message: "Could not load Rive asset: \(assetName)")
3228
}
3329

3430
final class ReferencedAssetLoader {
35-
private func handleRiveError(error: NSError) {
31+
private func handleRiveError(error: Error) {
3632
// TODO allow user to specify onError callback
37-
RCTLogError(error.localizedDescription)
33+
RCTLogError("\(error)")
3834
}
3935

4036
private func handleInvalidUrlError(url: String) {

ios/RiveReactNativeView.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ struct ViewConfiguration {
2626
let bindData: BindData
2727
}
2828

29-
enum NativeRiveError: Error {
29+
enum NitroRiveError: Error {
3030
case instanceNotFound(message: String)
31+
case fileNotFound(message: String)
3132
}
3233

3334
class RiveReactNativeView: UIView, RiveStateMachineDelegate {
@@ -110,7 +111,7 @@ class RiveReactNativeView: UIView, RiveStateMachineDelegate {
110111
let viewModel = riveFile.defaultViewModel(for: artboard),
111112
let instance = viewModel.createInstance(fromName: name)
112113
else {
113-
throw NativeRiveError.instanceNotFound(message: "\(name) instance not found")
114+
throw NitroRiveError.instanceNotFound(message: "\(name) instance not found")
114115
}
115116
stateMachine?.bind(viewModelInstance: instance)
116117
// this should be added if we support only playing artboards on their own - https://github.com/rive-app/rive-nitro-react-native/pull/23#discussion_r2534698281

src/core/Errors.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ export enum RiveErrorType {
44
MalformedFile = 2,
55
IncorrectArtboardName = 3,
66
IncorrectStateMachineName = 4,
7-
IncorrectAnimationName = 5,
87
DataBindingError = 6,
9-
TextRunNotFoundError = 7,
108
}
119

1210
export interface RiveError {

src/core/NitroRiveViewComponent.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {
2+
getHostComponent,
3+
type ReactNativeView,
4+
} from 'react-native-nitro-modules';
5+
import type {
6+
RiveViewMethods,
7+
RiveViewTSMethods,
8+
RiveViewProps as NativeRiveViewProps,
9+
} from '../specs/RiveView.nitro';
10+
import RiveViewConfig from '../../nitrogen/generated/shared/json/RiveViewConfig.json';
11+
12+
export const NitroRiveView = getHostComponent<
13+
NativeRiveViewProps,
14+
RiveViewMethods
15+
>('RiveView', () => RiveViewConfig) as ReactNativeView<
16+
NativeRiveViewProps,
17+
RiveViewTSMethods
18+
>;

src/core/RiveView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ComponentProps } from 'react';
2-
import { NitroRiveView } from '../index';
2+
import { NitroRiveView } from './NitroRiveViewComponent';
33
import { RiveErrorType, type RiveError } from './Errors';
44

55
export interface RiveViewProps

src/index.tsx

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
import {
2-
getHostComponent,
3-
NitroModules,
4-
type ReactNativeView,
5-
type HybridView,
6-
} from 'react-native-nitro-modules';
7-
import type { Rive } from './specs/Rive.nitro';
1+
import { type HybridView } from 'react-native-nitro-modules';
82
import {
93
type RiveViewMethods,
104
type RiveViewTSMethods,
@@ -20,15 +14,7 @@ export class DataBindByName implements DataBindByNameInterface {
2014
}
2115
}
2216

23-
import RiveViewConfig from '../nitrogen/generated/shared/json/RiveViewConfig.json';
24-
25-
export const NitroRiveView = getHostComponent<
26-
NativeRiveViewProps,
27-
RiveViewMethods
28-
>('RiveView', () => RiveViewConfig) as ReactNativeView<
29-
NativeRiveViewProps,
30-
RiveViewTSMethods
31-
>;
17+
export { NitroRiveView } from './core/NitroRiveViewComponent';
3218

3319
export { RiveView, type RiveViewProps } from './core/RiveView';
3420
export type { RiveViewMethods };

0 commit comments

Comments
 (0)