Ketakutan hanya perlahan apabila saya menyedari bahawa saya mula kehabisan stok gambar ini

Swift + Inisialisasi dengan Closures

Closures F.T.W.

Nota pantas - semua catatan masa depan saya akan diterbitkan di laman web khusus saya dan penerbitan ini tidak lagi dikemas kini. Terima kasih untuk membaca!

Saya mula benar-benar menggali tarian inisiasi penuh di Swift. Saya menulis tentangnya. Saya menulis tentang mengapa ia berfungsi seperti yang dilakukannya. Saya bercakap mengenainya. Saya membacanya (banyak). Tetapi, saya kembali untuk satu lagi perkara mengenai perkara itu.

Daripada semua cara yang banyak, indah dan pelbagai, seseorang boleh memulakan sesuatu di Swift - menggunakan penutupan biasanya tidak dibangkitkan sebagai kaedah untuk melakukannya. Tetapi malangnya, ia boleh membuat kod boilerplatey ™ init () lebih kurang menyakitkan dan sedikit lebih mudah diurus.

Untuk antara muka pengguna programmatic devs out there - yang ini untuk anda !

UIKit == UIHugeSetupCode ()

Lihat, itu bukan kesalahan UIKIT. Komponen yang perlu berinteraksi dengan pengguna meminjamkan diri ke gunung kod persediaan, kerana pilihan. Biasanya, banyak perkara ini mendapati dirinya dalam either viewDidLoad atau loadView:

menimpa func loadView ()
{
    mari helloWorldLbl = UILabel ()
    helloWorldLbl.text = NSLocalizedString ("controller.topLbl.helloWorld", komen: "Hello World!")
    helloWorldLbl.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    helloWorldLbl.textColor = UIColor.whiteColor ()
    helloWorldLbl.textAlignment = .Center
    self.view.addSubview (helloWorldLbl)
}

Ini agak standard bagi kita yang mencuba perairan Koko Cocoa tanpa .xib atau .storyboard. Walaupun, jika anda berkongsi cintaku terhadap kaedah pandangan ViewDidLoad atau loadView yang minuscule, anda boleh meletakkannya di tempat lain.

Katakanlah, harta:

mari helloWorldLbl: UILabel = {
    mari lbl = UILabel ()
    lbl.text = NSLocalizedString ("controller.topLbl.helloWorld", komen: "Hello World!")
    lbl.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    lbl.textColor = UIColor.whiteColor ()
    lbl.textAlignment = .Center
    kembali lbl
} ()

Cantik. Dalam buku Apple sendiri di Swift, ia menyatakan bahawa "jika nilai lalai harta anda memerlukan beberapa penyesuaian atau persediaan, anda boleh menggunakan penutupan atau fungsi global untuk memberikan nilai lalai tersuai untuk harta tersebut." Seperti yang telah disebutkan sebelumnya, UIKit mengawal hasil banyak penyesuaian dan persediaan.

Salah satu produk sampingan yang cantik, bagaimanapun, adalah bagaimana bebanView kelihatan sekarang:

menimpa beban loadView
{
    self.view.addSubview (self.helloWorldLbl)
}

Walau bagaimanapun, ambil perhatian "()" pada akhir penutupan dalam perisytiharan harta. Ini membiarkan ahli-ahli sihir Swift kecil yang menyusun kod anda tahu bahawa contoh sedang diberikan kepada jenis pemulangan penutupan. Sekiranya kita menghilangkan ini, mungkin kita dapat menetapkan penutupan sebenar itu sendiri.

Dan dalam kes ini, itu .

Peraturan adalah Peraturan

Walaupun kita mempunyai mainan baru yang berkilat, sangat penting untuk mengingati peraturan tanah. Memandangkan kami menyerahkan harta kepada penutupan, yang lain yang mengandungi contohnya mungkin belum dimulakan. Kerana itu, apabila penutupan dilaksanakan - tidak mungkin untuk merujuk nilai-nilai harta benda atau diri sendiri dari dalamnya.

Sebagai contoh:

mari helloWorldLbl: UILabel = {
    mari lbl = UILabel ()
    lbl.text = self.someFunctionToDetermineText () // Error compiler
    lbl.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    lbl.textColor = self.myAppTheme.textColor () // Satu lagi ralat
    lbl.textAlignment = .Center
    kembali lbl
} ()

Contoh diri mungkin tidak selamat digunakan, atau mungkin tidak melalui proses inisialisasi dua fase Swift. Perkara yang sama benar berlaku bagi apa-apa sifat hartanah, yang mungkin atau tidak boleh diperuntukkan dan dimulakan sejak penutupan dilaksanakan dengan serta-merta.

