SwiftUI Document API iOS 27 ile birlikte köklü bir güncelleme aldı: Apple, belge tabanlı uygulamalar için ReadableDocument ve WritableDocument adında iki yeni protokol tanıttı. Bu yazıda bu protokollerin FileDocument ve ReferenceFileDocument'tan farkını, artımlı/asenkron yazma mekanizmasını ve DocumentCreationSource ile çoklu belge oluşturma akışını, Apple'ın WWDC26 kaynakları ve bunları doğrulayan bağımsız bir derlemeye dayanarak adım adım anlatıyorum.
💡 Pro Tip: Yeni deployment target'ın 27+ olduğu bir proje başlatıyorsan,FileDocumentyerine doğrudanReadableDocument/WritableDocumentile başla — geriye geç dönüş migration'dan çok daha ucuz.
İçindekiler
- Neden yeni protokoller geldi
- FileDocument → ReadableDocument göçü (yan yana örnek)
- Eski FileDocument tarafı neye benziyordu
- PageSnapshot ve DocumentReader'ın rolü
- ReferenceFileDocument → WritableDocument
- Somut bir Writer tipi
- Aynı belgeyi PNG olarak da dışa aktarmak
- Artımlı ve asenkron yazma
- previous parametresiyle fark hesaplama
- Subprogress ile ilerleme raporlama
- consuming anahtar kelimesinin anlamı
- DocumentCreationSource ve NewDocumentButton
- Birden fazla kaynağı sahneye eklemek
- iCloud/Files entegrasyonu tuzakları
- Undo action kaydı olmadan autosave neden tetiklenmez
- iOS 26 geriye dönük uyumluluk
- Karma deployment target'ta ne yapmalısın
- SSS
- FileDocument yerine artık ne kullanılıyor?
- ReadableDocument ile WritableDocument farkı nedir?
- Büyük dosyayı SwiftUI'da artımlı nasıl kaydederim?
- DocumentGroup'ta birden fazla yeni-belge kaynağı nasıl tanımlanır?
- Undo action kaydetmezsem ne olur?
- Eski FileDocument kodumu hemen değiştirmem gerekiyor mu?
- Güncelleme (Eylül 2026)
- Sonuç
- Kaynaklar
Neden yeni protokoller geldi
Apple'ın resmi WWDC26 rehberi, genişletilmiş SwiftUI Document API'sini şöyle tanımlıyor: "The expanded SwiftUI Document API gives you direct control over the structure of your saved documents. For reading and writing, conform to WritableDocument and ReadableDocument…" Bu cümle, yeni protokollerin çıkış noktasını özetliyor: eski FileDocument/ReferenceFileDocument çifti, belgenin disk üzerindeki yapısına dair ayrıntılı kontrol vermiyordu.
Apple'ın WWDC26 oturum 269 anlatımı da aynı motivasyonu doğrudan destekliyor: "First, the write method is nonisolated and asynchronous. This lets me perform expensive disk writing operations in the background, so the app stays responsive. I write only the parts of the package that actually need updating, by comparing the current and the previous snapshots." Yani asıl gerekçe tek şey değil: disk yapısı üzerinde doğrudan kontrol, artımlı yazma ve bloklamayan arka plan G/Ç.
Bunlara ek olarak, yeni Document tipi artık bir referans tipi ve @Observable ile işaretli. onmyway133'ün ifadesiyle: "The document is a reference type marked @Observable, so SwiftUI does not recreate it on every change."
WWDC26 rehber sayfası FileDocument'ı doğrudan alıntılamıyor, ama Apple'ın oturum 269 özeti bu protokolden açıkça bahsediyor: "Expanded document APIs for SwiftUI apps, including the new DocumentCreationSource API for custom new-document flows, performance improvements for reading and writing large documents, and first-class support for direct document URL access via the FileDocument and ReferenceFileDocument protocols." onmyway133'ün derlemesi ise bunu daha keskin bir dille özetliyor: "two new protocols replace FileDocument and ReferenceFileDocument for new code." Yani yeni protokoller, yeni yazılan kod için eskilerinin yerini alan bir çift olarak tanımlanıyor; bu ayrım, ilerleyen bölümlerde (özellikle iOS 26 uyumluluğu) doğrudan işine yarayacak.
FileDocument → ReadableDocument göçü (yan yana örnek)
WWDC26 oturumundaki örneğe dayanan aşağıdaki StickerDocument tanımı, WritableDocument'a uyumun nasıl göründüğünü gösteriyor.
ReadableDocument, WWDC26 oturumunda şöyle tanımlanıyor: "ReadableDocument is a twin to WritableDocument. Here's how they compare. Each protocol requires a list of supported content types. WritableDocument provides a snapshot and ReadableDocument knows how to apply it." Aynı oturumda disk erişimi şöyle netleştiriliyor: "ReadableDocument's friend is DocumentReader, which does all the disk-related heavy lifting." Yani ikiz protokol mantığıyla çalışıyor ve diskten okunan anlık görüntüleri (snapshot) belgeye uygulamayı, bu işi devreden DocumentReader aracılığıyla yapıyor.
swift
1@Observable2final class StickerDocument: WritableDocument {3 static let writableContentTypes: [UTType] = [.stickerDocument]4 5 @MainActor6 func snapshot(contentType: UTType) async throws -> sending PageSnapshot {7 // encode current state into a PageSnapshot8 }9 10 func writer(configuration: sending WriteConfiguration) -> sending Writer {11 // return a Writer that knows how to persist a PageSnapshot12 }13}Yukarıdaki tanımdaki @MainActor işaretlemesi, snapshot alma işleminin ana thread üzerinde çalıştığını gösteriyor; ilerleyen bölümde göreceğin yazma tarafındaki nonisolated işaretlemesi ise tam tersine, o işlemin herhangi bir actor'a bağlı olmadan çalışabildiğini gösteriyor.
Eski FileDocument tarafı neye benziyordu
Yan yana karşılaştırmayı tamamlamak için, aynı StickerDocument tipinin eski FileDocument protokolüne uyumu şuna benziyordu — struct, readableContentTypes bildirir, okumayı init(configuration:) içinde, yazmayı ise fileWrapper(configuration:) içinde tek seferde yapar:
swift
1struct StickerDocument: FileDocument {2 static var readableContentTypes: [UTType] { [.stickerDocument] }3 4 init(configuration: ReadConfiguration) throws {5 // configuration.file (bir FileWrapper) içindeki veriyi tek seferde struct'a decode et6 }7 8 func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {9 // struct'ın güncel durumunu tek seferde yeni bir FileWrapper'a encode et10 }11}Yukarıdaki WritableDocument örneğiyle yan yana koyduğunda fark netleşiyor: eski tarafta init(configuration:) ve fileWrapper(configuration:) senkron ve tek parça çalışırken, yeni tarafta snapshot(contentType:) @MainActor'da hazırlanıyor, gerçek disk yazımı ise (ilerleyen bölümde göreceğin) ayrı ve nonisolated bir writer üzerinden yürütülüyor.
PageSnapshot ve DocumentReader'ın rolü
WWDC26 oturum 269'daki örnekte, yukarıdaki snapshot(contentType:) metodunun döndürdüğü tip somut olarak şöyle tanımlanıyor: struct PageSnapshot { var background: Image; var metadata: StickerPlacements; var stickers: [Image] }. Yani snapshot, belgenin o anki durumunu (arka plan görseli, sticker'ların konumlarını tutan metadata ve sticker görsellerinin kendisini) tek bir value type içinde donduruyor; ReadableDocument'ın apply(snapshot:previous:) tarafı da diskten okunan bu PageSnapshot değerini belge nesnesine geri uyguluyor.
Aynı oturumda StickerDocument'ın ReadableDocument'a uyumu ayrı bir extension olarak veriliyor: extension StickerDocument: ReadableDocument {}. Bu, WritableDocument ve ReadableDocument'ın aynı sınıf üzerinde iki ayrı uyum bloğu halinde tanımlanabildiğini, yani okuma ve yazma sorumluluklarının kod içinde de ayrıştırılabildiğini gösteriyor.
Pratik göçte dikkat etmen gereken asıl fark şu: FileDocument value type (struct) olduğu için her okuma yeni bir kopya üretiyordu; ReadableDocument tarafında konu artık referans tipi olan, @Observable bir belge nesnesine snapshot uygulamak. Migration bu yüzden "protokol imzasını değiştirmek" değil, belge modelini value'dan reference'a taşımak anlamına geliyor.
Bu değişimin en somut sonucu SwiftUI view katmanında görünüyor. onmyway133'ün "so SwiftUI does not recreate it on every change, and a TextEditor bound to a document property does not lose its model on each keystroke" ifadesi bunu doğrudan gösteriyor: ReadableDocument referans tipine geçtiğinde, view yeniden çizilse bile belge nesnesinin kimliği (identity) korunuyor, bir TextEditor'ın bağlı olduğu belge property'si her tuş vuruşunda modelini kaybetmiyor.
Boyut | FileDocument (eski) | ReadableDocument (yeni) |
|---|---|---|
Tip doğası | Value (struct) | Referans, @Observable |
Okuma sorumluluğu | init(configuration:) içinde tek seferde | DocumentReader aracılığıyla snapshot uygulama |
Değişiklikte yeniden oluşturma | Her düzenlemede yeni struct kopyası | Nesne kimliği korunur, yeniden oluşturulmaz |
İçerik tipi bildirimi | static var readableContentTypes | readableContentTypes, reader(configuration:), apply(snapshot:previous:) |
ReferenceFileDocument → WritableDocument
ReferenceFileDocument zaten referans tipliydi, bu yüzden WritableDocument'a geçiş kavramsal olarak ReadableDocument göçünden daha az köklü.
onmyway133'ün maddesi burada netlik getiriyor: "You convert between your data and disk through a snapshot, using either the FileWrapperDocumentReader and FileWrapperDocumentWriter convenience types or a fully custom reader and writer for streaming or direct URL access." Yani WritableDocument tarafında veri dönüşümü artık snapshot üzerinden, FileWrapperDocumentWriter gibi somut bir yardımcı tip aracılığıyla ya da tamamen özel bir okuyucu/yazıcıyla yapılıyor — ReferenceFileDocument'ın snapshot(contentType:) + fileWrapper(snapshot:configuration:) ikilisine kavramsal olarak karşılık geliyor ama disk erişimi artık streaming/doğrudan URL desteğiyle genişletilmiş.
Özellik | ReferenceFileDocument (eski) | WritableDocument (yeni) |
|---|---|---|
Tip doğası | Referans (class), ObservableObject | Referans, @Observable |
Yazma yardımcı tipi | fileWrapper(snapshot:configuration:) | FileWrapperDocumentWriter / DocumentWriter |
Disk erişimi | Tek seferlik FileWrapper üretimi | Streaming veya doğrudan URL desteği |
İlerleme raporlama | Belirtilmiyor | Subprogress parametresi |
Somut bir Writer tipi
WWDC26 oturum 269, DocumentWriter'a uyan somut bir yazıcı tipini şöyle veriyor: struct Writer<Snapshot>: DocumentWriter { typealias Snapshot = PageSnapshot; let contentType: UTType }. Yani Writer, hangi PageSnapshot'ı hangi contentType için yazacağını bilen, jenerik bir yardımcı tip; WritableDocument.writer(configuration:) metodu her çağrıldığında bu tipten bir örnek döndürüyor.
Aynı belgeyi PNG olarak da dışa aktarmak
Aynı oturumda, Writer'ın desteklediği içerik tipleri tek bir formatla sınırlı değil. 14:35 civarında .png, writableContentTypes listesine ekleniyor; 14:48'de ise yazıcı bunu şu şekilde dallandırıyor: if contentType.conforms(to: .stickerDocument) { /* .stickerDocument paketini yaz */ } else if contentType.conforms(to: .png) { /* .png için düzleştirilmiş görseli yaz */ }. Yani aynı Writer, contentType parametresine bakarak ya belgenin kendi paket formatını (.stickerDocument) ya da düzleştirilmiş bir PNG çıktısını üretebiliyor — sayfayı görsel olarak dışa aktarma akışında devreye giren dal budur.
Artımlı ve asenkron yazma
previous parametresiyle fark hesaplama
WWDC26 oturumunun kod örneğinde geçen imza, artımlı yazmanın nasıl çalıştığını doğrudan gösteriyor: DocumentWriter.write(snapshot:to:previous:progress:). Buradaki previous parametresi, önceki durumu writer'a taşıyor; writer bu sayede belgenin tamamını değil, yalnızca değişen kısmı yazabiliyor.
swift
1nonisolated func write(2 snapshot: sending PageSnapshot,3 to destination: URL,4 previous: sending PageSnapshot?,5 progress: consuming Subprogress6) async throws {7 // write .stickerDocument8 // previous == nil → ilk kayıt, tam yazma9 // previous != nil → yalnızca fark yazılır (artımlı yazma)10}Apple'ın oturum 269 anlatımı bu artımlı yazmanın nasıl çalıştığını doğrudan doğruluyor: yazma işlemi mevcut ve önceki snapshot'lar karşılaştırılarak yalnızca paketin gerçekten güncellenmesi gereken kısımlarına uygulanıyor. Aynı anlatım, bu işlemin ana thread'i bloklamadan arka planda yürütüldüğünü de ekliyor — yani artımlı yazma yalnızca "daha az veri yaz" değil, aynı zamanda "UI thread'i meşgul etme" anlamına da geliyor.
Pratikte bunun sonucu şu: büyük bir belgede (örneğin onlarca sayfalık bir çizim dosyası) her Cmd+S artık dosyanın tamamını değil, yalnızca son işlemden bu yana değişen parçaları (paket içindeki ilgili dosyaları) diske yazıyor.
Subprogress ile ilerleme raporlama
Yukarıdaki imzada gördüğün progress: consuming Subprogress parametresi, Foundation'ın ilerleme raporlama API'sinin SwiftUI Document katmanına doğrudan entegrasyonu. WWDC26 rehberi bunu şöyle özetliyor: "offer asynchronous, incremental disk operations and progress reporting via the Foundation Subprogress API." onmyway133 da aynı noktayı doğruluyor: "Packages can be read and written incrementally, and progress flows through Subprogress." — iki bağımsız kaynak burada hemfikir.
consuming anahtar kelimesi, Subprogress değerinin write çağrısına devredildiğini (ownership transfer) gösteriyor — yani writer, kendi alt-işlemlerinin ilerlemesini bu tek parametre üzerinden üst çağırana raporluyor. Bu, büyük bir belge kaydederken kullanıcıya "%42 kaydedildi" gibi bir gösterge sunmak istediğinde, kendi ilerleme sayaçlarını elle senkronize etmen gerekmediği anlamına geliyor; framework bunu senin için taşıyor.
consuming anahtar kelimesinin anlamı
swift
1// İmzadan çıkan sonuç (WWDC26'da doğrulanan parametre): consuming Subprogress2// "consuming" → değer write() çağrısına devredilir, sahiplik geri dönmez.3// Pratik etkisi: ilerlemeyi kendi elinle güncellemene gerek yok,4// DocumentWriter alt-işlemlerin ilerlemesini bu parametre üzerinden kendisi raporluyor.DocumentCreationSource ve NewDocumentButton
WWDC26 rehberi bu özelliği net bir cümleyle tanımlıyor: "The DocumentCreationSource API lets you declare multiple creation sources with a NewDocumentButton for each." Yani bir belge tabanlı uygulamada artık tek bir "Yeni Belge" düğmesi yerine, her biri farklı bir başlangıç durumuna (boş sayfa, şablon, fotoğraftan içe aktarma gibi) karşılık gelen birden fazla düğme tanımlayabiliyorsun.
WWDC26 oturumunun kod örneğinde geçen literal çağrı şu:
swift
1extension DocumentCreationSource {2 static let blank = Self(id: "blank")3 static let photo = Self(id: "photo")4}5 6DocumentGroupLaunchScene("Create a Sticker Page") {7 NewDocumentButton("New Sticker Page", source: .blank)8 NewDocumentButton("Sticker Page from Photo…", source: .photo)9}Birden fazla kaynağı sahneye eklemek
Bu kod bloğunun gösterdiği örüntü açık: her kaynak, bir id string'iyle başlatılan statik bir DocumentCreationSource değeri olarak tanımlanıyor; NewDocumentButton da bir başlık string'i ve bu değeri alıyor. Aynı oturumda düğmelerin sahne içindeki dizilimi de net: DocumentGroupLaunchScene içinde birden fazla NewDocumentButton alt alta tanımlanıyor, her biri kendi source değerini taşıyor. Bunun pratikteki karşılığı şu: bir çizim uygulamasında "Boş Sayfa" ve "Fotoğraftan Başla" gibi iki farklı akışın olması, kullanıcıya iki ayrı NewDocumentButton satırı, iki farklı source değeriyle sunulması demek.
iCloud/Files entegrasyonu tuzakları
iCloud veya Dosyalar (Files) senkronizasyonu düşünülürken akılda tutulması gereken, onmyway133'ün derlemesinde doğrulanan genel geçerli bir tuzak var: "One thing to remember is that SwiftUI tracks unsaved changes through undo actions, so without registered undo actions it will not autosave." Yani SwiftUI, kaydedilmemiş değişiklikleri undo (geri al) action'ları üzerinden takip ediyor. Eğer bir değişiklik undo stack'e kaydedilmemişse, otomatik kayıt (autosave) tetiklenmiyor.
Undo action kaydı olmadan autosave neden tetiklenmez
Bunun pratik sonucu şu: belgeni doğrudan bir @Observable property'sine atayarak değiştirirsen (undo action kaydetmeden), SwiftUI bu değişikliği "kaydedilmemiş" olarak işaretlemez ve otomatik kaydetmez — dosya diskte (dolayısıyla iCloud senkronizasyonunda da) eski haliyle kalır. Bu yüzden her mutasyonu, UndoManager üzerinden kayıtlı bir action olarak yapman gerekiyor; aksi halde kullanıcı değişikliği "kaybetmiş" gibi görünür, oysa aslında hiç yazılmamıştır.
iOS 26 geriye dönük uyumluluk
Apple'ın kanonik doküman verisi burada net: yeni protokoller yalnızca iOS 27.0, iPadOS 27.0, Mac Catalyst 27.0, macOS 27.0 ve visionOS 27.0 ile geliyor (readabledocument.json ve writabledocument.json'daki platform kayıtları) — yani iOS 26'ya geri taşınmıyor. Eski FileDocument ve ReferenceFileDocument ise iOS 14.0 / macOS 11.0'dan beri var; publish tarihi itibarıyla karma bir deployment target'ta (27 altını da kapsayan) bu protokollerde kalmak zorunluluk, çünkü yeni protokoller o ortamda çalışmıyor.
Bunun sonucu şu: deployment target 27+ ise onmyway133'ün derlemesindeki tavsiye net — "If you are starting a document app today and your deployment target is 27 or later, reach for these rather than the older protocols." Karma bir deployment target'ta (iOS 26+27) ise eski API'de kalmak tercih değil, zorunluluk — yeni protokoller iOS 26'da yok.
Karma deployment target'ta ne yapmalısın
Bu tavsiyeyi, daha önce "Neden yeni protokoller geldi" bölümünde belirttiğim onmyway133 kaynaklı "replace ... for new code" ifadesiyle birlikte okumak gerekiyor: yeni protokoller yeni yazılan kod için eskilerinin yerini alıyor, ama publish tarihi itibarıyla eskiler hâlâ kullanılabilir durumda olduğu için karma deployment target'lı bir uygulama her iki protokol ailesini de aynı anda barındırabiliyor — biri 27+ akış için, diğeri geriye dönük uyumluluk için.
ALTIN İPUCU
Bu yazının en değerli bilgisi
Bu ipucu, yazının en önemli çıkarımını içeriyor.
Easter Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
Okuyucu Ödülü
Bu yazıyı buraya kadar okuduysan, yeni Document API'ye geçerken izleyebileceğin sıralı bir kontrol listesi hak ediyorsun. Aşağıdaki maddeler, yazının içindeki kaynaklı tuzakları ve adımları tek bir sırayla topluyor — migration'a başlamadan önce her birini işaretle.
SSS
FileDocument yerine artık ne kullanılıyor?
iOS, macOS ve visionOS 27 ile Apple, belge tabanlı SwiftUI uygulamaları için ReadableDocument ve WritableDocument protokollerini sundu. onmyway133'ün ifadesiyle bu iki protokol, eski FileDocument/ReferenceFileDocument çiftinin yerini alıyor ("two new protocols replace FileDocument and ReferenceFileDocument for new code.") ve yeni kod için önerilen yaklaşım olarak konumlanıyor.
ReadableDocument ile WritableDocument farkı nedir?
ReadableDocument, desteklenen içerik tiplerini tutar ve diskten okunan snapshot'ları belgeye uygulamayı bilir; bu iş bir DocumentReader aracılığıyla yürütülür. WritableDocument ise yazılabilir formatların listesini ve mevcut içeriği döndüren bir snapshot mekanizmasını, DocumentWriter'a uyan bir yazıcı tipi üzerinden sağlar — biri okuma, diğeri kaydetme sorumluluğunu taşıyan ikiz protokoller.
Büyük dosyayı SwiftUI'da artımlı nasıl kaydederim?
WritableDocument'ın yazıcı tipi, write(snapshot:to:previous:progress:) imzasında previous parametresiyle önceki durumu alır ve yalnızca değişen kısmı yazar. Aynı çağrı progress: consuming Subprogress parametresiyle ilerlemeyi de raporlar — böylece büyük belgeleri her seferinde baştan yazmak yerine parça parça, asenkron kaydedebilirsin.
DocumentGroup'ta birden fazla yeni-belge kaynağı nasıl tanımlanır?
Her farklı başlangıç durumu için bir DocumentCreationSource değeri tanımlayıp bunu NewDocumentButton("Başlık", source: kaynak) çağrısına verirsin. WWDC26 kod örneğindeki doğrulanmış çağrı NewDocumentButton("New Sticker Page", source: .blank) şeklinde; aynı düğme tipini farklı source değerleriyle tekrar kullanarak DocumentGroupLaunchScene içinde birden fazla oluşturma seçeneği sunabilirsin.
Undo action kaydetmezsem ne olur?
SwiftUI, kaydedilmemiş değişiklikleri undo stack üzerinden takip ettiği için, bir mutasyon UndoManager'a kayıtlı bir action olarak yapılmadıysa autosave tetiklenmez. Bu, belgenin UI'da değişmiş görünüp diskte eski haliyle kalmasına yol açabilir — bu yüzden her düzenlemeyi undo-farkında bir action içinde yapmak gerekiyor.
Eski FileDocument kodumu hemen değiştirmem gerekiyor mu?
Kısa vadede hayır. FileDocument ve ReferenceFileDocument, iOS 14.0 / macOS 11.0'dan beri kullanılabilir durumdalar. Yeni ReadableDocument/WritableDocument çifti yalnızca iOS/macOS/visionOS 27.0 ve üzeriyle geliyor, iOS 26'ya geri taşınmıyor. Deployment target'ın 27 altını da kapsıyorsa, eski API ile devam etmek zorunluluk — yeni protokoller o ortamda çalışmıyor. Bu iki protokolün durumuyla ilgili yayından sonraki bir gelişme için aşağıdaki '## Güncelleme (Eylül 2026)' bölümüne bak.
Güncelleme (Eylül 2026)
Bu yazının yayın tarihinden (19 Haziran 2026) sonra, Apple'ın kanonik doküman verisinde gerçek bir değişiklik oldu: FileDocument ve ReferenceFileDocument, 27.2 itibarıyla deprecated olarak işaretlendi. FileDocument'ın kayıtlarındaki uyarı şu: "Conform your type to Document instead." ReferenceFileDocument'ınki ise: "Use Document protocol instead." Her iki protokol de iOS/iPadOS/Mac Catalyst 14.0, macOS 11.0'dan beri vardı; deprecation yalnızca 27.2 ile geldi, geriye dönük bir davranış değişikliği değil.
Apple'ın işaret ettiği Document protokolü, ReadableDocument ve WritableDocument'ın ikisini birden devralıyor: "Inherits From: ReadableDocument, WritableDocument", abstract'ı ise "A document that supports both reading and writing." (iOS/macOS/visionOS 27.0). Yani bu yazının anlattığı ikiz-protokol modeli değişmedi; Document, iki protokolü tek bir isimde birleştiren bir üçüncü protokol olarak üste eklendi. Yukarıdaki '## iOS 26 geriye dönük uyumluluk' bölümündeki önceki değerlendirmeyi bu bilgiyle birlikte oku: deployment target 27 altını kapsıyorsa eski protokollerde kalmak hâlâ zorunlu, ama artık bu bir "deprecated değil" durumu değil, "deprecated ama halihazırda tek seçenek" durumu.
Sonuç
ReadableDocument ve WritableDocument, SwiftUI'nin belge tabanlı uygulamalar için sunduğu en somut altyapı güncellemelerinden biri: referans tipli, @Observable bir belge modeli, Subprogress ile ilerleme raporlayan artımlı/asenkron yazma ve DocumentCreationSource ile çoklu belge oluşturma kaynağı. Ama bunun bir "büyük patlama" migration'ı olması da gerekmiyor: yeni protokoller yeni yazılan kod için eskilerin yerini alıyor, ama FileDocument/ReferenceFileDocument iOS 27 altını kapsayan deployment target'larda hâlâ zorunlu; taşıma yalnızca deployment target 27+ olduğunda bir tercih haline geliyor (bkz. aşağıdaki Güncelleme bölümü).
Belge modelini referans tipine taşımadan önce SwiftUI'nin state yönetimini genel hatlarıyla tazelemek istersen SwiftUI property wrapper'larını derinlemesine ele aldığım yazıya bakabilirsin. Masaüstü tarafında belge tabanlı bir macOS uygulaması planlıyorsan macOS'ta SwiftUI ile masaüstü geliştirme rehberi bu yazıyı tamamlayan bir sonraki adım. iOS 27'nin diğer kırılan davranışlarını merak ediyorsan State makrosu ve ContentBuilder'da neyin kırıldığını anlattığım yazıya göz atabilirsin. Belge modelini bileşenlere ayırmayı düşünüyorsan özel component kütüphanesi rehberi ve büyük belgelerde performans için performans optimizasyonu yazısı da işine yarayacak referanslar.
Kaynaklar
- WWDC26 SwiftUI rehberi — Apple'ın resmi rehberi; ReadableDocument/WritableDocument, Subprogress ve DocumentCreationSource'un birincil kaynağı.
- What's new in SwiftUI in iOS 27 (onmyway133) — 9 Haziran 2026 tarihli bağımsız derleme; undo-tabanlı autosave tuzağı dahil çoğu maddeyi doğrulayan ikinci kaynak.
- WWDC26 "What's new in SwiftUI" oturum videosu — DocumentWriter imzası ve NewDocumentButton kod örneğinin geçtiği oturum.
- ReadableDocument dokümantasyonu — protokolün resmi referans sayfası.
- WritableDocument dokümantasyonu — protokolün resmi referans sayfası.
- FileDocument dokümantasyonu — eski protokolün kanonik referans sayfası.
- ReferenceFileDocument dokümantasyonu — eski referans-tipli protokolün kanonik sayfası.
- Document protokolü dokümantasyonu — FileDocument/ReferenceFileDocument'ın yerine önerilen, ReadableDocument+WritableDocument'ı devralan protokol.
- DocumentGroup dokümantasyonu — DocumentCreationSource ve NewDocumentButton'ın bağlandığı kanonik tip.
- Foundation Subprogress dokümantasyonu — ilerleme raporlama için kullanılan Foundation API'si.

