Scholarship Projesi: Püf Noktaları ve Sık Yapılan Hatalar

Playground projesi hazırlarken karşılaşılan spesifik sorunların üstesinden nasıl gelebileceğinizi öğrenin!

M. Bertan Tarakçıoğlu
TurkishKit
11 min readMar 14, 2022

--

Not: An itibarıyla WWDC22 Swift Student Challenge kuralları açıklandı ve bu yılki proje formatı Playground App, ve bu makalede bahsettiğimiz Playground Book değil!

Daha fazla bilgi için Swift Student Challenge web sitesini ziyaret edin.

Merhaba sevgili TurkishKit okurları! WWDC ile birlikte Swift Student Challenge her geçen gün yaklaşıyor! Bu yüzden bu makalemizde sizlere Playground projelerinizi kodlarken sıkça karşılaşabileceğiniz ve bazen sinir bozucu olabilen hatalardan, onları nasıl çözebileceğinizden ve püf noktalarından bahsedeceğiz.

Playgrounds ve SwiftUI

Apple’ın 2019’da çıkardığı ve bizim TurkishKit’te kullanmayı çok sevdiğimiz SwiftUI teknolojisini Playground projelerinizde de aşağıdaki gibi basitçe kullanabilirsiniz.

import PlaygroundSupport
import SwiftUI
// Standard bir SwiftUI görünümü olan ContentView
struct ContentView: View {
var body: some View {
Text(“Hello, TurkishKit”)
.font(.largeTitle)
}
}
// Live View’a ContentView görünümünü atıyoruz
PlaygroundPage.current.setLiveView(ContentView())

İlk olarak kaynak kodumuzun en başında PlaygroundSupport teknolojisini ekliyoruz — bu şekilde Playgrounds uygulaması oluşturabilmek için gerekli kaynak kodlara erişiyoruz.

Ardından kodumuzun son satırındaki .setLiveView komutu ile Playgrounds uygulamasının sağ kısmındaki içerikleri görüntülemekle sorumlu bölüm olan Live View’a ContentView objesinin görüntülemesini söylüyoruz.

Bu komuta PlaygroundLiveViewable protokolüne uyan her objeyi atayabilirsiniz, yani sadece SwiftUI View objeleri ile sınırlı değilsiniz! 😄

Playgrounds ve UIKit

PlaygroundLiveViewable protokolüne uydukları için UIView ve UIViewController objelerini de bir önceki adımda kullandığımız iki komutu kullanarak LiveView’da görüntüleyebilirsiniz.

Aşağıdaki örnekte standard bir UIView objesinin LiveView’a nasıl atandığını görmektesiniz.

import PlaygroundSupport
import UIKit
var view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 50))var label = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 50))label.text = "Hello, TurkishKit"
label.font = .preferredFont(forTextStyle: .largeTitle)
view.addSubview(label)// view görünümünü LiveView'a atıyoruz
PlaygroundPage.current.setLiveView(view)

Şimdiyse de bir UIViewController objesini görmektesiniz. Temel mantık gördüğünüz gibi hiç değişmiyor.

import PlaygroundSupport
import UIKit
class ViewController: UIViewController {
var label: UILabel!

override func viewDidLoad() {
super.viewDidLoad()
label = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 50))

label.text = “Hello, TurkishKit”
label.font = .preferredFont(forTextStyle: .largeTitle)
self.view.addSubview(label)
}
}

PlaygroundPage.current.setLiveView(ViewController())

Live View’u Tam Ekran Haline Getirme

Normal şartlar altında Live View görünümü cihaz ekranın sadece yarısını kaplıyor, ancak zaman zaman bütün ekranın kaplanmasını istediğiniz durumlar olabilir. Bunun için kodunuzun sonuna aşağıdaki komutu eklemeniz yeterli.

PlaygroundPage.current.wantsFullScreenLiveView = true

Not: Playgrounds uygulamasındaki bir hatadan dolayı komutu ilk eklediğinizde biraz tutukluk yapabiliyor. Uygulamayı yeniden başlattığınızda olması gerektiği gibi çalışacaktır.

