Tüm Yazılar
KategoriFlutter
Okuma Süresi
22 dk
Yayın Tarihi
...
Kelime Sayısı
1.442kelime

Kahveni hazırla - bu içerikli bir makale!

Flutter'da MethodChannel, EventChannel ve Pigeon ile native iOS modülleri. Add-to-app, PlatformView ve FlutterEngine yönetimi.

Flutter ile iOS Entegrasyonu: Platform Channel ve Native Modüller

Flutter ile cross-platform uygulama geliştiriyorsun ama bazı özellikler native API gerektiriyor — HealthKit, Face ID, ARKit, Core Bluetooth. Bu durumda Platform Channel devreye girer. Flutter'ın Dart tarafı ile iOS'un Swift tarafı arasında köprü kurar.

💡 Hızlı Not: Flutter 3.0+ ile Pigeon code generator önerilir. Manuel MethodChannel hala çalışır ama Pigeon tip-güvenli ve daha az boilerplate sağlar.

İçindekiler

  1. Platform Channel Nedir?
  2. MethodChannel ile İletişim
  3. EventChannel ile Stream
  4. Pigeon ile Tip-Güvenli İletişim
  5. PlatformView: Native UIKit in Flutter
  6. Add-to-App: Flutter'ı Mevcut iOS App'e Ekle
  7. FlutterEngine Yönetimi
  8. Performance Karşılaştırma
  9. Ne Zaman Native, Ne Zaman Flutter?
  10. Best Practices

