NEW: Join my free 100 Days of SwiftUI challenge today! >>

FileManager ile görselleri listeleme

Size sağladığım görseller, bir Amerikan hükümet ajansı olan "National Oceanic and Atmospheric Administration (NOAA)"dan geliyor. Bu şekilde biz de kamuya açık olarak üretilen alan içeriğini serbestçe kullanabiliyoruz. Onları projenize kopyaladığınızda, Xcode bitmiş ürününüzün içine otomatik olarak onları derleyecek ve böylece kullanabileceksiniz.

Arka plana baktığınızda, bir iOS uygulaması aslında birçok dosya içeren bir dizindir: Binary'nin kendisi (bu, kodunuzun çalışmaya hazır olan derlenmiş versiyonudur), uygulamanızın kullandığı tüm ortam varlıkları, tüm görsel şablonlarınız ve artı olarak metadata (üstveri) ile güvenlik yetkilendirmeleri gibi diğer her şey.

Bu uygulama dizinleri, bundle (bağlam) olarak adlandırılırlar ve .app dosya uzantısına sahiptirler. Medya dosyalarımız bu klasörlerde olduğu için, tüm dosyaların orada olduğunu sistemin bize söylemesini ve istediğimiz herhangi birini çıkartmasını isteyebiliriz. Tüm görsel adlarının "nssl" (National Severe Storms Laboratory'nin kısaltması) ile başladığını farketmişsinizdir. Bu yüzden yapacağımız iş basit: Uygulama dizinindeki tüm dosyaları listele ve "nssl" ile başlayanları çek.

Şimdilik, listeyi yükleyeceğiz ve Xcode'un dahili log (günlük) görüntüleyicisine yazdıracağız, ama yakında onları uygulamamız içinde görüntüleyeceğiz.

Gelelim ilk adıma: ViewController.swift adlı dosyayı açın. Bir view controller (görüntü kontrolörü), bilginin görüntülenmesi olarak en iyi şekilde düşünülebilir; bu da bizim için büyük boş bir ekran demektir. ViewController.swift adlı dosya bu boş ekranın görüntülemekten sorumludur ve şu anda çok fazla bir kod içermemektedir. Şu şekilde birşey görmeniz gerekiyor:

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
}