Image Sorunu

Daha önceki bir makalemizde uygulamalarınızda Image görünümünü ile nasıl görsel ekleyebileceğinizi keşfetmiştik. Makalemize aşağıdan ulaşabilirsiniz:

Ancak Swift Playgrounds’a gelince işler biraz değişiyor, çünkü Image görünümünü aşağıdaki gibi kullanmaya çalıştığınızda sadece boş bir görüntü ile karşılaşıyorsunuz.

Image(“Photo”)
.resizable()
.scaledToFit()
.frame(width: 400)

Bunu Image görünümüne UIImage tipinde bir değer atayarak çözebiliyoruz, ancak her seferinde bunu yapmak kodunuzu uzatacak ve okunurluğunu azaltacaktır.

Bunun yerine UIImage görünümünü aşağıdaki extension ile genişleterek, Image görünümünün bundan sonra kendisine atanan String değerlerini önce bir UIImage değerine çevirip sonra onu kullanmasını sağlamak çok daha temiz bir çözüm.

extension Image {
init(_ named: String) {
self.init(
uiImage: UIImage(
imageLiteralResourceName: named
)
)
}
}

İşte bu kadar! Artık Image görünümlerini Playgrounds üzerinde her zaman olduğu gibi kullanmaya devam edebilirsiniz.

Not: Sağladığınız isimde bir görselin proje dosyalarında olduğuna dikkat edin. Standard bir SwiftUI projesinde görsel bulunmadığı takdirde sadece boş bir görüntü oluşmakta, ancak bu yöntemde Playground kodunuz tamamen çöküyor.

Playground Sonuçlarını Etkisizleştirmek

Buraya kadar hatasız bir proje ortaya çıkartmamıza rağmen, kaynak kodunuz arttıkça bir noktadan sonra pek anlam veremediğiniz bir runtime error, yani çalıştırma hatası alabilirsiniz.

Bu oldukça sinir bozucu, ancak çözmesi de bir o kadar kolay olan bir sorundan kaynaklanıyor: Sonuçları Etkinleştir (Enable Results) özelliğinin açık olması.

Özelliği kapatmak için aşağıdaki gibi Kodumu Çalıştır botunun yanındaki hız göstergesine benzer butona dokunup, açılan menüden Sonuçları Etkinleştir seçeneğini kapatın. Apple’ın aşağısına düştüğü nottaki gibi özellik performansı azalttığından dolayı bu soruna sebebiyet veriyor.

Projeniz artık sorunsuz bir biçimde çalışmalı. Ancak problem hâlâ tamamen çözülmüş diyemeyiz, çünkü projenizi bir dahaki açışınızda Sonuşları Etkinleştir özelliği kendiliğinden tekrar aktifleştirilecek. Bir sonraki adımda bunu nasıl engelleyebileceğimizi keşfediyoruz.

Manifesto!

Her Swift Playground kitabı (Playground Book) ayarlarını ve özelliklerini belirleyen manifest.plist isminde bir dosyaya sahip. Buna ek olarak Playground kitabınızın bölümü ve her sayfası için de yine aynı isim ve uzantıya sahip bir dosya bulunmakta.

💡İpucu: Eğer daha önce karşılaşmadıysanız, plist dosyaları Apple geliştirici ekosisteminde sıklıkla kullanılan; özellik, bilgi ve ayarların depolandığı dosyalardır.

İlk olarak sayfa ayarlarını belirleyen Manifest.plist dosyasını inceleyelim. Bunun için Xcode yüklü bir Mac bilgisayarına ihtiyacınız olacak.

İlk olarak Playground projenizi Finder’da bulun. Ardından projenize sağ tıklayarak aşağıdaki gibi Paket İçeriğini Göster’i tıklayın — sizi projenizin kaynak dosyaları bekliyor olacak. 😎

Sonrasında aşağıda gördüğünüz gibi bu uzun dosya adresini takip edip sayfa ayarlarını belirleyen Manifest.plist dosyasını Xcode ile açın.

Dosya konumu: /Chapters/Chapter1.playgroundchapter/Pages/My Playground.playgroundpage/Manifest.plist

Kalın font ile yazılı kısımlar düzenlediğiniz Playground ve sayfaya göre değişiklik gösterebilir.

Aşağıdaki gibi açılan editördeki anahtar değerlerinin üzerindeki artı sembolüne tıklayarak yeni bir anahtar ekleyin. Anahtar ismi PlaygroundLoggingMode, ve değeri de Off olmalı. Ayrıca anahtar veri tipinin bir String olmasına dikkat edin.

🥳 İşte bu kadar! Artık Sonuçları Etkinleştir tamamen devre dışı kalmakla birlikte Playgrounds uygulamasında gözükmeyecek bile.

Not: Projeniz birkaç sayfadan oluşuyorsa sonu .playgroundpage uzantısıyla biten bütün klasörlerin içerisindeki Manifest.plist dosyaları için bu adımı tekrarlamanız gerekmekte.

👀 Eğer bir Mac bilgisayarına sahip değilseniz bu sizin için! Sonuçları Etkinleştir ayarı yukarıdaki adımlar ile tamamen kaldırılmış bir Playground proje şablonu oluşturduk. Aşağıya tıklayarak GitHub’dan indirebilirsiniz.

Manifest.plist dosyasını kaptmadan önce bir seçeneğe daha değinelim. En üst kısımda gördüğünüz anahtar LiveViewEdgeToEdge, isminden de anlayabileceğimiz üzere Live View görünümünün pencere boyunca genişletilmesini sağlıyor.

Anahtar Bool tipinde ve şu anda 0 (false). Etkinleştirmek için bu değeri 1 (true) olarak değiştirin ve kaydedin.

Lütfen etkinleştirmeden önce bu ayarın Kodumu Çalıştır ve yanında bulunan iki butonun da proje görünümüzün içine alınmasına neden olacağını göz önünde bulundurun — çoğunlukla oyun ve kamerayı kullanan projeler için uygun.

Bu bölümde olası anahtarlardan sadece iki tanesine göz attık, ama seçenekler sadece bunlarla sınırlı değil! Eğer merak ediyorsanız aşağıdaki sayfada anahtarların tam bir listesi mevcut. 😌

Kapak Resmi Eklemek

Projenize bir kapak resmi ekleyerek bir kimlik kazanmasını sağlayabilir ve onu öne çıkarabilirsiniz! Şimdi ressam şapkanızı takın çünkü yapmanız gereken ilk şey kapak tasarımınızı yapmak olacak. 🧑‍🎨

Not: Kapak resminiz .png formatında ve 400 x 300 piksel boyutlarında olmalı.

Tasarım işi bittikten sonra kapağı Playground projenize eklemeye geçebiliriz.

Şimdi yine Paket İçeriğini Göster seçeneğini kullanarak proje kaynak dosyalarını görüntüleyin. Ardından Contents klasörünü açıp içinde hali hazırda yoksa PrivateResources isminde bir klasör oluşturun. Şimdi bu klasörü açın ve yukarıdaki özelliklere uyduğundan emin olduğunuz kapak resminizi içine taşıyın. Sonra da ismini cover.png olarak değiştirin.

Harika! Şimdi yapmamız gereken sadece tek bir şey kaldı: Playgrounds uygulamasını kapak resminizin nerede olduğunu söylemek. Finder’ın geri gitme butonunu kullanarak Contents klasörüne geri gidin ve karşınıza çıkan Manifest.plist Xcode ile açın. Bu dosya genel kitap ayarlarının düzenliyor.

Şimdiyse de yine herhangi bir anahtarın yanındaki artı sembolüne tıklayarak listeye yeni bir anahtar ekleyin: ImageReference. Değeri ise kapak resminizin dosya ismi olmalı, yani String veri tipinde cover.png.

Tebrikler! 🥳 Kapak resminiz artık hazır. Eğer kapak resminiz Playgrounds uygulamasıda hemen görünmezse projenizin bir kopyasını oluşturup içe aktarmayı ya da az sonra nasıl yapılacağını keşfedeceğimiz Yeni Oyun Alanı Olarak Dışarı Aktar özelliğini denemenizi öneririm.

