Apple metin düzenleyicisinin teknik iç yapısı
TextView tabanlı bir metin düzenleyici olarak Paper’ın nasıl çalıştığına dair ayrıntıları ele alıyor.
- Paper şu anda TextKit 1 framework’ü üzerine kurulu ve kavramlar, soyutlamalar ile ilkeler TextKit 2’de de korunuyor ya da daha iyi API’lerle değiştiriliyor.
Metin görünümü
TextView sınıfı, Apple metin düzenleyicisinde metin düzenleme işlemlerinin merkezinde yer alır.
NSTextView ve UITextView arasında farklar vardır, ancak API’leri benzer olduğu için tek bir TextView sınıfı gibi ele alınır.
TextView, karmaşıklığı her OS sürümünde artan büyük ölçekli bir bileşendir.
- Apple, metin düzenleme deneyimini sunmak için
TextView’i birden çok katmana ayırır.
NSTextStorage
- Ham metin dizgesini saklar.
- Metin aralıklarına atanmış öznitelikleri (string-değer çiftleri) saklar.
- Metin ve öznitelik değişiklikleri için olay üretir.
NSTextContainer
- Metin sembollerini (glyph) barındıran alanın şeklini ve boyutunu tanımlar.
NSLayoutManager
NSTextStorage içindeki metin dizgesine uygulanan öznitelik aralıklarına bakarak glyph boyutlarını ve aralıklarını hesaplar.
- Glyph’leri yerleştirir; metnin her satırının nerede başlayıp bittiğini ve tüm metnin yüksekliğini hesaplar.
TextView
NSLayoutManager tarafından üretilen glyph yerleşimini çizer.
- Görünümün yüksekliğini, yerleştirilmiş metnin güncel yüksekliğiyle senkronize eder.
- Metin seçimini, caret’i ve yeni eklenen metne uygulanacak yazım özniteliklerini yönetir.
ScrollView
TextView’in görünür bölümünü gösterir.
- Kaydırma, kaydırma çubukları ve yakınlaştırmayı yönetir.
Öznitelikler
NSAttributedString, Apple framework’lerinde zengin metin düzenlemenin temelidir.
- Düz metin dizgesi ile metin aralıklarına eklenmiş özniteliklerden (string-değer çiftleri) oluşur.
- Öznitelikler çoğunlukla biçimlendirme amacıyla kullanılır, ancak özel string-değer çiftleri atamak konusunda bir sınırlama yoktur.
Biçimlendirme
- Biçimlendirme, metin aralıklarına framework tarafından tanımlanmış özel özniteliklerin uygulanması anlamına gelir.
- Paper, metin yapısını belirlemek için meta öznitelikleri kullanır ve ardından biçimlendirmeyi uygular.
- Öznitelikler, kullanıcı girdisi nedeniyle değişen
NSTextStorage içindeki Markdown metni ve kullanıcının menü öğeleri, slider’lar ve gesture’lar üzerinden ayarladığı metni etkileyen ayarlar ile senkronize edilir.
Performans
- Meta, yerleşim ve dekorasyon özniteliklerinin ayrılması, belirli düzenleyici değişikliklerini hızlı şekilde korumaya yardımcı olur.
- Yazma hızı, metin düzenleyicisindeki en önemli performans unsurudur.
- Markdown’un çalışma biçimi nedeniyle metin değişiklikleri, tüm paragrafın biçimlendirmesini etkileyebilir.
Meta öznitelikler
- Vurgulama mantığının yanı sıra meta öznitelikler, metin yapısını bilmesi gereken çeşitli özelliklerde önemli rol oynar.
Biçimlendirme kısayolları
- Seçili Markdown metninin stilini açıp kapatmak için gereken ayrıntılı bilgileri sağlar.
Bölümler arasında gezinme
- Caret konumuna göre ilgili başlığı bulmaya yardımcı olur.
Taslak (Outline)
- Tüm başlıkları dolaşma işlevine dayanır.
Bölüm yeniden sıralama
- Taslak içinde bölümlerin yeniden sıralanmasını sağlar.
Biçim dönüştürme
- Markdown içeriğini RTF, HTML ve DOCX’e dönüştürmek için yapının bilinmesi gerekir.
Metin kapsayıcısı matematiği
- Metin kapsayıcısında en önemli kural, tercih edilen satır uzunluğunu korumaktır.
- Başlık etiketlerinin normal metin akışının dışına yerleştirildiği durumlarda olduğu gibi, bazen simetri varmış gibi davranmak gerekir.
Seçim sabitleme
- Metin seçiminin her zaman bir anchor point’i vardır.
- Mac’te tıklayıp sürükleyerek metin seçilir; iOS’te ise seçimin bir ucunu sürüklemek mümkündür.
Seçim affinity’si
- Metin düzenlemede selection affinity adlı ilginç bir kavram vardır.
- Caret’i ok tuşlarıyla hareket ettirdiğinizde satır basitçe değişir; ancak kısayolla satır sonuna gittiğinizde aynı satırda kalıp sağ tarafa yapışır.
Uniform Type Identifiers (UTIs)
- Uygulamalar arası veri alışverişinin temel sistemi olan UTIs ele alınıyor.
- Veri türlerinin üst veri türlerine conform to (kalıtım yoluyla uyum sağlaması) üzerinden bağlandığı hiyerarşik bir sistemdir.
Pano (Pasteboard)
- Pano, UTIs’nin serileştirilmiş veriye eşlendiği bir sözlüktür.
- Tek bir copy işlemi, aynı verinin birden çok gösterimini aynı anda yazar.
- Genel UTIs ve özel UTIs ile çalışmak görece basittir, ancak Apple tarafından tanımlanmamış ama yaygın kabul gören biçimleri ele almak daha karmaşıktır.
Kapanış
- İlk makaleye göz atarsanız uygulama ve geliştirme süreci hakkında daha fazla bilgi edinebilirsiniz.
GN⁺ görüşü
- Bu makale, Apple platformlarında
TextView tabanlı bir metin düzenleyicisinin karmaşık iç işleyişini ayrıntılı biçimde anlatarak yazılım geliştiriciler ve konuya ilgi duyan kullanıcılar için ilgi çekici bilgiler sunuyor.
- Metin düzenleyicisinin performansını optimize etmek için kullanılan algoritmalar ve öznitelik yönetimi yöntemleri, geliştiricilerin kendi uygulamalarını tasarlarken başvurabileceği iyi örnekler sunuyor.
- Performansı artırmak için kullanılan teknik yaklaşım, benzer sorunları çözen diğer geliştiricilere yararlı bir yol gösterici olabilir.
- Markdown gibi metin biçimlerini işleyen uygulamalar geliştirirken, veri alışverişi ve uyumluluk açısından UTIs’yi anlamak önemlidir.
- Bu makale, metin düzenleyicisinin iç yapısını anlamayı kolaylaştırsa da bu karmaşıklığı pratikte yönetmek geliştiriciler için ciddi bir zorluk olabilir.
1 yorum
Hacker News yorumları
Bu yazı gerçekten çok iyi. TextKit için temel giriş kaynağım olarak https://www.objc.io'nun yerini alacak gibi görünüyor.
Düzenleme transaction'larının dışında gerçekleştirilen dekoratif öznitelikler konusunda biraz kafam karıştı. "Ve transaction'dan haberdar değiller, çünkü NSTextStorage'da değil, NSLayoutManager'ın kendisinde bulunuyorlar" denmiş. Oysa renk gibi dekoratif öznitelikler normalde NSTextStorage'da bulunur! Yazar, Markdown karakterlerine uygulanan rengin NSLayoutManager'ın geçici öznitelik desteğiyle (genelde yazım hatalı sözcükleri renklendirmek için kullanılır) sağlandığını mı ima ediyor? Eğer öyleyse, bunun amacı ne olabilir?
Gerçekten harika bir makale (ve kişisel olarak da tam zamanında; şu anda NSTextView'lerle uğraşıyorum). Bu bilgileri nasıl edindin? Başkasının kodu mu? Acı verici deneyimler mi? developer.apple.com mu?
DOM belgeleri çağında (ör. notion, gitbook), metni ayrıştırmak ve işlemek için sihirli işler yapmak adına sık sık attributed string kullanıyorum. Bu çok zarif bir yapı ve neden bu kadar az bilindiğini anlayamıyorum. Bu arada makale muhteşem.
Geçmişte sıfırdan kendi metin editörümü yazmaya çalışmıştım; o zamanlar böyle bir kaynak olsaydı gerçekten harika olurdu.
Uzun süre Android uygulama geliştiricisi olduğum için, Apple'ın meselelere biraz daha farklı ve daha özenli yaklaşımını görmek ilginç geldi. Android'de Layout sınıfı (ve alt sınıfları) düzen ve render ile ilgili her şeyi ele alır, TextView ise düzenleme/seçim mantığının bir kısmını uygular. EditText ile TextView arasındaki tek fark, EditText'in TextView'da zaten mevcut olan düzenleme özelliklerini "etkinleştirmesi"dir. Bu biraz bütünleşik yaklaşımın (ve kötü API'nin) sorunu, uygulamanızın metni nasıl render ettiği üzerinde daha fazla kontrole ihtiyaç duyarsanız şansınızın kalmamasıdır. Örneğin, yerleşim yapıldıktan sonra tek tek glyph'lere erişmek isteseniz? Hayır, üzgünüm.
TextEdit uygulaması neredeyse tamamen tek bir TextView'dan oluşuyor. Windows'taki karşılığının WordPad olduğunu düşünüyorum. O da RichEdit kontrolünü temel alıyor. Bir başka ilginç bilgi de şu: RTF, temelde NSAttributedString'in serileştirilmiş hâlidir. Aynısı Windows'un RichEdit kontrolü için de geçerlidir. Hatta Windows'taki uygulama önce gelmiş gibi görünüyor: https://en.wikipedia.org/wiki/Rich_Text_Format
Bu uygulamayı gerçekten çok seviyorum. obsidian ve ia Writer dahil diğer tüm Markdown uygulamalarının yerini aldı!
Neyse ki en azından birileri 2024'te hâlâ Cocoa kullanıyor.
Keşke iOS bileşenleri hakkında bunun gibi daha fazla dokümantasyon olsa!