Ini adalah satu kelebihan tetapi pasti, merugikan dengan menggunakan penutupan permulaan. Ia masuk akal, walaupun - dan ia betul seiring dengan salah satu daripada tiga matlamat reka bentuk Swift: keselamatan.

Gettin 'Cute dengan Koleksi

Salah satu bidang di mana saya telah menemui teknik ini amat berguna adalah dengan contoh yang mewakili salah satu daripada pelbagai koleksi yang berbeza di Swift. Daripada banyak bakat Swift, mengiris dan menyaring koleksi dengan kuasa seribu naga sebagai salah satu kegemaran saya.

Perhatikan contoh berikut, yang diambil dari pemula dalam projek yang sedang saya kerjakan. Kelas yang menempatkan kod ini mempunyai sifat [Pemaju]. Pada pelancaran baru, saya menetapkan nilai awal mereka dari fail .plist. Selepas itu, ini disimpan melalui NSKeyedArchiver.

pengawal membiarkan devs = NSKeyedUnarchiver.unarchiveObjectWithFile (DevDataManager.ArchiveURL.path!) sebagai? [Pemaju] lain
{
    self.developers = {
        biarkan pListData = // Dapatkan data plist
        var devArray: [Developer] = [Developer] ()
        // Menyediakan devArray dari data plist
        kembali devArray.map {$ 0.setLocation ()}
                       .filter {$ 0.isRentable}
                       .sort {$ 0.name <$ 1.name}
     } ()
    kembali
}
self.developers = devs

Saya agak seperti pendekatan ini, kerana walaupun kita tidak menggunakannya di luar pemula, niat kod itu sangat jelas kerana ia hanya bertanggungjawab untuk menetapkan suatu harta.

Memandangkan pemula dan pandanganDidLoad menimpa menjadi lebih besar, perkara-perkara seksyen seperti ini (sekurang-kurangnya) adalah hadiah selamat datang dari segi kebolehbacaan.

Mendapatkan NSCute

Jika anda benar-benar menggali permulaan perkara dengan penutupan, tetapi mengalami kekurangan yang teruk menggunakan $ itu berfungsi dalam kod anda, bersorak. Menggunakan beberapa Swiftery yang mahir, seseorang boleh mengarang beberapa kod yang menyerupai jenis dalam penutupan itu sendiri, yang menghasilkan beberapa konfigurasi gaya pro. Pertimbangkan kod ini, yang pertama kali saya temui pada NSHipster yang sentiasa bermaklumat:

@warn_unused_result
public func Init  (value: Type, @noescape block: (object: Type) -> Void) -> Type
{
    blok (objek: nilai)
    nilai pulangan
}

Saya suka di mana ini berlaku. Fungsi awam yang mengambil penutupan dengan objek ditaip menggunakan generik, yang kemudian mengembalikan jenis itu. Ini bermakna anda boleh menghidupkan dan memulakan sesuatu dengan maklumat jenis yang lebih banyak. Sampel kod pertama kami kemudiannya akan kelihatan seperti ini:

mari helloWorldLbl = Init (UILabel ()) {
    $ 0.text = NSLocalizedString ("controller.topLbl.helloWorld", komen: "Hello World!")
    $ 0.font = UIFont.preferredFontForTextStyle (UIFontTextStyleBody)
    $ 0.textColor = UIColor.whiteColor ()
    $ 0.textAlignment = .Center
}

Fancy walaupun nampaknya, ia memang membunuh keperluan pembolehubah contoh dari dalam penutupan, dan ia menghilangkan keperluan "()". Sangat bagus .

Pemikiran Akhir

Boleh dikatakan bahawa menggunakan teknik sedemikian adalah enam dalam satu tangan, dan setengah dozen di sisi lain. Walaupun benar barisan kod yang ditulis oleh pengaturcara masih sebahagian besarnya sama, saya berpendapat bahawa penempatan dan kelenturan menjadikannya ideal untuk banyak senario.

Ini cara yang menyeronokkan untuk menyelesaikan sesuatu, dan ada beberapa cara untuk melakukan perkara yang sama di Objektif-C rakan lama kita. Tetapi hei, semakin anda tahu, amirite?

Sehingga nextWeek = {mari minggu = Minggu () week.advancedBy (hari: 7)} ()

Jordan Morgan adalah jurutera perisian iOS yang menjalankan Dreaming In Binary

Sekiranya anda mengetahui tentang penggunaan penutupan untuk pemula, jangan ragu untuk meneruskan dan NSRecommend (ini, di mana: di bawah);