Ayrıca aşağıdaki sayfadan da Playground proje ayarlarını belirleyen Manifest.plist dosyasına ekleyebileceğiniz anahtarların tam bir listesine ulaşabilirsiniz.

Cihaz Yönü

Playground projelerinizde birçok farklı nedenden dolayı cihaz yönüne (device orientation) ihtiyaç duyabilirsiniz. Maalesef Playgrounds uygulamasında cihaz yönüne erişmek sıkıntılı bir sürece dönüşebiliyor.

UIDevice.current.orientation özelliği ile cihaz yönüne kolayca erişebiliyorsunuz.

Maalesef ki kodunuz Playgrounds ortamında çalışıyorsa bu komut yanlış çalışıyor.

Eğer projeniz UIKit tabanlıysa, ideal olmamasına rağmen cihaz yönüne UIViewController tipine ait ve iOS 8'de deprecate edilmiş (kullanımdan kaldırılmış) interfaceOrientation değişkeni ile erişebilirsiniz.

Eğer projeniz UIKit tabanlıysa, ideal olmamasına rağmen cihaz yönüne UIViewController tipine ait ve iOS 8'de deprecate edilmiş (kullanımdan kaldırılmış) interfaceOrientation değişkeni ile erişebilirsiniz.

Not: Deprecate edilmesi, Apple’ın bu komutu kullanımdan kaldırması, ancak hali hazırda bu komutu kullanan uygulamalarda sorun oluşmaması için kaynak kodunda uyarıya sebep olmasına rağmen kullanımına izin verdiği anlamına geliyor.

Ekleyelim ki bu sadece geçici bir çözüm ve siz bunu okurken kullanımdan tamamen kaldırılmış bile olabilir! 🤯

Çoğu zaman yerlerini yenileri (ve daha iyileri) aldığı için komutlar deprecate edilir. Normal Şartlar altında bu komutlardan uzak durmalısınız.

PlaygroundKeyValueStore

PlaygroundKeyValueStore, temelde UserDefaults ile aynı görev ve amaca sahip, ancak isminden de anlaşılacağı üzere Playground projeleri için çok daha uygun. Daha önce UserDefaults ile çalışmadıysanız, bu makalemize bir göz atabilirsiniz:

PlaygroundKeyValueStore kaydettiği değerleri .playgroundbook dosyasının içinde depoluyor. Eğer playground dosyasını iCloud’da depoluyorsanız, PlaygroundKeyValueStore siz hiçbir şey yapmadan kaydettiğiniz verileri iCloud üzerinden senkronize ediyor. Bu, proje dosyanızı paylaştığınız durumda kaydedilen verilerin de paylaşılması demek, o yüzden kişisel veriler konusunda dikkatli olun!

Vari kaydetmeyle işe başlayalım. Aşağıdaki örnekte bir String değeri olan kullanıcı adını username isimli anahtara kaydediyoruz:

PlaygroundKeyValueStore.current[“username”] = .string(“Craig”)

Yukarı da da gördüğünüz üzere kaydedilen veri tipini bir enum değeri ile belirliyoruz. Bunun nedeni PlaygroundKeyValueStore mekanizmasının sadece belli başlı verileri kabul eden PlaygroundValue veri tipini depolayabilmesi.

Aşağıda PlaygroundValue tarafından desteklenen bütün veri tipleri için basit örnekler yer almakta:

  • .boolean(true)
  • .data(Data("Tim".utf8))
  • .date(Date())
  • .floatingPoint(42.53)
  • .integer(42)
  • .string("Steve")
  • .none (Tutulan veriyi temizler ve nil değerini atar.)

Ayrıca sadece yukarıdaki PlaygroundValue tipindeki değerler içeren Array değerlerine ek olarak anahtarları String ve değerleri PlaygroundValue tipindeki değerleri depolayabiliyorsunuz. Örnekler aşağıda:

  • .array(.integer(4), .integer(2))
  • .dictionary(["appleWeight": .floatingPoint(42.53), "strawberryWeight": .floatingPoint(12.34)])