Platform Channel Nedir? {#platform-channel}

Platform Channel, Flutter (Dart) ile native platform (Swift/Kotlin) arasında asenkron mesajlaşma mekanizmasıdır:

Channel Tipi
Yön
Kullanım
MethodChannel
İki yönlü
Tek seferlik çağrılar (getBatteryLevel)
EventChannel
Native → Dart
Sürekli veri akışı (location updates)
BasicMessageChannel
İki yönlü
Düşük seviye mesajlaşma

MethodChannel ile İletişim {#method-channel}

dart
1// Dart tarafı
2import 'package:flutter/services.dart';
3 
4class BatteryService {
5 static const _channel = MethodChannel('com.myapp/battery');
6 
7 Future getBatteryLevel() async {
8 final int level = await _channel.invokeMethod('getBatteryLevel');
9 return level;
10 }
11 
12 Future isCharging() async {
13 return await _channel.invokeMethod('isCharging');
14 }
15}
swift
1// iOS Swift tarafı (AppDelegate.swift)
2import Flutter
3import UIKit
4 
5@UIApplicationMain
6@objc class AppDelegate: FlutterAppDelegate {
7 override func application(
8 _ application: UIApplication,
9 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
10 ) -> Bool {
11 let controller = window?.rootViewController as! FlutterViewController
12 let channel = FlutterMethodChannel(
13 name: "com.myapp/battery",
14 binaryMessenger: controller.binaryMessenger
15 )
16 
17 channel.setMethodCallHandler { [weak self] call, result in
18 switch call.method {
19 case "getBatteryLevel":
20 let level = self?.getBatteryLevel() ?? -1
21 result(level)
22 case "isCharging":
23 let charging = self?.isCharging() ?? false
24 result(charging)
25 default:
26 result(FlutterMethodNotImplemented)
27 }
28 }
29 
30 return super.application(application, didFinishLaunchingWithOptions: launchOptions)
31 }
32 
33 private func getBatteryLevel() -> Int {
34 UIDevice.current.isBatteryMonitoringEnabled = true
35 return Int(UIDevice.current.batteryLevel * 100)
36 }
37 
38 private func isCharging() -> Bool {
39 UIDevice.current.isBatteryMonitoringEnabled = true
40 return UIDevice.current.batteryState == .charging
41 }
42}

EventChannel ile Stream {#event-channel}

dart
1// Dart - sürekli konum güncellemesi al
2class LocationService {
3 static const _channel = EventChannel('com.myapp/location');
4 
5 Stream> get locationStream {
6 return _channel.receiveBroadcastStream().map((event) {
7 final map = Map.from(event);
8 return {
9 'latitude': map['latitude'] as double,
10 'longitude': map['longitude'] as double,
11 };
12 });
13 }
14}
swift
1// iOS - EventChannel handler
2class LocationStreamHandler: NSObject, FlutterStreamHandler, CLLocationManagerDelegate {
3 private let locationManager = CLLocationManager()
4 private var eventSink: FlutterEventSink?
5 
6 func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
7 self.eventSink = events
8 locationManager.delegate = self
9 locationManager.startUpdatingLocation()
10 return nil
11 }
12 
13 func onCancel(withArguments arguments: Any?) -> FlutterError? {
14 locationManager.stopUpdatingLocation()
15 eventSink = nil
16 return nil
17 }
18 
19 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
20 guard let location = locations.last else { return }
21 eventSink?([
22 "latitude": location.coordinate.latitude,
23 "longitude": location.coordinate.longitude,
24 ])
25 }
26}

Pigeon ile Tip-Güvenli İletişim {#pigeon}

dart
1// pigeon/messages.dart - Pigeon şema tanımı
2import 'package:pigeon/pigeon.dart';
3 
4class SearchRequest {
5 String? query;
6 int? limit;
7}
8 
9class SearchResponse {
10 List? results;
11 int? totalCount;
12}
13 
14@HostApi()
15abstract class SearchApi {
16 SearchResponse search(SearchRequest request);
17}
18 
19// pigeon generate komutu ile Swift ve Dart kodu otomatik oluşturulur
20// flutter pub run pigeon --input pigeon/messages.dart

PlatformView: Native UIKit in Flutter {#platform-view}

swift
1// iOS Native MKMapView'ı Flutter'da göster
2class MapViewFactory: NSObject, FlutterPlatformViewFactory {
3 func create(withFrame frame: CGRect, viewIdentifier viewId: Int64,
4 arguments args: Any?) -> FlutterPlatformView {
5 return MapPlatformView(frame: frame, viewId: viewId, args: args)
6 }
7}
8 
9class MapPlatformView: NSObject, FlutterPlatformView {
10 private let mapView: MKMapView
11 
12 init(frame: CGRect, viewId: Int64, args: Any?) {
13 mapView = MKMapView(frame: frame)
14 super.init()
15 }
16 
17 func view() -> UIView { mapView }
18}
dart
1// Dart tarafında kullanım
2Widget build(BuildContext context) {
3 return UiKitView(
4 viewType: 'native-map-view',
5 creationParams: {'latitude': 41.0, 'longitude': 29.0},
6 creationParamsCodec: StandardMessageCodec(),
7 );
8}

Add-to-App: Flutter'ı Mevcut iOS App'e Ekle {#add-to-app}

Mevcut native iOS uygulamana Flutter modülü ekleyebilirsin:

swift
1// Podfile'a ekle
2// pod 'Flutter', :podspec => '../my_flutter/.ios/Flutter/Flutter.podspec'
3 
4// FlutterViewController'ı göster
5let flutterEngine = FlutterEngine(name: "my engine")
6flutterEngine.run()
7 
8let flutterVC = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
9present(flutterVC, animated: true)

FlutterEngine Yönetimi {#flutter-engine}

swift
1// Engine group ile birden fazla Flutter ekranı
2class FlutterEngineManager {
3 static let shared = FlutterEngineManager()
4 let engineGroup = FlutterEngineGroup(name: "multi-engine", project: nil)
5 
6 func makeEngine(entrypoint: String? = nil) -> FlutterEngine {
7 engineGroup.makeEngine(withEntrypoint: entrypoint, libraryURI: nil)
8 }
9}

Performance Karşılaştırma {#performance}

Metrik
Flutter
Native
Startup time
+200-500ms
Baseline
Memory overhead
+30-50MB
Baseline
Frame rate
60fps (çoğunlukla)
60-120fps
Platform channel latency
~0.1ms
N/A
App size
+5-15MB
Baseline

Ne Zaman Native, Ne Zaman Flutter? {#ne-zaman}

Native tercih et:

  • HealthKit, ARKit, Core Bluetooth gibi platform-specific API yoğunsa
  • Maksimum performans kritikse (oyun, video)
  • Küçük ekip, tek platform

Flutter tercih et:

  • iOS + Android aynı anda
  • UI-yoğun uygulamalar
  • Hızlı prototipleme
  • Büyük ekip, kod paylaşımı önemli

Best Practices {#best-practices}

  1. Pigeon kullan — manual MethodChannel yerine
  2. PlatformView minimize et — performans etkisi var
  3. Engine warming — FlutterEngine'i önceden başlat
  4. Channel isimlendirme — reverse domain notation (com.myapp/feature)
  5. Error handling — her iki tarafta da try-catch

Hata Yönetimi ve Debug {#error-handling}

Platform Channel'da hata ayıklama kritiktir. Dart ve Swift arasında hata iletişimi düzgün kurulmalıdır:

swift
1// Swift tarafında detaylı hata döndürme
2channel.setMethodCallHandler { call, result in
3 switch call.method {
4 case "processImage":
5 guard let args = call.arguments as? [String: Any],
6 let path = args["path"] as? String else {
7 result(FlutterError(
8 code: "INVALID_ARGS",
9 message: "path parametresi gerekli",
10 details: "Beklenen: [String: Any] icinde 'path' key'i"
11 ))
12 return
13 }
14 
15 do {
16 let processed = try ImageProcessor.process(path: path)
17 result(processed)
18 } catch let error as ImageError {
19 result(FlutterError(
20 code: "PROCESSING_FAILED",
21 message: error.localizedDescription,
22 details: "File: \(path), Error code: \(error.code)"
23 ))
24 } catch {
25 result(FlutterError(
26 code: "UNKNOWN",
27 message: error.localizedDescription,
28 details: nil
29 ))
30 }
31 default:
32 result(FlutterMethodNotImplemented)
33 }
34}
dart
1// Dart tarafında hata yakalama
2Future processImage(String path) async {
3 try {
4 final result = await _channel.invokeMethod('processImage', {'path': path});
5 return result ?? '';
6 } on PlatformException catch (e) {
7 switch (e.code) {
8 case 'INVALID_ARGS':
9 throw ArgumentError(e.message ?? 'Gecersiz arguman');
10 case 'PROCESSING_FAILED':
11 throw ProcessingException(e.message ?? 'Islem basarisiz', details: e.details);
12 default:
13 throw Exception('Bilinmeyen hata: ' + e.message);
14 }
15 }
16}

Channel Performans Optimizasyonu {#channel-performance}

Teknik
Aciklama
Kazanc
Batch calls
Birden fazla cagriyi tek mesajda birlestir
%40-60 latency azalma
Binary codec
StandardMessageCodec yerine custom binary format
%30 daha az veri transferi
Background thread
Agir native islemleri DispatchQueue.global()'da calistir
UI donmasi engellenir
Pigeon
Tip-guvenli code generation, az boilerplate
Hata orani %80 duser
Engine cache
FlutterEngine'i once baslatip hazirda tut
Ilk acilis %50 hizlanir
swift
1// Background thread'de agir islem
2channel.setMethodCallHandler { call, result in
3 if call.method == "heavyComputation" {
4 DispatchQueue.global(qos: .userInitiated).async {
5 let output = performHeavyTask()
6 DispatchQueue.main.async {
7 result(output)
8 }
9 }
10 }
11}

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Okuyucu Ödülü

Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var: **Kaynaklar:** - [Flutter: Platform Channels](https://docs.flutter.dev/platform-integration/platform-channels) - [Flutter: Add-to-app](https://docs.flutter.dev/add-to-app) - [Pigeon Package](https://pub.dev/packages/pigeon)

Etiketler

#flutter#ios#platform-channel#native#dart#swift#cross-platform
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz