<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<title>Snippets – FlineDev</title>
<description>Blog, apps, and open source Swift packages by indie developer Cihat Gündüz. Topics: SwiftUI, visionOS, error handling, localization, and more.</description>
<link>https://fline.dev/tr/snippets/</link>
<language>tr</language>
<atom:link href="https://fline.dev/tr/snippets/feed.xml" rel="self" type="application/rss+xml"/>
<item>
<title>Vapor&apos;un maximumActiveConnections Ayarı Worker Başına Değil, Event Loop Başınadır</title>
<link>https://fline.dev/tr/snippets/vapor-maximum-active-connections/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/vapor-maximum-active-connections/</guid>
<pubDate>Mon, 29 Dec 2025 00:00:00 +0000</pubDate>
<description><![CDATA[Gerçek bağlantı sayınız yapılandırdığınızı düşündüğünüz değeri aştığında aralıklı 500 hatalarına neden olabilecek, açık olmayan bir Vapor yapılandırma detayı.]]></description>
<content:encoded><![CDATA[<h2 id="yanıltıcı-yapılandırma">Yanıltıcı Yapılandırma</h2><p>Vapor’da bağlantı havuzlarını yapılandırırken – ister Redis, PostgreSQL veya diğer veritabanları için olsun – <code>maximumActiveConnections</code> adlı bir parametreyle karşılaşıyorsun. Doğal varsayım, bunun uygulamanın toplam maksimum bağlantısını ayarladığı. Ayarlamıyor. NIO <code>EventLoop</code> başına maksimumu ayarlıyor.</p><p>Bu ayrım production’da büyük önem taşıyor.</p><h2 id="beni-şaşırtan-hesap">Beni Şaşırtan Hesap</h2><p>Tipik bir sunucuda, Swift NIO her CPU çekirdeği için bir <code>EventLoop</code> oluşturuyor. Yani gerçek maksimum bağlantı sayısı:</p><pre><code>gerçek max = maximumActiveConnections * CPU çekirdekleri * dyno/instance sayısı</code></pre><p><code>maximumActiveConnections</code>‘ı 8 olarak yapılandırmıştım, Redis bağlantılarımı iki dyno’da makul bir 16 ile sınırladığımı düşünüyordum. Gerçek sayı:</p><pre><code>8 (event loop başına) * 8 (çekirdek) * 2 (dyno) = 128 potansiyel bağlantı</code></pre><p>Bu, hedeflenenden bir büyüklük sırası daha fazla ve trafik zirveleri sırasında Redis sağlayıcımın bağlantı limitini aşıyordu.</p><p><img src="https://fline.dev/assets/images/snippets/vapor-maximum-active-connections/code-screenshot.webp" alt="Code showing the connection pool configuration" loading="lazy" /></p><h2 id="belirtiler">Belirtiler</h2><p>Başarısızlık modu özellikle sinsi: sadece yük altında ortaya çıkan aralıklı 500 hataları. Normal trafik sırasında gerçek bağlantı limitine asla ulaşmıyorsun, bu yüzden her şey sorunsuz çalışıyor. Zirveler sırasında, bağlantılar tüm event loop’larda aynı anda birikiyor ve sağlayıcının limitini aşıyor. Hatalar rastgele görünüyor ve geliştirme makinelerinde genellikle daha az çekirdek olduğundan yerel olarak tekrarlamak zor.</p><h2 id="doğru-değeri-nasıl-hesaplarsın">Doğru Değeri Nasıl Hesaplarsın</h2><p>Sağlayıcının bağlantı limitini tüm instance’lardaki toplam event loop sayısına böl:</p><pre><code class="language-swift">// Provider limit: 40 connections
// 2 dynos * 8 cores = 16 event loops total
// 40 / 16 = 2.5, round down to 2

app.redis.configuration = .init(
   pool: .init(maximumActiveConnections: 2)
)</code></pre><p>Bu muhafazakar ayar, TranslateKit’teki aylardır beni şaşırtan uzun süredir devam eden nadir 500 hatalarını nihayet düzeltti. Her zaman bulut sağlayıcının bağlantı limitlerini kontrol et ve deploy etmeden önce çarpma işlemini yap.</p>]]></content:encoded>
</item>
<item>
<title>Apple Geri Bildirim İsteklerini Uyguluyor -- Rapor Göndermek İşe Yarıyor</title>
<link>https://fline.dev/tr/snippets/apple-implements-feedback-requests/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/apple-implements-feedback-requests/</guid>
<pubDate>Tue, 10 Jun 2025 00:00:00 +0000</pubDate>
<description><![CDATA[Xcode 26'da bir Feedback Assistant talebinin uygulanmasına dair kişisel bir deneyim ve etkili geri bildirim raporları yazmak için ipuçları.]]></description>
<content:encoded><![CDATA[<h2 id="geri-bildiriminiz-gerçekten-okunuyor">Geri Bildiriminiz Gerçekten Okunuyor</h2><p>Geliştirici topluluğunda yaygın bir inanış var: Feedback Assistant raporları (Radar’ın halefi) göndermek boşuna – raporlar bir boşluğa kaybolup hiçbir şey olmuyor. Benim bir özellik talebim Xcode 26’da uygulandı, bu da aksini kanıtlıyor.</p><p><img src="https://fline.dev/assets/images/snippets/apple-implements-feedback-requests/feedback-implemented.webp" alt="Screenshot showing the implemented feedback request" loading="lazy" /></p><p>İstediğin bir özelliğin bir keynote’ta veya sürüm notlarında görünmesi tatmin edici bir doğrulama. Ama daha da önemlisi, Apple’ın mühendislik ekiplerinin rapora doğrudan hiç yanıt vermese bile topluluk geri bildirimlerini gerçekten inceleyip önceliklendirdiğini gösteriyor.</p><h2 id="etkili-geri-bildirim-yazmak-için-i̇puçları">Etkili Geri Bildirim Yazmak için İpuçları</h2><p>Tüm raporlar eşit değil. İşte bir raporun eyleme geçirilebilir olma şansını artırdığını gördüğüm şeyler:</p><p><strong>Sorun hakkında spesifik ol.</strong> “Xcode yavaş” işe yaramaz. “Dosya 3’ten fazla <code>#Preview</code> bloğu içerdiğinde Xcode’un SwiftUI preview’ının yenilenmesi 12 saniye sürüyor” mühendislere araştırabilecekleri bir şey veriyor.</p><p><strong>Örnek bir proje ekle.</strong> Minimum düzeyde tekrarlama projesi ekleyebileceğin en değerli şey. Bir mühendis projeni build edip çalıştırarak sorunu görebiliyorsa, araştırma yapmasının önündeki en büyük engeli kaldırmış oluyorsun.</p><p><strong>Sadece çözümü değil, kullanım senaryosunu anlat.</strong> “X yapan bir buton ekleyin” yerine, neden ihtiyacın olduğunu açıkla: “Büyük SPM grafikleriyle çalışırken, bir dosyanın hangi target’a ait olduğunu hızlıca belirlemem gerekiyor çünkü…” Bu, ekibe doğru çözümü tasarlamaları için bağlam veriyor ki bu hayal ettiğinden farklı olabilir.</p><p><strong>Beta sezonunda bildir.</strong> WWDC’den sonraki haftalar, Apple’ın ekiplerinin yeni özellikler hakkında en aktif şekilde geri bildirim topladığı dönem. Bu zaman diliminde gönderilen raporlar, bir sürüm döngüsünün ortasında gönderilenlerden çok daha fazla ilgi görüyor.</p><h2 id="alışkanlık-haline-getir">Alışkanlık Haline Getir</h2><p>Her WWDC beta sezonunda, uygulamalarını yeni OS ve Xcode betalarına karşı test etmek için zaman ayır. Her sorun ve eksik özellik için rapor gönder. Çoğu yanıt almayacak, ama bazıları sessizce gelecek sürümleri etkileyecek.</p>]]></content:encoded>
</item>
<item>
<title>Button İçine Image Yerleştirmek Yerine .labelStyle(.iconOnly) Kullan</title>
<link>https://fline.dev/tr/snippets/labelstyle-icononly-swiftui/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/labelstyle-icononly-swiftui/</guid>
<pubDate>Sun, 12 Jan 2025 00:00:00 +0000</pubDate>
<description><![CDATA[Okunabilirlikten ödün vermeden erişilebilirliği koruyan, yalnızca simge butonları için doğru SwiftUI kalıbı.]]></description>
<content:encoded><![CDATA[<h2 id="frameworke-karşı-savaşmayı-bırak">Framework’e Karşı Savaşmayı Bırak</h2><p>SwiftUI kodlarında sürekli gördüğüm bir kalıp var: <code>Button</code>‘ın label closure’ına doğrudan <code>Image</code> koyarak elle yalnızca simge butonları oluşturmak. Görsel olarak işe yarıyor, ama erişilebilirlik bilgisini çöpe atıyor ve SwiftUI’ın tasarımına karşı çalışıyor.</p><h2 id="yanlış-yol">Yanlış Yol</h2><pre><code class="language-swift">Button {
   toggleSidebar()
} label: {
   Image(systemName: &quot;sidebar.left&quot;)
}</code></pre><p>Bu, dokunulabilir bir simge render ediyor, ama VoiceOver’ın duyuracak anlamlı bir etiketi yok. Kullanıcı “button” veya ham SF Symbol adı gibi bir şey duyuyor ki bu yardımcı değil.</p><h2 id="doğru-yol">Doğru Yol</h2><pre><code class="language-swift">Button(&quot;Toggle Sidebar&quot;, systemImage: &quot;sidebar.left&quot;) {
   toggleSidebar()
}
.labelStyle(.iconOnly)</code></pre><p>Veya açıkça <code>Label</code> kullanarak:</p><pre><code class="language-swift">Button(action: toggleSidebar) {
   Label(&quot;Toggle Sidebar&quot;, systemImage: &quot;sidebar.left&quot;)
}
.labelStyle(.iconOnly)</code></pre><p><img src="https://fline.dev/assets/images/snippets/labelstyle-icononly-swiftui/code-comparison.webp" alt="Code comparison showing the wrong way versus the right way" loading="lazy" /></p><h2 id="neden-önemlidir">Neden Önemlidir</h2><p><code>Label</code> view’ı hem bir başlık hem de bir simge taşıyor. <code>.labelStyle(.iconOnly)</code> uyguladığında, SwiftUI başlığı görsel olarak gizliyor ama erişilebilirlik ağacında koruyor. VoiceOver “Toggle Sidebar, button” diye duyuracak – tam olarak kullanıcının duyması gereken şey.</p><p>Bu kalıp aynı zamanda kodunu daha esnek yapıyor. Daha sonra simgenin yanında metin göstermeye karar verirsen (örneğin iPad’de bir araç çubuğunda), label stilini <code>.titleAndIcon</code> olarak değiştirmen yeterli. Yeniden yapılandırma gerekmiyor.</p><h2 id="butonların-ötesinde">Butonların Ötesinde</h2><p>Aynı prensip <code>Label</code> kabul eden her view için geçerli: <code>NavigationLink</code>, <code>Toggle</code>, <code>Picker</code>, menü öğeleri. Çıplak bir <code>Image</code> kullanmak istediğinde, stili modifier ile bir <code>Label</code>’ın daha uygun olup olmayacağını kendine sor. Neredeyse her durumda, öyle.</p>]]></content:encoded>
</item>
<item>
<title>Her SwiftPM Paketi için EditorConfig</title>
<link>https://fline.dev/tr/snippets/editorconfig-swiftpm-package/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/editorconfig-swiftpm-package/</guid>
<pubDate>Tue, 03 Dec 2024 00:00:00 +0000</pubDate>
<description><![CDATA[Her Swift paketinin tüm katkıda bulunanlar arasında tutarlı girintilemeyi sağlamak için neden bir .editorconfig dosyası içermesi gerektiği.]]></description>
<content:encoded><![CDATA[<h2 id="görünmez-biçimlendirme-sorunu">Görünmez Biçimlendirme Sorunu</h2><p>Birden fazla kişi bir Swift paketine katkıda bulunduğunda, girintileme tutarsızlıkları sızıyor. Bir katkıcı 4 boşluk kullanıyor, bir diğeri tab kullanıyor, üçüncüsü 2 boşluk kullanıyor. Pull request’ler sadece boşluk değişiklikleriyle gürültülü hale geliyor ve kod tabanı tutarsız bir karmaşaya doğru kayıyor. Çözüm, eklemesi 30 saniye süren tek bir dosya.</p><h2 id="editorconfig-standardı">.editorconfig Standardı</h2><p>EditorConfig, proje bazında kodlama stili ayarlarını tanımlamak için yaygın olarak desteklenen bir standart. Xcode <code>.editorconfig</code> dosyalarına saygı gösteriyor, böylece katkıcılar projeyi açtıklarında otomatik olarak doğru girintileme ayarlarını alıyor – elle yapılandırma yok, okunacak dokümantasyon yok.</p><p>İşte her SwiftPM paketi için önerdiğim <code>.editorconfig</code>:</p><pre><code>root = true

[*.swift]
indent_style = space
indent_size = 3

[*.{yml,yaml,json}]
indent_style = space
indent_size = 2</code></pre><p>Swift için 3 boşluk girintileme bilinçli bir tercih. 2 veya 4 boşluktan daha az yaygın, ama iyi bir denge noktası: iç içe closure’lar için 2 boşluktan daha okunabilir, yatay alanı 4 boşluktan daha az israf ediyor. Bir kez denediğinde, standart seçenekler ya çok sıkışık ya da çok dağınık hissetmeye başlıyor.</p><h2 id="neden-global-ayarları-geçiyor">Neden Global Ayarları Geçiyor</h2><p>Her geliştiricinin genel olarak yapılandırılmış kendi Xcode girintileme tercihleri var. <code>.editorconfig</code> olmadan, bu genel ayarlar açtıkları her projeye uygulanıyor. Bu, 4 boşluk tab’lı bir katkıcının bir dosyayı düzenlerken sessizce kodu yeniden biçimlendireceği anlamına geliyor, proje kuralı farklı olsa bile.</p><p>Depo kökünde <code>.editorconfig</code> ile Xcode, genel ayarları projeye özel olanlarla geçersiz kılıyor. Katkıcıların hiçbir şeyi değiştirmesi gerekmiyor – sadece çalışıyor.</p><h2 id="benimseme">Benimseme</h2><p>Bu dosyayı paket köküne bırak ve commit et. Hepsi bu. Build adımı yok, bağımlılık yok, dosyanın kendisi dışında yapılandırma yok. Çoğu modern editör (VS Code, Vim, Sublime Text) de EditorConfig destekliyor, bu yüzden Xcode kullanmayan katkıcılar da faydalanıyor.</p>]]></content:encoded>
</item>
<item>
<title>App Store Değerlendirmeleri için Push Bildirimleri</title>
<link>https://fline.dev/tr/snippets/push-notifications-app-store-reviews/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/push-notifications-app-store-reviews/</guid>
<pubDate>Thu, 28 Nov 2024 00:00:00 +0000</pubDate>
<description><![CDATA[Kullanıcı geri bildirimlerine hızlı yanıt verebilmen için App Store Connect uygulamasında yeni App Store değerlendirmeleri için push bildirimlerini nasıl etkinleştireceğin.]]></description>
<content:encoded><![CDATA[<h2 id="app-store-connectte-gizli-bir-özellik">App Store Connect’te Gizli Bir Özellik</h2><p>App Store Connect iOS uygulamasının çoğu geliştiricinin hiç keşfetmediği bir özelliği var: yeni kullanıcı değerlendirmeleri için push bildirimleri. Varsayılan olarak kapalı ve her uygulama için ayrı ayrı etkinleştirmen gerekiyor, bu yüzden muhtemelen bu kadar az kişi biliyor.</p><h2 id="nasıl-etkinleştirilir">Nasıl Etkinleştirilir</h2><p>iPhone’unda App Store Connect uygulamasını aç, sonra şuraya git:</p><ol><li><p>Profil simgene dokun veya <strong>Settings</strong>’e git</p></li><li><p><strong>Notifications</strong> seçeneğini seç</p></li><li><p>Tüm uygulamalarının bir listesini göreceksin</p></li><li><p>Her uygulama için <strong>Customer Reviews</strong> seçeneğini aç</p></li></ol><p>Bu kadar. Bundan sonra, birisi o uygulama için yeni bir değerlendirme bıraktığında push bildirimi alacaksın.</p><p><video src="https://fline.dev/assets/images/snippets/push-notifications-app-store-reviews/demo.mp4" controls muted playsinline></video></p><h2 id="bağımsız-geliştiriciler-i̇çin-neden-önemlidir">Bağımsız Geliştiriciler İçin Neden Önemlidir</h2><p>App Store değerlendirmelerine hızlı yanıt vermenin somut bir etkisi var. Bir kullanıcı bir hata hakkında olumsuz değerlendirme bıraktığında, sorunu kabul eden (veya bir çözüme yönlendiren) hızlı bir yanıt, kullanıcının puanını güncellemesine yol açabiliyor. Olumlu değerlendirmeler de takdiri hak ediyor – kullanıcıları geri bildirim vermeye devam etmeye teşvik ediyor.</p><p>Bildirimler olmadan, çoğu geliştirici değerlendirmeleri ancak hatırladığında kontrol ediyor ki bu günler veya haftalar sonra olabiliyor. O zamana kadar kullanıcı çoktan unutmuş oluyor ve yanıtın sonradan akla gelen bir şey gibi hissettiriyor.</p><h2 id="bir-uyarı-notu">Bir Uyarı Notu</h2><p>Yüksek değerlendirme hacmine sahip birden fazla uygulamanın varsa, hepsi için bunu etkinleştirmek gürültülü olabilir. En önemli uygulamalarınla başla ve gerçekte ne kadar bildirim aldığına göre ayarla. Birkaç uygulaması olan çoğu bağımsız geliştirici için hacim gayet yönetilebilir ve faydaları anında.</p>]]></content:encoded>
</item>
<item>
<title>DocC Belgelerinde Videolar ve Sekmeler</title>
<link>https://fline.dev/tr/snippets/docc-videos-tabs-documentation/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/docc-videos-tabs-documentation/</guid>
<pubDate>Thu, 20 Jun 2024 00:00:00 +0000</pubDate>
<description><![CDATA[Dokümantasyonunu daha etkileşimli yapan, az bilinen iki DocC özelliği: gömülü videolar ve sekmeli içerik navigasyonu.]]></description>
<content:encoded><![CDATA[<h2 id="doccde-temel-markdownın-ötesinde">DocC’de Temel Markdown’ın Ötesinde</h2><p>Çoğu geliştirici DocC’nin standart markdown desteklediğini bilir, ama şaşırtıcı derecede az kullanılan iki güçlü direktif var: video gömme ve sekmeli içerik. Her ikisi de Xcode’un dokümantasyon görüntüleyicisinde ve barındırılan DocC web sitelerinde çalışıyor.</p><h2 id="video-gömme">Video Gömme</h2><p>Dokümantasyonuna video eklemek tek bir direktifle yapılıyor:</p><pre><code>@Video(source: &quot;setup-walkthrough.mp4&quot;)</code></pre><p>Video dosyasını dokümantasyon kataloğunun Resources klasörüne yerleştir. Bu, dokümantasyonun içinde doğrudan satır içi bir video oynatıcısı olarak render ediyor; harici bir URL’ye bağlantı vermekten veya görsel bir süreci metin olarak anlatmaktan çok daha etkili. Kurulum rehberleri, UI yürüyüşleri veya animasyon gösterimleri için iyi çalışıyor.</p><h2 id="tabnavigator-ile-sekmeli-i̇çerik">TabNavigator ile Sekmeli İçerik</h2><p>Alternatif yaklaşımlar veya platforma özel talimatlar göstermen gerektiğinde, sekmeler okuyucuyu bunaltmadan şeyleri düzenli tutuyor:</p><pre><code>@TabNavigator {
   @Tab(&quot;SwiftUI&quot;) {
      Use the `.environment` modifier to inject dependencies.
   }
   @Tab(&quot;UIKit&quot;) {
      Override `viewDidLoad` and configure your dependencies there.
   }
}</code></pre><p>Bu, okuyucuların bölümler arasında geçiş yapabildiği düzgün bir sekmeli arayüz olarak render ediyor. Birden fazla platformu, API sürümlerini veya yapılandırma yaklaşımlarını kapsayan dokümantasyon için özellikle yararlı.</p><p><video src="https://fline.dev/assets/images/snippets/docc-videos-tabs-documentation/demo.mp4" controls muted playsinline></video></p><h2 id="pratik-tavsiyeler">Pratik Tavsiyeler</h2><p>Contributing rehberimi bu iki özelliği de kullanacak şekilde güncelledim ve sonuç bir metin duvarından belirgin şekilde daha yaklaşılabilir oldu. Video, paragraflarla anlatılması gereken kurulum sürecini gösteriyor ve sekmeler platforma özel adımları temiz bir şekilde ayırıyor.</p><p>Bu direktifler Apple’ın <a href="https://www.swift.org/documentation/docc/video">DocC dokümantasyonunda</a> belgelenmiş ama öğreticilerde nadiren bahsedilmiş. Açık kaynak bir Swift paketi sürdürüyorsan, bunları dokümantasyon kataloğuna eklemeyi düşün – insanların dokümanlarını nasıl deneyimlediğinde gerçek bir fark yaratıyorlar.</p>]]></content:encoded>
</item>
<item>
<title>Mevcut Kullanıcıları Etkilemeden Ücretli Uygulamaları Freemium&apos;a Dönüştür</title>
<link>https://fline.dev/tr/snippets/convert-paid-apps-freemium/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/convert-paid-apps-freemium/</guid>
<pubDate>Thu, 28 Mar 2024 00:00:00 +0000</pubDate>
<description><![CDATA[Daha önce ödeme yapmış kullanıcıların erişimini koruyarak ücretli uygulamadan freemium'a geçiş için StoreKit'in AppTransaction API'sini nasıl kullanacağın.]]></description>
<content:encoded><![CDATA[<h2 id="ücretliden-freemiuma-geçiş-sorunu">Ücretliden Freemium’a Geçiş Sorunu</h2><p>Ücretli bir uygulamayı freemium’a geçirmek yaygın bir iş kararı, ama bir adalet sorunu ile geliyor: uygulama için daha önce ödeme yapmış kullanıcılar aniden özellikleri kaybetmemeli veya tekrar ödeme yapmaları istenmemeli. StoreKit’in <code>AppTransaction</code> API’si bunu temiz bir şekilde çözüyor.</p><h2 id="satın-alma-geçmişini-kontrol-etmek-için-apptransaction-kullanımı">Satın Alma Geçmişini Kontrol Etmek için AppTransaction Kullanımı</h2><p>Anahtar, uygulamanın orijinal işlemi hakkında bilgi sağlayan <code>AppTransaction.shared</code>. Spesifik olarak, <code>originalAppVersion</code> kullanıcının uygulamayı ilk indirdiği sürümü söylüyor. Eğer o sürüm ücretli bir sürümdüyse, kullanıcının zaten ödeme yaptığını biliyorsun.</p><pre><code class="language-swift">import StoreKit

func shouldGrantFullAccess() async -&gt; Bool {
   do {
      let result = try await AppTransaction.shared
      if case .verified(let transaction) = result {
         let originalVersion = transaction.originalAppVersion
         // Version &quot;2.0&quot; was when the app went freemium
         if originalVersion.compare(&quot;2.0&quot;, options: .numeric) == .orderedAscending {
            return true // User purchased before freemium transition
         }
      }
   } catch {
      // Handle verification failure
   }
   return false
}</code></pre><p>Mantık basit: kullanıcının <code>originalAppVersion</code> değerini freemium geçişini yaptığın sürümle karşılaştır. Orijinal sürümleri değişiklikten önceyse, otomatik olarak tam erişim ver.</p><h2 id="önemli-ayrıntılar">Önemli Ayrıntılar</h2><p><code>originalAppVersion</code>, orijinal satın alma (veya ücretsiz uygulamalar için indirme) sırasındaki <code>CFBundleShortVersionString</code> değerine karşılık geliyor. Geçiş noktanı tam olarak hangi sürüm numarasının işaretlediğini bildiğinden emin ol.</p><p>Bu yaklaşım sunucu altyapısı ve migrasyon kodu gerektirmiyor. StoreKit, doğrulamayı App Store makbuz zinciri üzerinden yapıyor, bu yüzden kontrol kurcalamaya karşı dayanıklı. Apple bu kalıbı <a href="https://developer.apple.com/documentation/storekit/apptransaction/3954437-originalappversion">iş modeli geçişi için orijinal API</a> belgesinde dokümante ediyor.</p><p>TestFlight ve simülatör testleri için, <code>originalAppVersion</code> bunun yerine <code>CFBundleVersion</code> (build numarası) döndürüyor, bu yüzden test senaryolarını buna göre planla.</p>]]></content:encoded>
</item>
<item>
<title>Kenar Çubuğunda Xcode Quick Help</title>
<link>https://fline.dev/tr/snippets/xcode-quick-help-sidebar/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/xcode-quick-help-sidebar/</guid>
<pubDate>Mon, 25 Mar 2024 00:00:00 +0000</pubDate>
<description><![CDATA[Xcode'un kenar çubuğundaki Quick Help inspector'ı, imlecin hareket ettikçe dokümantasyonu otomatik güncelliyor ve dokümanlar için Cmd-click yapma ihtiyacını ortadan kaldırıyor.]]></description>
<content:encoded><![CDATA[<h2 id="gözden-kaçan-bir-özellik">Gözden Kaçan Bir Özellik</h2><p>Yıllardır Xcode’da dokümantasyon kontrol etme iş akışım hep aynıydı: bir sembole Cmd-click yap, bağlam menüsünden “Show Quick Help” seç, popup’ı oku, sonra kapat ve kodlamaya devam et. Çalışıyor, ama kesintiye uğratıcı – her arama üç eylem gerektiriyor ve düzenleme akışını bozuyor.</p><p>Sonra yanlışlıkla sağ kenar çubuğundaki Quick Help inspector panelini keşfettim.</p><p><video src="https://fline.dev/assets/images/snippets/xcode-quick-help-sidebar/demo.mp4" controls muted playsinline></video></p><h2 id="nasıl-çalışır">Nasıl Çalışır</h2><p>Quick Help inspector’ı Option+Cmd+3 ile aç veya View &gt; Inspectors &gt; Quick Help’e git. Bu, sağ kenar çubuğunda imlecinin şu anda üzerinde olduğu sembolün dokümantasyonunu gösteren bir panel açıyor. Kodunda imlecini hareket ettirdikçe – bir metoda tıklama, parametreler arasında ok tuşlarıyla gezme, bir tür seçme – kenar çubuğu otomatik güncelleniyor.</p><p>Tıklama yok, kapatılacak popup yok, kesinti yok. Sadece kodlamaya devam ediyorsun ve ilgili dokümantasyon seni takip ediyor.</p><h2 id="cmd-clickten-neden-üstündür">Cmd-Click’ten Neden Üstündür</h2><p>Cmd-click yaklaşımının belirli bir maliyeti var: bakmadan önce “bunun için dokümana ihtiyacım var” diye karar vermen gerekiyor. Kenar çubuğu bunu tersine çeviriyor. Her zaman görünür olduğu için, dokümantasyonu pasif olarak özümsüyorsun. Parametre açıklamalarını, dönüş türlerini, kullanımdan kaldırma uyarılarını ve kullanılabilirlik notlarını bilinçli bir çaba harcamadan fark ediyorsun.</p><p>Bu özellikle alışık olmadığın API’lerle çalışırken değerli. Her ikinci sembole Cmd-click yapmak yerine, imlecini kodda gezdirip kenar çubuğunu okuyorsun. Dokümantasyon aramasını ayrı bir eylemden sürekli bir akışa dönüştürüyor.</p><p>Panel, Quick Help popup’ı ile aynı içeriği gösteriyor: tanımlama, açıklama, parametreler, dönüş değeri, kullanılabilirlik ve ilgili semboller. Tek fark, belirir ve kaybolmak yerine kalıcı olması ve yerinde güncellenmesi.</p><p>Sağ kenar çubuğu için ekran alanın varsa, kodlarken Quick Help’i açık tutmak zamanla birikerek fark yaratan küçük iş akışı değişikliklerinden biri.</p>]]></content:encoded>
</item>
<item>
<title>SwiftUI&apos;da AsyncButton Oluşturma</title>
<link>https://fline.dev/tr/snippets/asyncbutton-swiftui-progress-status/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/asyncbutton-swiftui-progress-status/</guid>
<pubDate>Wed, 27 Sep 2023 00:00:00 +0000</pubDate>
<description><![CDATA[Otomatik yükleme durumu, devre dışı bırakma ve başarı/başarısızlık gösterimi ile asenkron işlemleri yöneten yeniden kullanılabilir bir buton bileşeni.]]></description>
<content:encoded><![CDATA[<h2 id="asyncbuttona-duyulan-i̇htiyaç">AsyncButton’a Duyulan İhtiyaç</h2><p>Standart SwiftUI <code>Button</code> eylemleri senkrondur. Asenkron bir işlem yapman gerektiğinde – bir ağ isteği, veritabanı yazımı, StoreKit satın alımı – elle bir <code>Task</code> yönetmek, yükleme durumunu takip etmek, butonu devre dışı bırakmak ve hataları ele almak zorunda kalıyorsun. Bu kalıp kod, uygulamandaki her asenkron butonda tekrarlanıyor.</p><p>Tüm bunları tek bir yeniden kullanılabilir view’da saran bir <code>AsyncButton</code> bileşeni oluşturdum.</p><p><video src="https://fline.dev/assets/images/snippets/asyncbutton-swiftui-progress-status/demo.mp4" controls muted playsinline></video></p><h2 id="basitleştirilmiş-bir-uygulama">Basitleştirilmiş Bir Uygulama</h2><p>İşte temel fikir:</p><pre><code class="language-swift">struct AsyncButton&lt;Label: View&gt;: View {
   let action: () async throws -&gt; Void
   let label: () -&gt; Label

   @State private var isRunning = false
   @State private var result: Result&lt;Void, Error&gt;?

   var body: some View {
      Button {
         isRunning = true
         Task {
            do {
               try await action()
               result = .success(())
            } catch {
               result = .failure(error)
            }
            isRunning = false
         }
      } label: {
         HStack(spacing: 8) {
            label()
            if isRunning {
               ProgressView()
            }
         }
      }
      .disabled(isRunning)
   }
}</code></pre><p>Buton dahili olarak bir <code>Task</code> oluşturuyor, böylece çağıranlar action closure’ında doğrudan <code>await</code> kullanabiliyor. Task çalışırken, etiketin yanında bir <code>ProgressView</code> görünüyor ve mükerrer gönderileri önlemek için buton devre dışı bırakılıyor. <code>result</code> state’i başarı veya başarısızlık göstergelerini – bir onay işareti, bir renk flaşı veya bir sallama animasyonu – yönlendirebilir.</p><h2 id="kullanım">Kullanım</h2><p>Kullanımı doğal hissettiriyor:</p><pre><code class="language-swift">AsyncButton {
   try await viewModel.submitOrder()
} label: {
   Text(&quot;Place Order&quot;)
}</code></pre><p>Elle state yönetimi yok, çağrı noktasında <code>Task</code> oluşturma yok. <a href="https://github.com/FlineDev/HandySwiftUI">HandySwiftUI</a> paketindeki tam implementasyon yapılandırılabilir başarı/başarısızlık animasyonları, özelleştirilebilir ilerleme göstergeleri ve buton stilleri desteği ekliyor. Ama yukarıdaki temel kalıp en yaygın durumu kapsıyor ve kendi projelerine uyarlaması kolay.</p>]]></content:encoded>
</item>
<item>
<title>ImageRenderer UIKit Destekli View&apos;ları Dışa Aktaramaz</title>
<link>https://fline.dev/tr/snippets/imagerenderer-uikit-backed-views/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/imagerenderer-uikit-backed-views/</guid>
<pubDate>Tue, 19 Sep 2023 00:00:00 +0000</pubDate>
<description><![CDATA[SwiftUI'ın ImageRenderer'ı, List ve ScrollView gibi UIKit veya AppKit kullanarak oluşturulan view'larda sessizce başarısız oluyor.]]></description>
<content:encoded><![CDATA[<h2 id="kısıtlama">Kısıtlama</h2><p>SwiftUI’ın <code>ImageRenderer</code>‘ı herhangi bir SwiftUI view’ını <code>UIImage</code> veya <code>CGImage</code>‘a dönüştürmeye olanak tanıyor. Saf SwiftUI view’larında iyi çalışıyor, ama view ağacında UIKit veya AppKit tarafından desteklenen bileşenler olduğunda sessizce başarısız oluyor – boş veya eksik bir görsel üretiyor. Bu, yaygın olarak kullanılan birçok view’ı kapsıyor:</p><ul><li><p><code>List</code> (UITableView / NSTableView sarmalıyor)</p></li><li><p><code>ScrollView</code> (UIScrollView / NSScrollView sarmalıyor)</p></li><li><p><code>TextEditor</code> (UITextView / NSTextView sarmalıyor)</p></li><li><p><code>Map</code> (MKMapView sarmalıyor)</p></li></ul><p>Herhangi bir derleyici uyarısı veya çalışma zamanı hatası yok. Renderer sadece view hiyerarşisinin o kısımlarını yakalamıyor.</p><h2 id="geçici-çözüm">Geçici Çözüm</h2><p>Liste benzeri bir düzeni görsel olarak export etmem gerektiğinde, çözüm <code>List</code>’i <code>VStack</code> ve manuel stillendirmeden oluşan saf bir SwiftUI karşılığıyla değiştirmek oldu:</p><pre><code class="language-swift">let exportView = VStack(spacing: 0) {
   ForEach(items) { item in
      HStack {
         Text(item.name)
         Spacer()
         Text(item.value)
            .foregroundStyle(.secondary)
      }
      .padding(.horizontal, 16)
      .padding(.vertical, 12)

      if item.id != items.last?.id {
         Divider()
      }
   }
}
.background(.white)
.frame(width: 390)

let renderer = ImageRenderer(content: exportView)
renderer.scale = UIScreen.main.scale

if let image = renderer.uiImage {
   // Use the rendered image
}</code></pre><p><code>ForEach</code> ile <code>VStack</code>, UIKit destekli herhangi bir view’a bağlı kalmadan <code>List</code>’in görsel yapısını kopyalıyor. Ayırıcılar, dolgu ve arka plan eklemek, export amaçları için standart bir listeye yeterince yakın bir sonuç üretiyor.</p><h2 id="pratik-tavsiye">Pratik Tavsiye</h2><p>Uygulamanda <code>ImageRenderer</code> kullanmayı planlıyorsan, export edilecek view’larını en başından bu kısıtlamayı göz önünde bulundurarak tasarla. Bunları temel SwiftUI bileşenlerinden oluştur: stack’ler, metin, şekiller ve görseller. Platform-özel bir kontrolü sardığını bildiğin herhangi bir view’dan kaçın. Render çıktısını erken test etmek, daha sonra boş bölgeler keşfetmenin hayal kırıklığından kurtarıyor.</p>]]></content:encoded>
</item>
<item>
<title>Swift Import&apos;larını Sarmalayıcı Modülle Birleştir</title>
<link>https://fline.dev/tr/snippets/combine-swift-imports-wrapper-module/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/combine-swift-imports-wrapper-module/</guid>
<pubDate>Wed, 13 Sep 2023 00:00:00 +0000</pubDate>
<description><![CDATA[@_exported import kullanarak sık kullandığın tüm framework'leri yeniden export eden tek bir import oluştur.]]></description>
<content:encoded><![CDATA[<h2 id="tekrarlayan-import-sorunu">Tekrarlayan Import Sorunu</h2><p>Orta büyüklükteki herhangi bir Swift projesinde, neredeyse her dosyanın başında aynı import setini yazıyorsun. Foundation, SwiftUI, OSLog, belki Observation – yeni framework’ler benimsedikçe liste büyüyor. OSLog üzerinden yapılandırılmış loglama’ya geçişle birlikte, kendimi neredeyse her dosyaya alışılagelen isimlerin yanına <code>import OSLog</code> eklerken buldum.</p><p>Çözüm, sık ihtiyaç duyduğun her şeyi tek bir import üzerinden yeniden export eden bir wrapper modül.</p><h2 id="wrapper-modülü-kurma">Wrapper Modülü Kurma</h2><p>Swift paketinde veya Xcode projesinde yeni bir target oluştur. Benim durumumda adını <code>AppFoundation</code> koydum. Modülün tamamı tek bir dosyadan oluşuyor:</p><pre><code class="language-swift">// Sources/AppFoundation/Exports.swift
@_exported import Foundation
@_exported import SwiftUI
@_exported import OSLog
@_exported import Observation</code></pre><p><code>@_exported</code> attribute’u, her framework’ten tüm public sembolleri <code>AppFoundation</code>’ı import eden herhangi bir dosyaya erişilebilir yapıyor. Artık uygulamandaki her dosyanın sadece şuna ihtiyacı var:</p><pre><code class="language-swift">import AppFoundation</code></pre><p><code>Package.swift</code> dosyanda, target’ın export dosyası dışında kendi kaynak kodu yok. Uygulama target’ın <code>AppFoundation</code>‘a bağımlılık tanımlıyor ve yeniden export edilen tüm framework’ler her yerde kullanılabilir oluyor.</p><h2 id="göz-önünde-bulundurulacak-ödünler">Göz Önünde Bulundurulacak Ödünler</h2><p>Bu yaklaşımın açık faydaları var: daha az kalıp kod, import bölümlerinde daha az merge çakışması ve yeni framework import’ları eklemek için tek bir yer. Ama ödünler de var.</p><p>Birincisi, <code>@_exported</code> alt çizgili bir attribute, yani resmi olarak stabil Swift API’sinin parçası değil. Pratikte yıllardır stabil ve ekosistemde yaygın olarak kullanılıyor, ama resmi bir garanti taşımıyor.</p><p>İkincisi, örtük bağımlılıklar bir dosyanın gerçekte ne kullandığını anlamayı zorlaştırabilir. Her dosyanın her şeye erişimi olduğunda, açık import’ların dokümantasyon değerini kaybediyorsun. Daha sonra bir modülü bağımsız bir pakete çıkarırsan, açık import’ları geri eklemen gerekecek.</p><p>Kolaylığın katı modülerlikten daha önemli olduğu uygulama target’ları için, wrapper modül kalıbı gerçek zaman kazandırıyor. Yeniden kullanılabilir kütüphaneler için ise açık import’lar daha iyi bir seçim olmaya devam ediyor.</p>]]></content:encoded>
</item>
<item>
<title>SwiftUI Navigasyon: View Değil, Veri Sun</title>
<link>https://fline.dev/tr/snippets/swiftui-navigation-present-data/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/swiftui-navigation-present-data/</guid>
<pubDate>Thu, 27 Jul 2023 00:00:00 +0000</pubDate>
<description><![CDATA[UIKit'teki imperatif navigasyondan SwiftUI'daki veri odaklı navigasyona zihinsel model değişimini anlama.]]></description>
<content:encoded><![CDATA[<h2 id="zihinsel-model-değişimi">Zihinsel Model Değişimi</h2><p>UIKit’te navigasyon imperatiftir. Sisteme tam olarak ne yapacağını söylersin:</p><pre><code class="language-swift">let detailVC = DetailViewController()
detailVC.item = selectedItem
navigationController?.pushViewController(detailVC, animated: true)</code></pre><p>Bir view controller oluşturursun, yapılandırırsın ve yığına itersin. Eylemi sen kontrol edersin.</p><p>SwiftUI farklı çalışıyor. Navigasyon yapmıyorsun – verileri yeni view’larda sunuyorsun. Her şey veri odaklı. View’ları kontrol etmiyorsun. Verileri kontrol ediyorsun.</p><h2 id="veri-odaklı-navigasyon-pratikte">Veri Odaklı Navigasyon Pratikte</h2><p><code>NavigationStack</code> ile navigasyon state tarafından yönlendiriliyor. Hangi verinin hangi view’a karşılık geldiğini tanımlıyorsun, geçişleri SwiftUI hallediyor:</p><pre><code class="language-swift">struct ContentView: View {
   @State private var path: [Item] = []

   var body: some View {
      NavigationStack(path: $path) {
         List(items) { item in
            Button(item.name) {
               path.append(item)  // Modify data, not views
            }
         }
         .navigationDestination(for: Item.self) { item in
            DetailView(item: item)
         }
      }
   }
}</code></pre><p>Kilit satır <code>path.append(item)</code>. Bir view itmiyorsun. Bir diziye veri ekliyorsun. SwiftUI değişikliği gözlemliyor ve karşılık gelen view’ı otomatik olarak sunuyor.</p><h2 id="bu-neden-önemli">Bu Neden Önemli</h2><p>Bu ayrım sadece felsefi değil – pratik sonuçları var. Navigasyon state olduğu için, doğru path dizisini oluşturarak deep linking’i bedavaya alıyorsun. Path’i kaydederek navigasyon state’ini kalıcı hale getirebilir ve geri yükleyebilirsin. Aynı anda birden fazla öğe ekleyerek programatik olarak herhangi bir derinliğe gidebilirsin.</p><p>Bu aynı zamanda kapatmanın sadece veri silme olduğu anlamına geliyor. <code>path.removeLast()</code> çağrısı en üstteki view’ı kaldırıyor. Diziyi temizlemek köke döndürüyor. View controller referanslarını takip etmeye veya navigasyon hiyerarşisinde dolaşmaya gerek yok.</p><p>Bu değişimi içselleştirmek zaman alıyor, özellikle yıllarca UIKit deneyimin varsa. Ama bir kez oturduğunda, SwiftUI navigasyonu çok daha tahmin edilebilir hale geliyor. View’ların verilerinin saf fonksiyonları oluyor ve navigasyon da o verinin sadece bir parçası.</p>]]></content:encoded>
</item>
<item>
<title>AsyncImage .resizable()&apos;ı Desteklemiyor</title>
<link>https://fline.dev/tr/snippets/asyncimage-resizable-modifier/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/asyncimage-resizable-modifier/</guid>
<pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
<description><![CDATA[SwiftUI'ın AsyncImage'ı .resizable() modifier'ını desteklemiyor, bu yüzden phase tabanlı bir çözüm gerekiyor.]]></description>
<content:encoded><![CDATA[<h2 id="sorun">Sorun</h2><p>SwiftUI’ın <code>AsyncImage</code>‘ı uzak görselleri yüklemek için kullanışlı, ama şaşırtıcı bir sınırlaması var: <code>.resizable()</code> modifier’ını uygulayamıyorsun. Bu kod derleniyor ama beklendiği gibi çalışmıyor:</p><pre><code class="language-swift">// This does NOT work as intended
AsyncImage(url: imageURL)
   .resizable()  // Has no effect -- AsyncImage is not an Image
   .aspectRatio(contentMode: .fill)
   .frame(width: 200, height: 200)</code></pre><p>Nedeni, <code>AsyncImage</code>‘ın bir <code>Image</code> olmaması – yükleme durumunu yöneten bir konteyner view. <code>.resizable()</code> modifier’ı sadece <code>Image</code> üzerinde tanımlı, bu yüzden onu <code>AsyncImage</code>’a uygulamak sadece genel <code>View</code> versiyonunu çağırıyor ki o da işe yaramıyor.</p><h2 id="çözüm">Çözüm</h2><p>Çözüm, yükleme tamamlandıktan sonra alttaki <code>Image</code> değerine doğrudan erişim sağlayan phase tabanlı başlatıcıyı kullanmak:</p><pre><code class="language-swift">AsyncImage(url: imageURL) { phase in
   switch phase {
   case .success(let image):
      image
         .resizable()
         .aspectRatio(contentMode: .fill)
   case .failure:
      Image(systemName: &quot;photo&quot;)
         .foregroundStyle(.secondary)
   case .empty:
      ProgressView()
   @unknown default:
      EmptyView()
   }
}
.frame(width: 200, height: 200)
.clipped()</code></pre><p><code>.success</code> durumunun içinde, <code>image</code> gerçek bir <code>Image</code> değeri, bu yüzden <code>.resizable()</code> doğru çalışıyor. Bu ayrıca yükleme ve hata durumları üzerinde kontrol sağlıyor ki bu zaten daha iyi bir uygulama.</p><h2 id="ne-zaman-manuel-yüklenir">Ne Zaman Manuel Yüklenir</h2><p>Ham görsel verisine ihtiyacın varsa – örneğin önbelleğe almak, boyutunu incelemek veya bir <code>UIImage</code> oluşturmak için – <code>AsyncImage</code>’ı tamamen atlayıp <code>URLSession</code> ile yüklemek isteyebilirsin. Ama çoğu sadece görüntüleme amaçlı durum için, phase tabanlı başlatıcı ekstra karmaşıklık olmadan ihtiyacı karşılıyor.</p><p>Bu, basit başlatıcının çekici göründüğü ama pratikte yetersiz kaldığı SwiftUI API’lerinden biri. Görsel-özel modifier’lara ihtiyacın olduğunda varsayılan olarak phase tabanlı versiyonu kullan.</p>]]></content:encoded>
</item>
<item>
<title>Xcode 15&apos;te Ctrl+M ile Çok Satırlı Kod</title>
<link>https://fline.dev/tr/snippets/multi-line-code-ctrl-m-xcode-15/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/multi-line-code-ctrl-m-xcode-15/</guid>
<pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
<description><![CDATA[Xcode 15, fonksiyon çağrılarını ve parametreleri birden fazla satıra genişletmek için Ctrl+M kısayolu sunuyor.]]></description>
<content:encoded><![CDATA[<h2 id="kodu-birden-fazla-satıra-genişletme">Kodu Birden Fazla Satıra Genişletme</h2><p>Xcode 15, küçük ama etkili bir düzenleme kısayolu tanıttı: Ctrl+M. İmlecini bir fonksiyon çağrısına, başlatıcıya veya virgülle ayrılmış herhangi bir parametre listesine yerleştir, Ctrl+M’ye bas ve Xcode otomatik olarak onu birden fazla satıra genişletiyor – her satırda bir parametre, düzgün girintili.</p><p><img src="https://fline.dev/assets/images/snippets/multi-line-code-ctrl-m-xcode-15/ctrl-m-shortcut.webp" alt="Ctrl+M shortcut" loading="lazy" /></p><p>Bu kısayoldan önce, uzun bir fonksiyon çağrısını yeniden biçimlendirmek elle satır sonları eklemek ve girintiyi düzeltmek demekti. Şöyle bir çağrıyı düşün:</p><pre><code class="language-swift">let label = UILabel(frame: .zero, font: .systemFont(ofSize: 14), textColor: .label, numberOfLines: 0)</code></pre><p>İmleç o satırdayken Ctrl+M’ye bastıktan sonra, Xcode şöyle yeniden biçimlendiriyor:</p><pre><code class="language-swift">let label = UILabel(
   frame: .zero,
   font: .systemFont(ofSize: 14),
   textColor: .label,
   numberOfLines: 0
)</code></pre><h2 id="ne-zaman-kullanılır">Ne Zaman Kullanılır</h2><p>Bu kısayol, zamanla parametre biriktiren SwiftUI view modifier’ları veya başlatıcılar yazarken en değerli. İki parametreyle başlayan bir view, yapılandırma ekledikçe genellikle beş veya altıya çıkıyor. Her seferinde elle yeniden biçimlendirmek yerine, Ctrl+M bunu tek bir tuş vuruşuyla halledebiliyor.</p><p>Tersi yönde de çalışıyor – parametrelerin zaten ayrı satırlardaysa, Ctrl+M’ye basmak onları tekrar tek satıra daraltıyor. Bu geçiş davranışı, okunabilirlik ihtiyacına göre kompakt ve genişletilmiş formatlar arasında kolayca geçiş yapmayı sağlıyor.</p><p>Dikkat edilmesi gereken bir şey: kısayol, imleç konumundaki en içteki parametre listesi üzerinde çalışıyor. İç içe fonksiyon çağrıların varsa, doğru olanı genişletmek için imlecini dikkatli konumlandır.</p>]]></content:encoded>
</item>
<item>
<title>Shift+Cmd+O ile Apple Belgelerinde Arama Yapma</title>
<link>https://fline.dev/tr/snippets/search-apple-documentation-shift-cmd-o/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/search-apple-documentation-shift-cmd-o/</guid>
<pubDate>Sat, 10 Jun 2023 00:00:00 +0000</pubDate>
<description><![CDATA[Apple'ın geliştirici dokümantasyonunu doğrudan web üzerinde aramak için aynı Open Quickly kısayolunu kullan.]]></description>
<content:encoded><![CDATA[<h2 id="dokümantasyon-için-open-quickly">Dokümantasyon için Open Quickly</h2><p>Çoğu Xcode kullanıcısı Shift+Cmd+O’ya aşinadır – projendeki herhangi bir dosyaya, sembole veya türe atlamanı sağlayan “Open Quickly” kısayolu. Xcode’u kullanmaya başladıktan birkaç gün sonra refleks haline gelen kısayollardan biri. Yakın zamana kadar fark etmediğim şey, aynı kısayolun artık DocC tarafından desteklenen Apple Developer dokümantasyon web sitesinde de çalıştığı.</p><p><img src="https://fline.dev/assets/images/snippets/search-apple-documentation-shift-cmd-o/search-documentation.webp" alt="Search documentation" loading="lazy" /></p><p><a href="https://developer.apple.com/documentation">developer.apple.com/documentation</a> adresinde gezinirken Shift+Cmd+O tuşlarına basmak, Xcode’un Open Quickly diyaloğu gibi davranan bir arama katmanı açıyor. Bir framework adı, bir sınıf, bir metod veya kısmi bir eşleşme yazabilirsin ve sonuçlar anında görünüyor. Bir sonucu seçmek doğrudan o dokümantasyon sayfasına yönlendiriyor.</p><h2 id="bu-neden-önemli">Bu Neden Önemli</h2><p>Bu özellikten önce, Apple dokümantasyonunda arama yapmak kenar çubuğu hiyerarşisinde gezinmek veya genel arama çubuğunu kullanmak demekti; bu da genellikle makalelerin, öğreticilerin ve API referanslarının bir karışımını döndürüyordu. Open Quickly katmanı, sonuçları API sembolleri ve sayfalarıyla filtreleyerek çok daha hassas hale getiriyor.</p><p>Bu özellikle bir tarayıcıda WWDC makalesi veya forum konusu okurken ve hızlıca ilgili bir API’nin imzasını kontrol etmen gerektiğinde çok yararlı. Xcode’a geri dönmek yerine, bağlamında kalıp doğrudan bakabilirsin.</p><p>Bu özellik, Apple’ın DocC’yi bir dokümantasyon platformu olarak daha geniş yatırımının bir parçası. DocC hem Xcode’un dokümantasyon görüntüleyicisini hem de web tabanlı dokümantasyonu güçlendirdiğinden, aynı etkileşim kalıplarının taşınması mantıklı. Apple dokümanlarını tarayıcıda okumaya vakit harcıyorsan, bu kısayolu kas hafızana yerleştirmek çabaya değer.</p>]]></content:encoded>
</item>
<item>
<title>Xcode 15 Tip Güvenli Asset Catalog Erişimi Getiriyor</title>
<link>https://fline.dev/tr/snippets/xcode-15-type-safe-asset-catalogs/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/xcode-15-type-safe-asset-catalogs/</guid>
<pubDate>Tue, 06 Jun 2023 00:00:00 +0000</pubDate>
<description><![CDATA[Xcode 15, asset catalog'larındaki görseller ve renkler için tür güvenli Swift erişimcileri oluşturarak SwiftGen ihtiyacını ortadan kaldırıyor.]]></description>
<content:encoded><![CDATA[<h2 id="string-tabanlı-asset-referanslarının-sonu">String Tabanlı Asset Referanslarının Sonu</h2><p>Xcode 15’teki daha sessiz ama etkili değişikliklerden biri, asset catalog’lara yerleşik tür güvenli erişim. Daha önce, asset catalog’undan bir görsel veya renk referansı almak string literal gerektiriyordu:</p><pre><code class="language-swift">// Before Xcode 15
Image(&quot;custom-header-icon&quot;)
Color(&quot;primaryBrand&quot;)</code></pre><p>Bu kırılgandı. Bir asset’i yeniden adlandır, kodun sorunsuz derlenir ama çalışma zamanında çöker veya hiçbir şey göstermez. SwiftGen gibi araçlar, asset catalog’larından tür güvenli sabitler üreterek tam olarak bu sorunu çözmek için vardı.</p><h2 id="ne-değişti">Ne Değişti</h2><p>Xcode 15 artık asset catalog’undaki her görsel ve renk için otomatik olarak Swift erişimcileri üretiyor. Bunlara resource başlatıcıları aracılığıyla erişiyorsun:</p><pre><code class="language-swift">// Xcode 15+
Image(.customHeaderIcon)
Color(.primaryBrand)</code></pre><p><img src="https://fline.dev/assets/images/snippets/xcode-15-type-safe-asset-catalogs/asset-catalog-autocomplete.webp" alt="Xcode showing autocomplete suggestions for asset catalog resources" loading="lazy" /></p><p>Derleyici asset’lerini biliyor. Tam otomatik tamamlama alıyorsun ve bir asset’i silersen veya yeniden adlandırırsan, sessiz bir çalışma zamanı hatası yerine derleme zamanı hatası alıyorsun.</p><h2 id="apple-swiftgeni-sherlocked-etti">Apple SwiftGen’i Sherlocked Etti</h2><p>Bu aslında Apple’ın SwiftGen’in yıllardır sunduğunu entegre etmesi. Halihazırda SwiftGen kullanan ekipler için, hala ona ihtiyaç duyup duymadığınızı değerlendirmek için iyi bir zaman. Yerleşik çözüm, en yaygın iki kullanım alanını – görseller ve renkler – herhangi bir build phase scripti veya kod üretme adımı olmadan kapsıyor.</p><p>SwiftGen’i fontlar, yerelleştirilmiş dizeler veya diğer kaynak türleri için kullanıyorsan, onu tutmak için hala nedenler var. Ama özellikle asset catalog’ları için, yerel çözüm artık çoğu proje için yeterince iyi ve sıfır yapılandırmayla kutudan çıkar çalışıyor.</p>]]></content:encoded>
</item>
<item>
<title>Xcode 15 String Catalog&apos;ları .strings ve .stringsdict&apos;in Yerini Alıyor</title>
<link>https://fline.dev/tr/snippets/xcode-15-string-catalogs/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/xcode-15-string-catalogs/</guid>
<pubDate>Tue, 06 Jun 2023 00:00:00 +0000</pubDate>
<description><![CDATA[Xcode 15, eski .strings ve .stringsdict dosyalarının yerini alan, yerelleştirilmiş dizeleri yönetmek için görsel bir editör olan String Catalogs'u tanıtıyor.]]></description>
<content:encoded><![CDATA[<h2 id="eski-yerelleştirme-i̇ş-akışı">Eski Yerelleştirme İş Akışı</h2><p><code>.strings</code> ve <code>.stringsdict</code> dosyalarıyla çalışmak her zaman Apple geliştirmesinin daha pürüzlü taraflarından biri olmuştur. Düz metin anahtar-değer dosyalarında hata yapmak kolay – eksik noktalı virgüller, diller arasında uyumsuz anahtarlar, çeviri ilerlemesini bir bakışta görme imkanı yok. Ve çoğullaştırma kuralları için kullanılan <code>.stringsdict</code> dosyaları ise XML tabanlı plist dosyaları olup elle yazmak oldukça zor.</p><h2 id="string-catalogs-ne-getiriyor">String Catalogs Ne Getiriyor</h2><p>Xcode 15, String Catalogs adında yeni bir <code>.xcstrings</code> dosya formatı tanıtıyor. Hem <code>.strings</code> hem de <code>.stringsdict</code> dosyalarını, özel bir görsel editörle gelen tek bir dosyayla değiştiriyor.</p><p><img src="https://fline.dev/assets/images/snippets/xcode-15-string-catalogs/string-catalog-editor.webp" alt="The String Catalog editor in Xcode 15 showing translations across multiple languages" loading="lazy" /></p><p>Temel iyileştirmeler oldukça önemli:</p><p><strong>Görsel editör</strong> – Tüm yerelleştirilebilir dizeler, her dil için sütunlar içeren bir tabloda gösteriliyor. Çevirileri, dosyalar arasında geçiş yapmadan veya harici araçlar kullanmadan satır içinde görebilir ve düzenleyebilirsin.</p><p><strong>Çeviri ilerleme takibi</strong> – Her dil bir tamamlanma yüzdesi gösteriyor. Bir bakışta hangi dillerin ilgiye ihtiyacı olduğunu ve hangi dizelerin henüz çevrilmediğini görebilirsin.</p><p><strong>Otomatik dize çıkarma</strong> – Xcode, Swift kodunu tarayarak yerelleştirme gerektiren dizeleri otomatik olarak keşfediyor. Yeni dizeler, herhangi bir elle kayıt adımı olmadan katalogda görünüyor.</p><p><strong>Yerleşik geçiş</strong> – Mevcut <code>.strings</code> ve <code>.stringsdict</code> dosyalarından bir geçiş yolu var. Mevcut yerelleştirme dosyalarına sağ tıkla, Xcode bunları yeni formata dönüştürmeyi teklif ediyor.</p><h2 id="pratik-etki">Pratik Etki</h2><p>Birkaç desteklenen dili olan projeler için bile, bu önemli bir yaşam kalitesi iyileştirmesi. Görsel editör tek başına bir biçimlendirme hatası sınıfını tamamen ortadan kaldırıyor. Otomatik çıkarmayla birleştirildiğinde, daha az unutulan dize ve tüm proje genelinde yerelleştirme durumunun daha net bir görüntüsü demek.</p><p>Xcode 15’te yeni bir proje başlıyorsan, String Catalogs varsayılan. Mevcut projeler için geçiş kolay ve kesinlikle yapılmaya değer.</p>]]></content:encoded>
</item>
<item>
<title>Xcode 15&apos;in Çoklu Satır Biçimlendirme Özelliği</title>
<link>https://fline.dev/tr/snippets/xcode-15-format-parameters-multiple-lines/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/xcode-15-format-parameters-multiple-lines/</guid>
<pubDate>Tue, 06 Jun 2023 00:00:00 +0000</pubDate>
<description><![CDATA[Xcode 15, uzun fonksiyon parametre listelerini tek satırdan birden fazla satıra yeniden biçimlendirmek için yerleşik bir eylem ekliyor.]]></description>
<content:encoded><![CDATA[<h2 id="biçimlendirme-sorunu">Biçimlendirme Sorunu</h2><p>Birçok parametresi olan uzun fonksiyon çağrıları ve tanımlamaları, Swift kodunda en yaygın okunabilirlik sorunlarından biri. Makul herhangi bir sütun sınırının çok ötesine uzanan satırlarla karşılaşıyorsun:</p><pre><code class="language-swift">func configureView(title: String, subtitle: String, icon: Image, backgroundColor: Color, isEnabled: Bool, action: @escaping () -&gt; Void) {</code></pre><p>Bunu elle birden fazla satıra bölmek sıkıcı. İmleci konumlandırman, satır sonları eklemen, her parametreyi girintilemen ve kapanış parantezinin doğru hizalandığından emin olman gerekiyor.</p><h2 id="xcode-15teki-yeni-eylem">Xcode 15’teki Yeni Eylem</h2><p>Xcode 15, bunu otomatik yapan bir “Format to Multiple Lines” eylemi sunuyor. İmlecini birden fazla parametresi olan bir fonksiyon çağrısına veya tanımlamasına yerleştir, Xcode yeniden biçimlendirmeyi sunuyor:</p><p><img src="https://fline.dev/assets/images/snippets/xcode-15-format-parameters-multiple-lines/format-to-multiple-lines.webp" alt="The Format to Multiple Lines option in Xcode 15" loading="lazy" /></p><p>Sonuç, her satırda bir parametre olacak şekilde temiz biçimlendirilmiş:</p><pre><code class="language-swift">func configureView(
   title: String,
   subtitle: String,
   icon: Image,
   backgroundColor: Color,
   isEnabled: Bool,
   action: @escaping () -&gt; Void
) {</code></pre><p>Bu eylemi fonksiyon imzasına sağ tıklayıp <strong>Refactor</strong> altında arayarak veya <strong>Editor</strong> menüsünü kullanarak bulabilirsin. Hem fonksiyon tanımlamalarında hem de çağrı noktalarında çalışıyor.</p><h2 id="ne-zaman-kullanılır">Ne Zaman Kullanılır</h2><p>Bu, yeni bir fonksiyon yazdıktan veya mevcut birine parametreler ekledikten hemen sonra en çok işe yarıyor. Yazarken elle biçimlendirmek yerine, her şeyi tek satıra yazıp sonra biçimlendiriciyi tek bir eylemle uygulayabilirsin. Ayrıca başka birinin uzun tek satırlık imzalar bıraktığı kodu incelerken de yardımcı oluyor – seç ve elle düzenleme yapmadan yeniden biçimlendir.</p><p>Ters işlem (birden fazla satırı tekrar tek satıra daraltma) şu anda mevcut değil, ama o yön genellikle daha az gerekli.</p>]]></content:encoded>
</item>
<item>
<title>Üretim Kodunu Değiştirmeden SwiftUI&apos;da Yükleme Durumlarını Önizleme</title>
<link>https://fline.dev/tr/snippets/preview-loading-states-swiftui/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/preview-loading-states-swiftui/</guid>
<pubDate>Wed, 31 May 2023 00:00:00 +0000</pubDate>
<description><![CDATA[SwiftUI preview'larında yükleme durumlarını görebilmen için ağ gecikmelerini simüle eden, sadece preview'a özel bir yardımcı.]]></description>
<content:encoded><![CDATA[<h2 id="zorluk">Zorluk</h2><p>Asenkron verilere bağımlı view’lar oluştururken, genellikle bir spinner veya placeholder gösteren bir yükleme durumun oluyor. Production’da bu durum, veriler ağdan veya veritabanından yüklenirken kısa süreliğine görünüyor. Ama SwiftUI preview’larında mock verilerin anında hazır olduğundan, yükleme durumu incelemek için çok hızlı geçiyor – ya da hiç görünmüyor.</p><h2 id="sadece-preview-i̇çin-gecikme-yardımcısı">Sadece Preview İçin Gecikme Yardımcısı</h2><p>Çözüm, sadece preview veya debug bağlamlarında yapay bir gecikme ekleyen küçük bir yardımcı. İşte kalıp:</p><pre><code class="language-swift">struct DelayedStatePreview&lt;Content: View&gt;: View {
   @State private var isLoaded = false
   let delay: Duration
   let content: (Bool) -&gt; Content

   init(
      delay: Duration = .seconds(2),
      @ViewBuilder content: @escaping (Bool) -&gt; Content
   ) {
      self.delay = delay
      self.content = content
   }

   var body: some View {
      content(isLoaded)
         .task {
            try? await Task.sleep(for: delay)
            isLoaded = true
         }
   }
}</code></pre><p>Bunu bir preview’da şöyle kullanıyorsun:</p><pre><code class="language-swift">#Preview {
   DelayedStatePreview { isLoaded in
      if isLoaded {
         ArticleListView(articles: mockArticles)
      } else {
         LoadingView()
      }
   }
}</code></pre><p><img src="https://fline.dev/assets/images/snippets/preview-loading-states-swiftui/code-example.webp" alt="Code example showing the preview helper in context" loading="lazy" /></p><h2 id="bu-neden-önemli">Bu Neden Önemli</h2><p>Temel fayda, production kodunun temiz kalması. Gerçek view’larına yapay gecikmeler veya debug bayrakları eklemiyorsun. Yardımcı tamamen preview katmanında var olarak, yükleme durumlarının doğru göründüğünü, geçişlerin düzgün animasyon yaptığını ve veriler geldiğinde düzenin sıçramadığını görsel olarak doğrulama imkanı tanıyor.</p><p>Bu, özellikle iskelet yükleyicileri veya parıltı efektleri olan view’lar için çok yararlı; yükleme durumunun görsel kalitesinin kullanıcı deneyiminin bir parçası olduğu durumlar.</p>]]></content:encoded>
</item>
<item>
<title>Debug Executable&apos;ı Devre Dışı Bırakarak Xcode Başlatmayı Hızlandır</title>
<link>https://fline.dev/tr/snippets/speed-up-xcode-disable-debug-executable/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/speed-up-xcode-disable-debug-executable/</guid>
<pubDate>Wed, 10 May 2023 00:00:00 +0000</pubDate>
<description><![CDATA[Geliştirme sırasında uygulama başlatma sürelerini önemli ölçüde azaltabilen gizli bir Xcode scheme ayarı.]]></description>
<content:encoded><![CDATA[<h2 id="boş-ekran-sorunu">Boş Ekran Sorunu</h2><p>Xcode’da Run’a bastıktan sonra uygulamanın gerçekten görünmesi arasında bir gecikme – bazen birkaç saniye – fark ettiysen, suçlu genellikle LLDB debugger’ının sürecine bağlanmasıdır. Bu süre zarfında Simulator, debugger başlatılırken boş bir ekran gösteriyor.</p><p><img src="https://fline.dev/assets/images/snippets/speed-up-xcode-disable-debug-executable/comparison.webp" alt="Comparison of launch times with and without debug executable enabled" loading="lazy" /></p><h2 id="ayar-nerede-bulunur">Ayar Nerede Bulunur</h2><p>Ayar scheme yapılandırmasında bulunuyor:</p><ol><li><p><strong>Product &gt; Scheme &gt; Edit Scheme</strong> menüsüne git (veya Cmd+Shift+&lt; tuşlarına bas)</p></li><li><p>Sol tarafta <strong>Run</strong> eylemini seç</p></li><li><p><strong>Info</strong> sekmesine geç</p></li><li><p><strong>Debug executable</strong> seçeneğinin işaretini kaldır</p></li></ol><p><img src="https://fline.dev/assets/images/snippets/speed-up-xcode-disable-debug-executable/setting-before.webp" alt="The setting before the change" loading="lazy" /></p><p><img src="https://fline.dev/assets/images/snippets/speed-up-xcode-disable-debug-executable/setting-after.webp" alt="The setting after unchecking Debug executable" loading="lazy" /></p><h2 id="bu-ne-yapar">Bu Ne Yapar</h2><p>“Debug executable” etkinken (varsayılan), Xcode başlatmada LLDB debugger’ını uygulama sürecine bağlıyor. Bu, breakpoint’leri, hata ayıklama bellek grafiğini, view hiyerarşisi debugger’ını ve konsolda <code>po</code> komutlarını mümkün kılan şey.</p><p>Bunu devre dışı bırakmak debugger bağlantısını tamamen atlıyor. Uyguaman fark edilir şekilde daha hızlı başlıyor – benim deneyimimde, büyük projelerde fark 2 ila 5 saniye olabiliyor. <code>print()</code> ve <code>os_log</code> ile konsol çıktısı normal şekilde çalışmaya devam ediyor, yani hata ayıklama için loglama kullanmaya devam edebilirsin.</p><h2 id="takas">Takas</h2><p>Debugger bağlı olmadan şunları kaybediyorsun:</p><ul><li><p>Breakpoint’ler (tetiklenmezler)</p></li><li><p>Konsolda <code>po</code> ve <code>expression</code> komutları</p></li><li><p>Bellek grafiği ve view hiyerarşisi hata ayıklama araçları</p></li></ul><p>Bu, ayarı özellikle UI iterasyon çalışmaları için ideal yapıyor; görsel düzenlemeler yapıp sık sık yeniden çalıştırdığın zamanlar. Breakpoint’lerle belirli bir hatayı araştırman gerektiğinde, geçici olarak onay kutusunu tekrar etkinleştir. Ben çoğu zaman kapalı tutuyorum ve sadece kod üzerinde adım adım ilerlemem gerektiğinde açıyorum.</p>]]></content:encoded>
</item>
<item>
<title>Geliştirici Uyarıları için Xcode Kod Parçacıkları</title>
<link>https://fline.dev/tr/snippets/xcode-snippets-developer-warnings/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/xcode-snippets-developer-warnings/</guid>
<pubDate>Sun, 07 May 2023 00:00:00 +0000</pubDate>
<description><![CDATA[Kod tabanında eyleme geçirilebilir hatırlatıcılar bırakmak için #warning ile Xcode kod snippet'lerini kullanma.]]></description>
<content:encoded><![CDATA[<h2 id="geliştirme-sürecinde-warning-neden-önemli">Geliştirme Sürecinde #warning Neden Önemli</h2><p>Swift’in <code>#warning</code> direktifi, özel bir mesajla derleyici uyarısı üretiyor. Yorumlardan farklı olarak, bunlar Issue Navigator’da ve derleme çıktısında görünüyor, bu yüzden gözden kaçırmaları imkansız. Ben bunları yayınlamadan önce mutlaka ele alınması gereken şeyler için kesin hatırlatıcılar olarak kullanıyorum.</p><h2 id="her-gün-kullandığım-i̇ki-snippet">Her Gün Kullandığım İki Snippet</h2><p>Bu amaçla yapılandırdığım iki Xcode kod snippet’im var.</p><p><strong>“nyi” – Not Yet Implemented:</strong></p><pre><code class="language-swift">#warning(&quot;Not yet implemented!&quot;)</code></pre><p>Prototipleme sırasında bir fonksiyonu stub’ladığımda veya bir kod yolunu atladığımda <code>nyi</code> yazıp Enter’a basıyorum. Sorunsuz derleniyor ama uyarı, işi bitirmek için geri dönmemi sağlıyor.</p><p><strong>“dw” – Developer Warning:</strong></p><pre><code class="language-swift">#warning(&quot;&lt;#message#&gt;&quot;)</code></pre><p>Bu, bir placeholder token kullanıyor, böylece <code>dw</code> yazıp Enter’a bastıktan sonra imleç mesajın içine düşüyor ve özel bir not yazabiliyorum. Bunu <code>#warning(&quot;Çevrimdışı mod için hata durumunu ele al&quot;)</code> veya <code>#warning(&quot;Yayınlamadan önce kaldır&quot;)</code> gibi şeyler için kullanıyorum.</p><h2 id="xcode-snippetleri-nasıl-oluşturulur">Xcode Snippet’leri Nasıl Oluşturulur</h2><p>Bunları ayarlamak her biri yaklaşık 30 saniye sürüyor:</p><ol><li><p>Snippet olarak istediğin kodu herhangi bir Swift dosyasına yaz</p></li><li><p>Kodu seç</p></li><li><p>Sağ tıkla ve <strong>Create Code Snippet</strong> seçeneğini seç</p></li><li><p>Bir başlık ver (ör. “Developer Warning”)</p></li><li><p><strong>Completion</strong> kısayolunu ayarla (ör. <code>dw</code>)</p></li><li><p><strong>Availability</strong> seçeneğini “All” veya “Swift” olarak ayarla</p></li><li><p>Done’a tıkla</p></li></ol><p>Bu noktadan sonra, herhangi bir Swift dosyasında kısayolu yazmak, snippet’i otomatik tamamlama aracılığıyla sunuyor.</p><p>Düz yorumlara göre temel avantaj görünürlük. Bir <code>// TODO:</code> yorumunu görmezden gelmek kolay ve tutarlı bir şekilde aramak zor. Bir <code>#warning</code> ise derleyiciyi her derlemede bunu yüzeye çıkarmaya zorluyor, sen çözene kadar tamamlanmamış işini ön planda tutuyor.</p>]]></content:encoded>
</item>
<item>
<title>GitHub&apos;da Swift Evolution Teklif Özetlerine Hızlı Erişim</title>
<link>https://fline.dev/tr/snippets/swift-evolution-proposal-summaries-github/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/swift-evolution-proposal-summaries-github/</guid>
<pubDate>Tue, 02 May 2023 00:00:00 +0000</pubDate>
<description><![CDATA[GitHub'daki Swift Evolution tekliflerinin özetlenmiş versiyonlarını okumak için basit bir URL hilesi.]]></description>
<content:encoded><![CDATA[<h2 id="teklif-belgelerinin-sorunu">Teklif Belgelerinin Sorunu</h2><p>Swift Evolution teklifleri tasarım gereği kapsamlıdır. Motivasyonu, detaylı tasarımı, değerlendirilen alternatifleri, ABI etkilerini ve daha fazlasını kapsarlar. Bu kapsamlılık inceleme süreci için gerekli, ama sadece bir teklifin ne yaptığını ve neden yaptığını anlamak istediğinde, binlerce kelimeyi okumak biraz fazla olabiliyor.</p><h2 id="url-hilesi">URL Hilesi</h2><p>GitHub’daki herhangi bir Swift Evolution teklifinin özetlenmiş versiyonunu almanın basit bir yolu var. Şöyle bir URL’deki bir teklifi görüntülüyorsan:</p><pre><code>https://github.com/apple/swift-evolution/blob/main/proposals/0390-noncopyable-structs-and-enums.md</code></pre><p><code>apple</code> kısmını <code>FlineDev</code> ile değiştir:</p><pre><code>https://github.com/FlineDev/swift-evolution/blob/main/proposals/0390-noncopyable-structs-and-enums.md</code></pre><p>Bu seni swift-evolution deposunun bir fork’una götürüyor. Burada tekliflerin başına yapay zeka tarafından oluşturulmuş özetler eklenmiş. Her özet, teklifin ne getirdiğini, neden önemli olduğunu ve temel sözdizimini birkaç paragrafa sığdırıyor.</p><h2 id="ne-zaman-i̇şe-yarıyor">Ne Zaman İşe Yarıyor</h2><p>Bu özellikle sürüm notlarında veya sosyal medyada bir tekliften bahsedildiğini gördüğünde ve hızlıca özünü anlamak istediğinde işe yarıyor. Tam teklifi okumak için 15 dakika harcamak yerine, temel bilgiyi birkaç dakika içinde alıyorsun.</p><p>Özetler son zamanlarda kabul edilen tekliflerin çoğunu kapsıyor. Fork’dan önce gelen eski teklifler için orijinal metni görürsün. Ama Swift Evolution’ın son birkaç yılı için özetlenmiş versiyon gerçek bir zaman tasarrufu.</p><p>Bu fork’u, teklifleri sürekli sadece ana fikri bulmak için göz gezdirirken oluşturdum ve diğer geliştiricilerin de aynı kısayoldan faydalanabileceğini düşündüm.</p>]]></content:encoded>
</item>
<item>
<title>Pulsating Button Animation in SwiftUI</title>
<link>https://fline.dev/tr/snippets/pulsating-button-animation-swiftui/</link>
<guid isPermaLink="true">https://fline.dev/tr/snippets/pulsating-button-animation-swiftui/</guid>
<pubDate>Fri, 07 Apr 2023 00:00:00 +0000</pubDate>
<description><![CDATA[Onboarding sırasında kullanıcıları yönlendirmek için SwiftUI'da titreşen buton efekti nasıl oluşturulur.]]></description>
<content:encoded><![CDATA[<h2 id="guiding-users-with-a-pulsating-button">Guiding Users with a Pulsating Button</h2><p>Bir onboarding akışı oluştururken, kullanıcının dikkatini yapması gereken bir sonraki işleme yönlendirmek zorlu olabiliyor. Butonlarda ince bir titreşim animasyonu, göze batmadan dikkati çekiyor. Ben bunu SwiftUI’da <code>scaleEffect</code> ve <code>opacity</code> modifier’larını tekrarlayan bir animasyonla birleştirerek gerçekleştirdim.</p><p>İşte temel yaklaşım:</p><pre><code class="language-swift">struct PulsatingButtonStyle: ButtonStyle {
   @State private var isPulsating = false

   func makeBody(configuration: Configuration) -&gt; some View {
      configuration.label
         .scaleEffect(isPulsating ? 1.06 : 1.0)
         .opacity(isPulsating ? 0.8 : 1.0)
         .animation(
            .easeInOut(duration: 0.8)
               .repeatForever(autoreverses: true),
            value: isPulsating
         )
         .onAppear {
            isPulsating = true
         }
   }
}</code></pre><p>İşin sırrı, senkronize çalışan iki animasyonu – ölçek ve opaklık – birleştirmek. <code>repeatForever(autoreverses: true)</code> modifier’ı animasyonun sürekli ileri geri gitmesini sağlıyor. <code>isPulsating</code> değerini onAppear’da değiştirerek, animasyon view göründüğü anda başlıyor.</p><p><video src="https://fline.dev/assets/images/snippets/pulsating-button-animation-swiftui/demo.mp4" controls muted playsinline></video></p><p>1.06’lık ölçek faktörü bilerek ince tutulmuş. Çok fazla büyütmek (mesela 1.2) animasyonun agresif ve dikkat dağıtıcı hissettiriyor. Hafif opaklık değişimi, butonu okunmaz yapmadan derinlik hissi katıyor.</p><p>Bu kalıp, “Devam Et” veya “Başla” butonunu vurgulamak istediğin onboarding ekranları için çok iyi çalışıyor. Kullanıcı onboarding’i geçtikten sonra animasyon artık gösterilmiyor, böylece zamanla sinir bozucu olmuyor.</p><p>Bunu herhangi bir butona <code>.buttonStyle(PulsatingButtonStyle())</code> ile uygulayabilirsin, böylece animasyon mantığı buton içeriğinden temiz bir şekilde ayrılmış oluyor.</p>]]></content:encoded>
</item>
</channel>
</rss>