0Pricing
React Native Academy · Ders

Swift ile Eski Bir Yerel Modül Yazma

Bir Objective-C köprü dosyası ve RCTBridgeModule'a uyan bir Swift sınıfı oluşturun, RCT_EXPORT_METHOD ile bir yöntemi dışa açın ve bunu React Native JS'den çağırın.

Swift ile Eski Bir Yerel Modül Yazma, CoddyKit'te ücretsiz bir React Native Academy dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, React Native Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. React Native Academy kursu toplamda 4 dersten oluşur.

Bu dersin bazı bölümleri henüz çevrilmemiş olup İngilizce olarak gösterilmektedir.

iOS Native Modules Overview

On iOS, legacy native modules expose Swift or Objective-C code to JavaScript through an Objective-C bridge. Even when you write the implementation in Swift, React Native requires an Objective-C bridge header file to register the module because the RN bridge is built in Objective-C. You write a thin .m bridge file alongside your Swift class.

Creating the Swift Module Class

Create a Swift class that conforms to NSObject and is decorated with the @objc attribute so Objective-C can see it. The class implements the RCTBridgeModule protocol. Swift modules also need @objcMembers on the class so all methods are visible to the bridge without individual @objc annotations on each one.

// CalendarModule.swift
import Foundation

@objc(CalendarModule)
class CalendarModule: NSObject {

  @objc
  func createCalendarEvent(
    _ name: String,
    location: String
  ) {
    print('Creating event: \(name) at \(location)')
  }
}

The Objective-C Bridge File

The bridge file is a plain .m file that does no implementation — it only declares your module and its methods using macros. RCT_EXTERN_MODULE registers the class name, and RCT_EXTERN_METHOD declares each exported method with its parameter labels exactly matching the Swift signatures.

// CalendarModuleBridge.m
#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_MODULE(CalendarModule, NSObject)

RCT_EXTERN_METHOD(
  createCalendarEvent:(NSString *)name
  location:(NSString *)location
)

@end

Exposing the Module Name

React Native identifies your module by the name in RCT_EXTERN_MODULE. On the JavaScript side, this becomes the key on NativeModules. By convention the name matches the Swift class name. If you want a different JavaScript-facing name, you can provide an alias as the second argument to RCT_EXTERN_MODULE, but keeping them the same avoids confusion.

// JavaScript — accessing the iOS module
import { NativeModules } from 'react-native';

const { CalendarModule } = NativeModules;

if (!CalendarModule) {
  console.warn('CalendarModule not found — iOS only?');
} else {
  CalendarModule.createCalendarEvent('Team Lunch', 'Conference Room A');
}

Returning Data with Promises in Swift

Swift native methods that return data use RCTPromiseResolveBlock and RCTPromiseRejectBlock parameters. These are passed in as the last two arguments when declared in the bridge file. Call resolve(value) on success or reject(code, message, error) on failure. On the JS side, await the call as you would any async function.

// Swift method
@objc
func getDeviceModel(
  _ resolve: @escaping RCTPromiseResolveBlock,
  rejecter reject: @escaping RCTPromiseRejectBlock
) {
  let model = UIDevice.current.model
  resolve(model)
}

// Bridge file
RCT_EXTERN_METHOD(
  getDeviceModel:(RCTPromiseResolveBlock)resolve
  rejecter:(RCTPromiseRejectBlock)reject
)

// JavaScript
const model = await CalendarModule.getDeviceModel();

Running on the Main Thread

Native module methods run on a background serial queue by default. If your method touches UIKit (which requires the main thread), you must dispatch to the main queue. You can override the static method requiresMainQueueSetup() to return true if the module needs to be initialized on the main thread from the start.

@objc
static func requiresMainQueueSetup() -> Bool {
  return true // init on main thread
}

@objc
func openAlert(_ message: String) {
  DispatchQueue.main.async {
    let alert = UIAlertController(
      title: 'Alert',
      message: message,
      preferredStyle: .alert
    )
    alert.addAction(UIAlertAction(title: 'OK', style: .default))
    UIApplication.shared.keyWindow?.rootViewController?
      .present(alert, animated: true)
  }
}

Exporting Constants to JavaScript

Like Android, iOS native modules can expose constants via the constantsToExport() method. Return a dictionary of values that React Native serializes and attaches to the module object in JavaScript at startup. Constants are synchronous and zero-cost to read after initialization.

// Swift
@objc
func constantsToExport() -> [String: Any]! {
  return [
    'PLATFORM': 'ios',
    'OS_VERSION': UIDevice.current.systemVersion,
    'IS_PAD': UIDevice.current.userInterfaceIdiom == .pad
  ]
}