Şimdiyse kaydedilen değerlere nasıl erişeceğimize göz atalım. Bu kısım olduğu şey için biraz karışık gelebilir, merak etmeyin, hepsinin üstünden tek tek geçeceğiz. Aşağıdaki örnekte kaydettiğimiz kullanıcı adına erişiyor ve konsola yazdırıyoruz.

// Anahtar için bir değer olduğunu doğrula
if let keyValue = PlaygroundKeyValueStore.current["username"] {
// Değerin String veri tipinde olduğunu doğrula
if case .string(let name) = keyValue {
// Değeri yazdır
print("Merhaba, \(name)!")
} else {
print("Değer yanlış veri tipinde")
}
} else {
print("Değer bulunamadı")
}

İlk önce bir if let ifadesiyle anahtarımıza ilişik kayıtlı veri olduğunu doğruluyoruz ve bulunan veriyi keyValue ismindeki bir sabite atıyoruz. Bulunamadığı halde konsola bir hata mesajı yazdırıyoruz.

Ancak elimizdeki verinin hangi veri tipinde olduğunu hâlâ bilmiyoruz. Burada kullandığınız veri tipi, değeri kaydederken kullandığınız veri tipinin aynısı olmalı.

Sonraki adımda if case ifadesiyle önceden oluşturduğumuz keyValue sabitinin .string tipinde olduğundan emin olup, onu name isminde başka bir sabite atıyoruz. Aksi takdirde yine konsola hata mesajı yazdırıyoruz.

Her şey yolunda gittiyse artık name değişkeni üzerinden kaydettiğimiz değere erişebilirsiniz.

Playground Modüllerini Kullanın

Düzenli ve okunması kolay bir projeye sahip olmak için farklı amaçlara hizmet eden kod parçacıklarını kendi modüllerine ayırmak her zaman iyi bir pratik olarak kabul edilir.

Ancak Swift Playgrounds üzerinde bir birinden ayrı Swift dosyaları oluşturmak için en az bir tane modüle ihtiyacımız var. Swift Playgrounds’taki bu modülleri Xcode’taki Swift Package Manager’a (SPM) benzetebiliriz.

Hadi gelin biz kendi modülümüzü oluşturalım. Aşağıdaki gibi proje dosyaları menüsünün Kaynak Kodu yazan kısmının hemen sağında bulunan artı butonuna tıklayarak yeni bir modül oluşturun ve TurkishKit olarak adlandırın.

Modüller içerisinde birden fazla Swift dosyası barındırabiliyor, bu yüzden proje yapınızı oluştururken modülleri Xcode’daki grup klasörleri gibi düşünebilirsiniz. İhtiyacınız oldukça aşağıdaki gibi modül isminizin sağındaki artı sembolünü kullanarak Swift dosyaları ekleyebilirsiniz.

Playground modüllerinde dikkat etmeniz gereken iki ek nokta bulunmakta. Bunlardan ilki Access Control.

Modüllerinizin içerdiği class, struct ve enum benzeri yapılara, içerdikleri değişkenlere ve metotlara diğer modüller ve sayfalardan erişebilmeniz için public anahtar kelimesiyle işaretlemeniz gerekmekte.

Normal şartlar altında bir Xcode projesinde oluşturduğunuz Swift dosyalarının içeriklerine erişmek için public ile işaretlemeye ihtiyaç duymazsınız. Ancak Playgrounds kullanırken sadece dosya değil, dosyaları içeren modüller oluşturuyoruz, ve modüller public işaretini zorunlu kılıyor.

Eğer Access Control ile ilk kez çalışıyorsanız onunla ilgili bir yazımız da mevcut. 😄

İkinci nokta da import komutları. Playgrounds uygulaması oluşturduğunuz modülleri Playground sayfalarına otomatik olarak dahil etmekte, ancak bir modülü başka bir modül içerisinde kullanmak istediğinizde bir import komutuna ihtiyacınız var. Diyelim ki oluşturduğumuz TurkishKit modülünün içinden bir class yapısına Playgrounds uygulamasının otomatik oluşturduğu UserModule modülünün SharedCode.swift dosyasından erişmek istiyorsunuz. Aşağıdaki gibi bir import komutu yardımıyla TurkishKit modülünü dosyaya dahil etmelisiniz.