Devam etmeden önce, üzerinde durmak istediğim beş ilginç şeyi barındırıyor bu kod.

  1. Dosya, "bu dosya, iOS kullanıcı arayüz araç kitine başvuracak" anlamına gelen import UIKit ile başlıyor.
  2. class ViewController: UIViewController satırı, "ViewController adında, verileri gösterecek yeni bir ekran oluşturmak istiyorum" anlamına geliyor. "UI" ile başlayan bir veri tipi gördüğünüzde, bilin ki bu UIKit'ten geliyor. UIViewController, biz değiştirinceye kadar beyaz ve boş kalacak olan Apple'ın öntanımlı ekran tipidir.
  3. override func viewDidLoad() satırı, ViewController ekranımızın içindeki bir kod parçası olan, bir metod (kod bloğu) başlatır. override anahtar sözcüğü burada gereklidir, çünkü bu "Apple'ın UIViewControllerda öntanımlı olan davranışını değiştirmek istiyoruz" anlamına gelir. Ekran yüklendiğinde, viewDidLoad() çağırılır ve böylece değişiklik yapmanız için hazır hale gelir.
  4. Birçok { ve } karakterleri var. Parantezler (veya bazen süslü parantezler) olarak da bilinen bu semboller, bir kod yığınını işaretlemek için kullanılır ve kodun nerede başlayıp, nerede bittiğini kolayca anlayabilmek için parantezlerin içindeyken birkaç karakter içeriden başlamak gelenektir. En dış parantezler tüm bir ViewController veri tipini içerir ve daha iç parantezler ise viewDidLoad() metodunun başlangıcını ve sonunu işaretler.
  5. viewDidLoad(), super.viewDidLoad() yazan bir kod satırı ve bir de yorum satırı içerir (// ile başlayan satırlar). Bu super çağrısı, "benim kodumdan önce Apple'ın UIViewControllerın kendi kodunu çalıştır" anlamına gelir. Bunun kullanıldığını birçok kez göreceğiz.

İlerideki projeler için bu koda birçok kez geri geleceğiz; o yüzden, şimdilik bunlar size belirsiz gelirse kaygılanmayın.

Satır numaraları yok mu? Kodu okurken, satır numaralarının etkin hale getirilmesi oldukça çok işe yarar; böylece belirli bir kodu daha kolay bulabilirsiniz. Eğer Xcode'unuz önayarlı olarak satır numaralarını göstermiyorsa, onu şimdi etkin hale getirmenizi öneririm: Xcode menüsüne gidin ve Preferences'i (Tercihler) seçin. Ardından Text Editing'i (Metin Düzenleme) seçin ve "Line Numbers"ın (Satır Numaraları) onaylı olduğundan emin olun.

Daha önce söylediğim gibi, ekranın yüklendiği ve değişiklik yapılabilmesi için hazır olduğu zaman çağırılır. func viewDidLoad() { ve izleyen birkaç satır sonra gelen } arasındaki her şey metodun bir parçasıdır ve ekranı düzenlemeye başladığınızda çağırılır.

NSSL görsellerini yükleyecek olan metodun içine biraz daha kod yerleştireceğiz. super.viewDidLoad() satırının hemen altına şunu ekleyin:

let fm = FileManager.default
let path = Bundle.main.resourcePath!
let items = try! fm.contentsOfDirectory(atPath: path)

for item in items {
    if item.hasPrefix("nssl") {
        // this is a picture to load!
    }
}

Not: Bazı deneyimli Swift geliştiricileri bu kodu okuyacaklar, try!'ı görecekler ve bana kızgınlıklarını belirten bir eposta atacaklar. Böyle birşey yapmadan önce, lütfen okumaya devam edin.

Bu, hepsi yeni olan büyük bir kod yığını. Satır satır üzerinden geçelim:

  • let fm = FileManager.default satırı, fm adında bir sabit tanımlıyor ve FileManager.defaultden dönen değeri saklıyor. Bu, dosya sistemiyle çalışmamızı sağlayan bir veri tipidir ve bu kodla da biz onu, dosyaları aramak için kullanacağız.
  • let path = Bundle.main.resourcePath! satırı, uygulama bağlamımızın kaynak yolunu (path) ayarlayan path adında bir sabit tanımlıyor. Bağlamın (bundle), derlenmiş programımızı ve tüm varlıklarımızı (asset) içeren bir dizin olduğunu hatırlayın. Dolayısıyla bu satır, "uygulamama eklenen tüm bu görselleri nerede bulabileceğimi söyle bana" anlamına geliyor.
  • let items = try! fm.contentsOfDirectory(atPath: path) satırı, yoldaki dizinin içeriğini items adıyla ayarlayan üçüncü bir sabit tanımlıyor. Peki hangi yol? Önceki satırda döndürülen değer bu işte. Görebileceğiniz gibi, Apple'ın uzun metod isimleri, kodun kendi kendini anlatmasına gerçekten yardımcı oluyor! items sabiti, uygulamamız için kaynak dizinde bulunan tüm bu dosya adlarından oluşan bir dizidir; bir koleksiyondur.
  • for item in items { satırı bir döngü başlatıyor. Döngüler birçok defa çalıştırılacak kod bloklarıdır. Bu kodda döngü, uygulama bağlamında bulunan her bir eleman için bir kez çalışıyor. Yeni bir kod bloğu başlangıcının sinyalini veren satır sonundaki açık paranteze dikkat edin. Dört satır sonra da kapalı parantezi göreceksiniz. Bu parantezlerin içindeki her şey, döngünün devam ettiği her defasında çalıştırılacaktır. Bu satırın çevirisini şöyle yapabiliriz: "items sabitini, metin string serileri olarak dikkate al, sonrasında bu metin string'lerinin her birini çek ve onları item olarak adlandır; ardından devamındaki kodu çalıştır..."
  • if item.hasPrefix("nssl") { satırı, döngümüzdeki ilk satırdır. Bu noktaya gelene kadar, çalışacağımız ilk dosya adı hazır olacak ve item olarak adlandırılacak. Aradığımız dosyanın bu olup olmadığına karar vermek için, hasPrefix() metodunu kullanacağız: Bir parametre (aradığımız ön ek) alıyor ve geriye ya true ya da false değerini döndürüyor. Bu "if" ile başlayan satır bir şartlı ifadedir: Eğer "item", "nssl" ön ekine sahipse, ardından... Evet haklısınız, diğer açık parantez başka bir yeni kod bloğunu işaretliyor. Bu kez, sadece hasPrefix() metodu true değerini döndürüyorsa kod çalıştırılacak.
  • Son olarak, // this is a picture to load! satırı bir yorumdur; buraya ulaştıysak, item değişkeni bağlamımızdan görsel ismini içerecektir. Dolayısıyla onu bir yerde saklamamız gerekiyor.

Şu sadece birkaç satırlık kodda ise, anlamanız gereken oldukça çok şey var, o yüzden devam etmeden önce, yeniden üstünden geçelim:

  • Sabitleri tanımlamak için let kullanırız. Sabitler, başvurmak istediğimiz veri parçalarıdır, ama sahip oldukları değerleri değiştiremeyeceğimizi biliyoruz. Örneğin, doğum gününüz bir sabit olsun, ama yaşınız sabit değildir; yaşınız değişken olacaktır, çünkü değişir.
  • Swift geliştiricileri, başkalarının değişken kullandığı yerlerde sabitleri kullanmayı çok severler. Bunun sebebi, gerçekten kodlamaya başladığınızda, depoladığınız verinin aslında pek fazla değişmediğini farketmeye başladığınızdandır. Dolayısıyla onları sabit olarak tanımlarsınız. Böyle yaparak, sistemin kodunuzu daha hızlı çalıştırmasını sağlarsınız ve aynı zamanda bu fazladan güvenlik ekler, çünkü Xcode kodu değiştirmeye çalıştığınızda uygulamanızı derlemeyi reddeder.
  • Swift dilinde metin, String veri tipinin kullanımıyla sunulmuştur. Swift string'leri son derece güçlüdür ve aklınıza gelen her dille çalışabilir; İngilizce, Çince, Klingonca ve daha fazlası.
  • Değerler koleksiyonuna diziler denir ve genellikle tek bir veri tipi tutmasıyla sınırlandırılmıştır. String'lerden oluşan bir dizi [String] olarak yazılır ve sadece string'leri tutabilir. Eğer sayı yerleştirmeye çalışırsanız, Xcode uygulamanızı derlemeyecektir.
  • try! anahtar sözcüğü, "ardından gelen kod potansiyel bir hataya sahip, ama onun hata vermeyeceğinden kesinlikle eminim" anlamına gelir. Eğer kod hata yaparsa, örneğin aradığımız dizin orada yoksa, uygulamamız çökecektir.
  • Bu durumda try! çağrısı yapmak son derece iyidir, çünkü bu kod hata verirse, uygulamamız kendi verisini okuyamayaz, dolayısıyla bir şeyler ciddi bir şekilde yanlış gidiyor demektir! Bazı Swift geliştiricileri bu felaket hataları başlangıç zamanında ele alacak kodlar yazmaya girişirler, ama ne üzücüdür ki, oluşan asıl problemi sık sık sadece maskelerler.
  • Dizideki her bir eleman için for someItem in someArray döngüsünü kullanabilirsiniz. Swift her bir elemanı çeker ve her eleman için birer defa olmak üzere döngünüz içindeki kodu çalıştırır.

Eğer son derece gözlemci biriyseniz, Swift'in en karmaşık parçası olan çok ama çok küçük bir şeyi farketmiş olabilirsiniz. O yüzen şimdilik olabildiğince basit tutacağım: Bundle.main.resourcePath! ibaresinin sonundaki ünlem işareti.

Hayır, bu bir yazım hatası değil. Eğer bu ünlem işaretini çıkarsanız, kodunuz çalışmaz. Yani açıkça Xcode bunun önemli olduğunu düşünüyor; ki, gerçekten de öyle. Swift dili verilerle üç şekilde çalışır:

  1. Veriyi tutan bir değişken veya bir sabit. Örneğin name: String, bir dizi harften oluşuyor ve name olarak adlandırılıyor.
  2. Bir değişken veya bir sabit verileri tutabilir de, tutmayabilir de; bundan emin değiliz. Buna optional type (seçimli tip) adı verilir ve şuna benzer: name: String?. Bunu doğrudan kullanamazsınız; Swift dilinden, onların bir değer içerip içermediğini kontrol etmesini istersiniz.
  3. Bir değişken veya sabit bir değer içerebilir de, içermeyebilir de. Ama içerdiğinden %100 eminiz; en azından ayarlanmış bir ilk değere sahip. Buna "implicitly unwrapped optional" (dolaylı olarak açılan optional'lar) denir ve şuna benzer: name: String! Bunları doğrudan kullanmanızda sakınca yoktur.

Bunu insanlara açıkladığımda, hemen hemen her zaman kafaları karıştı. O yüzden yukarıda anlatılanlar anlamlı gelmediyse, lütfen kaygılanmayın; sonraki projelerde tekrar tekrar optional's konusuna gireceğiz, o yüzden kendize zaman tanıyın.

Optionals konusuna daha sonra derinlemesine bakacağız, ama şimdilik önemli olan Bundle.main.resourcePath ifadesinin bir string döndürüp döndürmeyeceği konusudur. Dolayısıyla String? ifadesinin döndürdüğü şey bir optional string'dir. Sonuna ünlem işaretini ekleyerek, optional string'i açmaya zorluyoruz; bu da "bunun gerçek bir string döndüreceğinden emin değil, ama asla nil olmayacak, o yüzden lütfen onu sıradan bir string olarak ver bana" anlamına gelir.

Önemli uyarı: Eğer nil değerine sahip bir sabit veya değişken kullanmayı denediyseniz, uygulamanız çözecektir. Sonuç olarak, bazı insanlar ! kullanmayı "crash" (çökme) operatörü olarak adlandırırlar, çünkü yanlış anlaşılması kolaydır. Aynı try!ın true değerini vermesindeki gibi; kolaylıkla yanlış anlaşılabilir. Eğer şimdilik bunlar size zor geliyorsa, kaygılanmayın. Çünkü daha sonra bunu kullanacaksınız ve zaman içinde size daha anlamlı gelecek.

Kodumuz uygulamamız içinde bulunan dosyaların listesini yüklediği anda, "nssl" ile başlayan isimleri bulmak için hepsini döngüye sokar. Ama yine de, aslında bu dosyalarla pek fazla birşey yapmıyor. Dolayısıyla sonraki adımımız "nssl" görsellerinden oluşan bir dizi oluşturmak olacaktır ki, sonrasında kaynak dizinini tekrar tekrar okumaktansa, ona başvuralım.

Üç tane sabit oluşturmuştuk: fm, path, ve items. Bunlar viewDidLoad() metodunun içinde yaşayacaklar ve metod biter bitmez yok olacaklar. İstediğimiz şey, tüm ViewController tipine veri eklemenin bir yoludur. Öyle ki, ekranımız varolduğu sürece onlar da varolsun. Swift dilinde bu "property" (özellik) kullanarak yapılır: ViewController'a istediğimiz kadar çok bu özelliklerden verebiliriz, sonrasında ekran varken gerektiği kadar sık onları okur ve yazarız.

Bir özellik oluşturmak için, onu metodun dışında tanımlamanız gereklidir. Şimdiye kadar let kullanarak sabitleri oluşturduk, ama bu dizi döngümüz içinde değiştirilecek, o yüzden değişken olarak tanımlayacağız. Tabi aynı zamanda Swift'e onun ne tür bir veri tutacağını da söylemeliyiz; kodumuza göre, her bir eleman bir "nssl" görselinin adı olacağı için, bu bir string dizisi olacak.

Şu satırı viewDidLoad()'tan önce kodunuza ekleyin:

var pictures = [String]()

Eğer doğru bir şekilde yerleştirdiyseniz, kodunuz şu şekilde olması gereklidir:

class ViewController: UIViewController {
    var pictures = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        let fm = FileManager.default

var anahtar sözcüğü değişken oluşturmak için kullanılır; aynı şekilde let de sabitleri oluşturmak için kullanılır. Satırın ikinci yarısında işler karışmaya başlıyor: [String](). Burada aslında iki şey bir tanesinin içinde: [String] ifadesi "string'lerden oluşan bir dizi" ve () ise "şimdi bir adet oluştur" anlamına gelir. Burada parantezler tam olarak viewDidLoad() metodundaki gibidirler; çalışması gereken diğer kodun adını işaret eder ve bu durumda da string'lerden oluşan yeni bir diziyi oluşturacak kodun adını işaret ediyor.

Bu pictures, ViewController ekranı oluşturulduğunda yaratılacak ve ekran varolduğu sürece o da varolacak. İçi boş olacak, çünkü içini aslında hiçbir şeyle doldurmadık, ama en azından doldurmamız için hazır olarak orada bekliyor.

pictures dizisine gerçekten eklemek istediğimiz şey, döngümüzün içinde eşlediğimiz tüm dosyalardır. Bunu yapmak için, varolan // this is a picture to load! yorum satırını, pictures dizisine her bir görseli ekleyecek kodla değiştirmemiz gerekiyor.

Ne mutlu ki, Swift dizileri istediğimiz herhangi bir elemanı eklemek için kullanabileceğimiz append adında dahili bir metoda sahipler. Şimdi // this is a picture to load! yorumunu şununla değiştirin:

pictures.append(item)

İşte bu kadar! Sinir bozucu bir şekilde, bu kadar çalışmadan sonra uygulamamız "play"e bastığınızda birşeyler yapıyor gibi görünmeyecek; daha önceden olduğu gibi aynı beyaz ekranı göreceksiniz. Çalışmıyor mu veya birşeyler sesizce hata mı veriyor?

Bunu ortaya çıkarmak için, viewDidLoad()'ın sonuna şu kod satırını ekleyin; tam kapalı parantezinin öncesine:

print(pictures)

Bu kod Swift'e, Xcode'un derleme penceresine pictures dizisinin içeriğini yazdırmasını söylüyor. Şimdi programı çalıştırdığınızda, Xcode penceresinin altında bu metni görmelisiniz: “["nssl0033.jpg", "nssl0034.jpg", "nssl0041.jpg", "nssl0042.jpg", "nssl0043.jpg", "nssl0045.jpg", "nssl0046.jpg", "nssl0049.jpg", "nssl0051.jpg", "nssl0091.jpg”]”

Not: iOS, Xcode'un derleme konsolunda ilgimizi çekmeyen birçok derleme mesajı yazdırmayı sever. Eğer tanımlayamadığınız birçok metnin orada olduğunu görürseniz, üzülmeyin; üstünde metni görünceye kadar pencereyi kaydırın; eğer metni görürseniz, her şey yolunda demektir.

SAVE 20% ON iOS CONF SG The largest iOS conference in Southeast Asia is back in Singapore for the 5th time in January 2020, now with two days of workshops plus two days of talks on SwiftUI, Combine, GraphQL, and more! Save a massive 20% on your tickets by clicking on this link.

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!