// Bridge file (add inside the interface)
RCT_EXPORT_MODULE()

// JavaScript
const { PLATFORM, IS_PAD } = NativeModules.CalendarModule;
console.log(PLATFORM, IS_PAD);

Sending Events to JavaScript

To push data from native to JavaScript proactively, your Swift module should extend RCTEventEmitter instead of NSObject. Override supportedEvents() to list event names, and call sendEvent(withName:body:) to emit. On the JS side, use NativeEventEmitter to subscribe to the events.

// Swift
@objc(LocationModule)
class LocationModule: RCTEventEmitter {
  override func supportedEvents() -> [String]! {
    return ['onLocationUpdate']
  }

  func startTracking() {
    sendEvent(withName: 'onLocationUpdate',
              body: ['lat': 37.7749, 'lng': -122.4194])
  }
}

// JavaScript
import { NativeModules, NativeEventEmitter } from 'react-native';
const emitter = new NativeEventEmitter(NativeModules.LocationModule);
const sub = emitter.addListener('onLocationUpdate', (loc) => {
  console.log(loc.lat, loc.lng);
});
// cleanup: sub.remove();

Cross-Platform Module Wrapper

When your module only exists on one platform, guard calls with Platform.OS in your wrapper file to avoid runtime crashes on the other platform. A common pattern is to export a no-op stub on unsupported platforms so calling code never needs to check Platform.OS itself.

// CalendarModule.js
import { NativeModules, Platform } from 'react-native';

const { CalendarModule: NativeCalendar } = NativeModules;

export const CalendarModule = {
  createEvent: (name, location) => {
    if (Platform.OS === 'ios' && NativeCalendar) {
      NativeCalendar.createCalendarEvent(name, location);
    } else {
      console.warn('CalendarModule not available on', Platform.OS);
    }
  }
};

Handling Bridging Header for Mixed Projects

When you add Swift files to an Objective-C project (the default for older React Native), Xcode asks to create a bridging header. This file imports the Objective-C headers that Swift needs to see. You typically import React/RCTBridgeModule.h, React/RCTEventEmitter.h, and any other RN headers your Swift code references. Without this file, Swift cannot see the RCT types.

// YourApp-Bridging-Header.h
// Auto-created by Xcode when adding first Swift file

#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>

Testing the Native Module End-to-End

After writing your Swift class and bridge file, rebuild the app from Xcode (not just Metro) because native code changes require a full native build. Open the iOS Simulator, trigger the JS code that calls your module, and use console.log or Xcode's console to verify the native side executes. Xcode's debugger can set breakpoints in Swift code while the React Native app runs.

// Quick integration test in a component
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
import { CalendarModule } from './CalendarModule';

export function TestScreen() {
  useEffect(() => {
    CalendarModule.createEvent('Standup', 'Zoom')
      .then((result) => console.log('Event created:', result))
      .catch((err) => console.error('Error:', err));
  }, []);

  return <View><Text>Native Module Test</Text></View>;
}

Quick Check

Test your understanding of React Native Mobile Development concepts from this lesson.

Lesson Recap

In this lesson you learned: how to create a Swift class conforming to RCTBridgeModule, write an Objective-C bridge file with RCT_EXTERN_MODULE and RCT_EXTERN_METHOD, and return async data using RCTPromiseResolveBlock and RCTPromiseRejectBlock. You also saw how to emit events with RCTEventEmitter. Next up we explore the modern Turbo Native Module architecture with JSI.

Sıkça Sorulan Sorular

“Swift ile Eski Bir Yerel Modül Yazma” dersi ücretsiz mi?

Evet — “Swift ile Eski Bir Yerel Modül Yazma” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve React Native Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. React Native Academy kursu toplamda 4 dersten oluşur.

“Swift ile Eski Bir Yerel Modül Yazma” dersinde ne öğreneceğim?

Bir Objective-C köprü dosyası ve RCTBridgeModule'a uyan bir Swift sınıfı oluşturun, RCT_EXPORT_METHOD ile bir yöntemi dışa açın ve bunu React Native JS'den çağırın. React Native Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

React Native Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te React Native Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.

“Swift ile Eski Bir Yerel Modül Yazma” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu React Native Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her React Native Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Kotlin ile Eski Bir Yerel Modül Yazma
  2. Swift ile Eski Bir Yerel Modül Yazma
  3. JSI ile Turbo Yerel Modülleri
  4. Yerelden Eşzamansız Geri Çağırmalar, Promise'ler ve Olaylar
← React Native Academy Sayfasına Dön