// UserModule/SharedCode.swift:import TurkishKit

Yeni Playground Olarak Dışa Aktar

Eğer bir Mac bilgisayarına sahipseniz, Playgrounds uygulamasının Yeni Playground Olarak Dışarı Aktar özelliğinden yararlanarak özel alt başlık ve sıfırlama noktasına sahip bir Playground kitabı dosyası oluşturabilirsiniz.

Sıfırlama noktası, sizin ya da diğer kullanıcıların yaptığı değişikleri kolayca silmenize ve kaynak kodunuzu orijinal haline getirmenizi sağlıyor. Oldukça havalı. 😎

Yapmanız gereken ilk şey projenizi açmak olacak. Ardından menü çubuğunun dosya menüsünde bulunan Yeni Playground Olarak Dışarı Aktar seçeneğine tıklayın. Açılan pencerede değerleri istediğiniz gibi kişiselleştirebilirsiniz. Content ID bölümünü olduğu gibi bırakıp geçebilirsiniz, ancak sıfırlama noktası oluşturmak için alttaki seçeneğin işaretli olduğundan emin olun!

İşlem tamamlandığında Playground projeniz iCloud Playgrounds klasörüne aktarılmış olacak.

Son Birkaç İpucu! 👀

Makaleyi sonlandırmadan önce Scholarship Projesi hazırlama sürecinde işinize yarayacak birkaç ipucu paylaşmak istiyorum.

Xcode Projesinde Kodlayın, Sonra Playgrounds’a Aktarın

Projenizi ya Playgrounds uygulamasında ya da Xcode kullanarak Playgrounds Author Template ile yapıyor olun, standard bir Xcode projesinde çalışmak size çok daha iyi bir deneyim sunacak ve zaman kazanmanızı sağlayacaktır.

Mesela Swift Playgrounds’da CMD + F kısayoluyla arama özelliği bulunmuyor ve Author Template’ı kullanırken de kod tahmini özelliği devre dışı kalıyor.

Playgrounds Hatalarına Hazırlıklı Olun!

Bu makalede de gördüğünüz üzere Swift Playgrounds uygulamasında her şey beklediğiniz gibi çalışmayabilir. Bu yüzden kodunuzu bir Xcode projesinden Playgrounds’a aktardıktan sonra meydana gelebilecek hataları göz ününde bulundurun ve proje sürecinizi planlarken bu hatalarıda çözmeye de zaman ayırın. Aksi takdirde son anda beklenmedik bir hatadan dolayı projeniz başarısız olabilir.

Playground Kitabı Formatından Yararlanın

Projenizin benim şimdiye kadar yaptıklarım gibi Playgrounds ortamında çalışan bir uygulama gibi olabileceği gibi, Playground Book formatından da yararlanabileceğini unutmayın.

Playgrounds Author Template kullanarak kullanıcıya herhangi bir konsepti adım adım ve interaktif bir şekilde adeta bir kitap gibi öğreten bir Playground projesi oluşturabilirsiniz.

Playground Book ve Author Template ile ilgili yazımızı da aşağıya bırakıyorum. Okumanızı mutlaka öneririm. 😄

Böylece bir yazımızın daha sonuna gelmiş oluyoruz. Umuyoruz ki burada öğrendikleriniz sizin için faydalı olur. Eğer bu yıl yarışmaya katılmak istiyorsanız şu an başlamak için harika bir zaman! Bir sonraki yazıya kadar kendinize çok iyi bakın. 😌 İyi şanslar! 🙌

Bizi daha yakından takip etmek istiyorsanız, sosyal medya hesaplarımıza aşağıdan ulaşabilirsiniz!

Twitter | Instagram | Facebook

--

--

M. Bertan Tarakçıoğlu
TurkishKit

18, He/Him, Incoming CS at Stevens Institute of Technology, IBDP Graduate, Apple Developer, Maker, Three-Time Apple WWDC Scholar, MUN Delegate