review-case
Structured code review for a case in the APIExample-SwiftUI project. Checks engine lifecycle, SwiftUI state ownership, thread safety, permissions, and API correctness.
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
review-case — APIExample-SwiftUI
Review Dimensions (in priority order)
1. Engine Lifecycle
Check:
-
AgoraRtcEngineKitcreated insidesetupRTC()of the RTC class, not in the Entry view -
leaveChannel()+AgoraRtcEngineKit.destroy()called insideonDestroy() -
setupRTC()called from.onAppear,onDestroy()called from.onDisappear - No engine instance retained beyond the RTC object's lifetime
Correct:
.onAppear { rtc.setupRTC(configs: configs) }
.onDisappear { rtc.onDestroy() }
Wrong:
// Missing onDisappear — engine never destroyed
.onAppear { rtc.setupRTC(configs: configs) }
2. SwiftUI State Ownership
Check:
- Main view declares RTC object as
@ObservedObject, not@StateObject - Entry view does not hold a reference to the RTC object
-
@Publishedproperties used for state that drives UI updates
Correct:
struct MyCase: View {
@ObservedObject private var rtc = MyCaseRTC() // correct
}
Wrong:
struct MyCase: View {
@StateObject private var rtc = MyCaseRTC() // wrong — SwiftUI owns lifetime, may outlive view
}
3. Thread Safety
All AgoraRtcEngineDelegate callbacks may arrive on a background thread.
Check:
- Every
@Publishedproperty mutation inside a delegate callback is dispatched toDispatchQueue.main - No direct SwiftUI state mutation on background thread
Correct:
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
DispatchQueue.main.async {
self.remoteUid = uid
}
}
4. Permissions
Check:
- Camera/microphone permissions requested before
joinChannel() -
joinChannel()called only inside the permission grant callback
5. Error Handling
Check:
- Return value of
joinChannel()checked -
rtcEngine(_:didOccurError:)implemented and logged - Token expiry handled if token is used
6. Code Conventions
Check:
- RTC class inherits
NSObject, conforms toObservableObjectandAgoraRtcEngineDelegate - Entry view named
<ExampleName>Entry, main view named<ExampleName> - RTC class named
<ExampleName>RTC -
configsdictionary used to pass data from Entry to Main - No SDK calls inside SwiftUI
bodycomputed property
7. Resource Cleanup
Check:
- Audio files / custom audio tracks stopped in
onDestroy() - External video sources unregistered in
onDestroy() - Media player destroyed if created
- Screen capture stopped if started
- Multi-camera capture stopped if started
Review Output Format
[SEVERITY] file/line — issue description
Suggestion: how to fix
Severity levels:
-
[CRITICAL]— crash, leak, or incorrect behavior -
[WARNING]— convention violation or subtle bug risk -
[INFO]— style or minor improvement
SwiftUI-Specific Checks
-
onAppearcan fire multiple times (e.g., sheet dismiss, navigation pop/push) — verifysetupRTCis idempotent or guarded -
onDisappearfires when the view is covered by another view in aTabView— verify this does not prematurely destroy the engine - Video rendering views (
VideoView/VideoUIView) must be created beforesetupRTCis called so the canvas can be set up correctly -
[weak self]required in all closures capturingselfinside the RTC class to avoid retain cycles
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-03-11
- Index updated
- 2026-03-11
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!