---
title: "Adding Event Emitters to Your TurboModule in Swift"
description: "Learn how to emit native events from a Swift TurboModule and subscribe to them in JavaScript, including proper memory management and Codegen integration."
url: https://www.callstack.com/tutorials/adding-event-emitters-to-your-turbomodule-in-swift
updated: 2026-10-24T08:39:46.184Z
---

# Adding Event Emitters to Your TurboModule in Swift

Learn how to emit native events from a Swift TurboModule and subscribe to them in JavaScript, including proper memory management and Codegen integration.

_Video tutorial · 2025-12-30 · Length: 11:04 · Category: React Native_

Teachers: Oskar Kwaśniewski (Software Developer @ Callstack)

[Watch on YouTube](https://www.youtube.com/watch?v=cG7Uj2fyt70)

TurboModules don’t just expose functions, they can also push information from native to JavaScript. In this episode, Oskar shows how to extend the Local Storage TurboModule from Episode 1 with an event emitter that notifies JS whenever a new key is added. You’ll see how event types flow from TypeScript through Codegen into Objective‑C and Swift, and how to wire everything so JavaScript can subscribe safely and respond in real time.

## Adding event types to the TypeScript spec

Oskar introduces the idea of emitting events when native state changes, such as when a new key is added in Local Storage. He adds an event payload type (`key`, `value`) and a new Codegen event field. After rerunning Codegen, new interfaces become available on the native side.

## Understanding the newly generated native interfaces

Codegen now outputs a `NativeLocalStorageSpecBase` interface containing the auto‑generated `emitOnKeyAdded` method. Oskar shows how this sits alongside the existing TurboModule protocol and explains why the module must now inherit from this new base.

## Implementing event emission in Swift

The Swift class gains a stored callback (`onKeyAdded`) and a custom initializer that accepts this closure. Oskar walks through marking the closure `@escaping`, storing it, and triggering it inside `setItem` only when a new key is created.

## Wiring the Objective‑C Layer

Because the Swift initializer changed, the Objective‑C class must now call `initOnKeyAdded:` and forward the emitted dictionary back to JS via the generated `emitOnKeyAdded`. Oskar fills in the placeholders and validates that compilation succeeds.

## Avoiding retain cycles

Oskar highlights a subtle memory bug caused by the Swift closure capturing `self` strongly, while Objective‑C also retains the Swift instance, forming a retain cycle. He fixes it by using a weak reference, breaking the circular ownership.

## Subscribing to events in JavaScript

On the JS side, a `useEffect` subscription listens for `onKeyAdded` events and shows an alert when they occur. A new button writes a random key to trigger the event, and Oskar verifies the flow step‑by‑step in the Xcode debugger.

## Resources

- Oskar Kwaśniewski on [X](https://x.com/o_kwasniewski/) and [GitHub](https://github.com/okwasniewski)
- [Other episodes in this series](https://www.youtube.com/playlist?list=PLZ3MwD-soTTE9yIH2ziaxBO6ytManw5Qc)
- Tools & libraries:
  - [TurboModules](https://reactnative.dev/docs/turbo-native-modules-introduction) (New Architecture)
  - [Codegen](https://codegen.com/)
  - Swift + Objective‑C integration
  - [Expo](https://expo.dev/) (testing)

**TurboModules feel powerful but risky?** We help teams use them with confidence in real production apps. [Let’s chat](/contact)
