Modern bir yardımcı uygulama geliştirirken uygulamanın içindeki göz alıcı bir arayüz artık yeterli değil. Kullanıcıyı elde tutmanın asıl savaş alanı ana ekran.
Minimalist su takip uygulamam WaterPaw’u geliştirirken yerel iOS Widget’ları vazgeçilmez bir özellikti. Kullanıcılar ana ekranlarına göz atıp su içme halkalarını görebilmeli. Ancak React Native / Expo ekosisteminde çalışıyorsanız bu işin tarihsel korkusunu bilirsiniz: iOS widget’ları yerel Swift yazmayı, özel App Extension’ları yapılandırmayı ve Xcode’da kod imzalama hedeflerini yönetmeyi gerektirir - bunu elle yapmak kesintisiz, yönetilen Expo iş akışını tamamen bozar.
İşte Expo Config Plugin’ler ve paylaşılan yerel öncelikli depolama kullanarak yerel iOS widget’larını yayınlamak için kullandığım temiz, otomatik mimari.
Mimari Zorluk: Uygulamadan Widget’a Sandbox
WaterPaw yerel öncelikli ve gizlilik odaklı olduğu için veriler tamamen cihazda kalır. Ancak bir iOS Widget’ı kendi ayrı işletim sistemi arka plan sürecinde çalışır - uygulamanızın standart AsyncStorage’ına veya belge dizini dosyalarına erişemez.
Bulut backend’i kurmadan bu boşluğu kapatmak için App Group adlı bir Apple sandbox kapsayıcısı yapılandırmanız gerekir:
[ WaterPaw React Native App ]
→ (Writes to Shared Suite)
→ [ iOS App Group Container ]
→ [ iOS Native Home Widget ] ← (Reads via Swift)Adım 1: React Native’den Veri Yazmak
Kullanıcı JavaScript katmanında su kaydettiğinde bu veriyi paylaşılan App Group’a göndermemiz gerekir. Yerel köprü bağlantısını yönetmek için react-native-shared-group-preferences kullanabiliriz:
import SharedGroupPreferences from 'react-native-shared-group-preferences';
const APP_GROUP = 'group.com.yourgroupname';
export const syncDataToWidget = async (currentMl: number, goalMl: number) => {
const dataForWidget = {
progress: currentMl / goalMl,
displayString: `${currentMl} / ${goalMl} ml`,
updatedAt: new Date().toISOString()
};
try {
await SharedGroupPreferences.setItem('WidgetData', dataForWidget, APP_GROUP);
} catch (error) {
console.error('Failed to sync data to iOS App Group Suite', error);
}
};Adım 2: Paylaşılan Veriyi Swift’te Kullanmak
Yerel Swift widget dizininizin içinde artık UserDefaults(suiteName:) ile aynı App Group paketinden anında okuyabilirsiniz. Bu, her şeyi yerel, anlık ve %100 gizli tutar:
import WidgetKit
import SwiftUI
struct HydrationEntry: TimelineEntry {
let date: Date
let progress: Double
let displayString: String
}
struct WaterPawWidgetEntryView: View {
var entry: Provider.Entry
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text("WaterPaw")
.font(.caption)
.foregroundColor(.secondary)
Text(entry.displayString)
.font(.title2)
.bold()
ProgressView(value: entry.progress)
.progressViewStyle(LinearProgressViewStyle(tint: .blue))
}
.padding()
}
}Adım 3: Expo Config Plugin’ler ile Xcode’u Otomatikleştirmek 🛠️
Geliştiricilerin genellikle sorun yaşadığı yer burası. npx expo prebuild çalıştırırsanız Expo, widget için yaptığınız tüm manuel Xcode değişikliklerini veya hedeflerini tamamen siler.
Tamamen yönetilen bir iş akışını sürdürmek için Swift kodumuzu bağımsız bir targets/ dizinine ayırır ve yerel derlemeyi otomatikleştirmek için bir Config Plugin (expo-target-extension gibi) kullanırız. Bu, Expo’ya Widget Target’ı otomatik oluşturmasını, Swift derleme aşamalarını bağlamasını ve App Group yetkilerini her seferinde eklemesini söyler:
{
"expo": {
"name": "WaterPaw",
"slug": "waterpaw",
"plugins": [
[
"expo-target-extension",
{
"targetName": "WaterPawWidget",
"dir": "targets/widgets",
"entitlements": {
"com.apple.security.application-groups": ["group.com.yourgroupname"]
}
}
]
]
}
}Bu kurulumu app.json içine koyarak, ios/ dizininizi temizleyip npx expo prebuild --clean çalıştırdığınızda yerel Xcode ortamı kutudan çıktığı gibi tamamen yapılandırılır.
Sonuç: Eject Etmeyin, Otomatikleştirin
Yerel eklenti iş akışlarını tamamen Config Plugin’lere taşımak, mobil projenizi temiz ve geleceğe hazır tutar. Expo’nun hızlı yineleme döngülerini korurken kullanıcılarınıza derinlemesine entegre, sıfır gecikmeli bir iOS sistem özelliği sunarsınız.
Yardımcı uygulamalar geliştirirken verilerinizi ana ekranda bir bakışta görünür kılmak için harcanan ekstra çaba, uzun vadeli etkileşimde büyük karşılık bulur. Bu mimariyi WaterPaw içindeki bir bakışta görülebilir ilerleme halkalarını ve maskot takibi özelliklerini uygulamak için kullandım.
