Swift Academy · Pelajaran

Penutupan

Penutupan

Pelajaran 1 daripada 129 langkah

Penutupan ialah pelajaran Swift Academy percuma di CoddyKit. Ini ialah pelajaran 1 daripada 1. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Swift Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Swift Academy merangkumi sejumlah 1 pelajaran.

Pengenalan

Helo,

Penutupan ialah blok kod yang berdikari. Penutupan dihantar sebagai parameter kepada kod, atau boleh digunakan di dalam kod.

Penutupan ialah sejenis fungsi. Penutupan boleh digunakan dengan menghantarnya dalam kod. Penutupan ini serupa dengan lambda dalam bahasa pengaturcaraan lain.

Pengurusan Memori

Salah satu perkara yang paling penting ialah penutupan boleh menyimpan nilai pemalar dan pemboleh ubah dalam konteks tempat penutupan itu ditakrifkan.

Proses ini dikenali sebagai penangkapan nilai daripada konteks luar.

Swift mengurus memori untuk kita semasa proses penyimpanan ini.

Jenis Penutupan

Terdapat beberapa jenis penutupan.

  1. Fungsi global ialah penutupan yang mempunyai nama. Fungsi ini tidak menyimpan sebarang nilai.
  2. Fungsi bersarang boleh membawa nilai nama dan fungsi yang dibungkus di dalamnya.
  3. Ungkapan penutupan pula ialah penutupan tanpa nama yang boleh menyimpan data daripada konteks yang mengelilinginya menggunakan sintaks yang ringkas.

Sintaks Penutupan

Sintaks penutupan cuba dipermudah sebanyak mungkin. Antara ciri yang paling penting adalah seperti berikut.

  • Parameter dalam penutupan boleh ditentukan secara automatik.
  • Nilai pulangan boleh ditentukan secara automatik.
  • Pulangan penutupan boleh ditulis dalam satu baris.
  • Nama argumen boleh dinyatakan sebagai singkatan seperti $ 0 atau $ 1.
  • Sintaks TRAILING CLOSURE boleh digunakan.

Maklumat

Ungkapan penutupan bermaksud menulis penutupan secara sebaris dengan menumpukan pada sintaks dan kesederhanaan.

Sintaks Penutupan

Sintaks penutupan ditunjukkan dalam kod contoh di bawah.

{ (parameters) -> return type in
    statements
}


func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
//If we didn't use closures, our code structure would be as follows.

var reversedNames = names.sorted(by: backward)

Sintaks Penutupan

Namun begitu, dengan menggunakan penutupan, kita tidak perlu mentakrifkan penutupan global yang mempunyai nama secara tidak perlu.

Memadai untuk mentakrifkan ungkapan penutupan yang ringkas dalam parameter. Mari kita lihat contohnya.

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

print(reversedNames)

///sorted method takes closure as parameter.

Kata Kunci in

Kita dapat memahami bahawa badan penutupan bermula apabila melihat kata kunci in.

Sebelum kata kunci in dimulakan, parameter yang diterima oleh penutupan dan jenis pulangan perlu ditakrifkan.

Menentukan Jenis daripada Konteks

Dalam contoh di atas, ungkapan penutupan boleh difahami dengan menentukan parameter dan jenis pulangan secara automatik kerana kaedah sorted menerima penutupan.

Oleh itu, kita tidak perlu mentakrifkannya secara berasingan.

Dalam contoh ini, jenis nilai dalam tatasusunan names akan difahami sebagai String, maka parameter yang diterima oleh penutupan juga akan mempunyai jenis String.

Begitu juga, penutupan tersebut memerlukan jenis Bool untuk melakukan pengisihan, maka jenis pulangan akan ditentukan sebagai Bool.

Contoh

Hal ini akan memudahkan penggunaan seperti di bawah.

Anak panah juga boleh digugurkan daripada kod kerana jenis pulangan telah ditentukan secara automatik.

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

print(reversedNames)

Sintaks Ringkas

Penggunaan sintaks panjang berbanding sintaks ringkas lebih sesuai untuk mengelakkan pembaca kod berasa keliru.

Sintaks di atas boleh dipendekkan lagi.

Nilai pulangan boleh dipendekkan dalam ungkapan penutupan dengan membuang kata kunci return.

/*
In this example, the return keyword has been extracted.
It already has single expression. 
There is no need to express it as an extra with return.
*/

var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
print(reversedNames)

Contoh

Dalam contoh ini, kata kunci return telah digugurkan.

Ungkapan tersebut sudah pun tunggal, jadi tidak perlu menyatakannya secara berasingan menggunakan return.

reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )

Singkatan Nama

Sintaks ini boleh dipendekkan lagi. Dalam contoh di atas, kita menyatakan bahawa penutupan menerima dua parameter, termasuk s1 dan s2. Jenis kedua-duanya ditentukan secara automatik.

Kini kita boleh mengelakkan keperluan menyatakan parameter ini secara terperinci dengan menggunakan singkatan.

Selain itu, kerana tiada definisi parameter dan nilai pulangan yang perlu dihantar, kata kunci in juga boleh digugurkan.

let names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { $0 > $1 } )
print(reversedNames)

// In this example $0 will shortcut the first parameter and $1 will shortcut the second parameter.

Contoh Pemendekan

var names = ["Coddy", "Kit"]

let reversedNames = names.sorted(by: >)
print(reversedNames)
// Greater than operator takes two parameters and the rotation type is squat.

TRAILING CLOSURE

Jika parameter yang dihantar kepada fungsi penutupan ialah argumen terakhir fungsi tersebut dan ungkapan penutupan itu panjang, mungkin lebih berguna untuk menulisnya sebagai pernyataan TRAILING CLOSURE.

Kita boleh menggunakan TRAILING CLOSURE sebagai gula sintaks. Tujuannya adalah untuk meningkatkan keterbacaan kod.

Parameter terakhir bagi kebanyakan kaedah iOS ialah penutupan.

Parameter Akhir

Contohnya, dalam contoh ini, parameter terakhir ialah penutupan.

class Animator {
    class func animate(withDuration duration: Double, animations: () -> Void) {
        animations()
    }
}

class MyViewController {
    func start() {
        // With the traditional method, we can call this fund as follows.
        Animator.animate(withDuration: 1, animations: { [unowned self] in
            print("red")
        })
    }
}
MyViewController().start()

Oleh sebab kod di atas kurang mudah dibaca, kod tersebut boleh ditulis seperti berikut

Oleh sebab kod di atas kurang mudah dibaca, kod tersebut boleh ditulis seperti berikut.

import Foundation
Thread.sleep(forTimeInterval: 1)
print("Background color changed to red")

Contoh

Apabila menggunakan sintaks TRAILING CLOSURE, kita tidak perlu menulis label argumen.

Hal ini kerana penutupan kini telah menjadi sebahagian daripada panggilan fungsi.

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // function body goes here
}

// Here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure(closure: {
    // closure's body goes here
})

// Here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
    // trailing closure's body goes here
}

Sintaks

Kita sebenarnya boleh menganggap sintaks TRAILING CLOSURE sebagai gula sintaks. Sintaks ini menjadikan kod lebih mudah dibaca.

/*
In the example below, animations
are expressed as closure.
*/
public class func animate(withDuration: TimeInterval, animations: () -> Void)

// In traditional usage, we need to make a call like the following.
UIView.animate(withDuration: 1, animations: { [unowned self] in
    self.view.backgroundColor = UIColor.red
})

/*
In this way, both the readability of the code
increases and we avoid the use of extra brackets.
If it is as above and the last parameter of the method 
is closure, Swift allows to make a call like the one below.
*/

UIView.animate(withDuration: 1) { [unowned self] in
    self.view.backgroundColor = UIColor.red
}

Kita Boleh Menggunakan Kod di Bawah untuk Menguji Kod

Kita boleh menggunakan kod di bawah untuk menguji kod.


func greetThenRunClosure(name: String, closure: () -> ()) {
    print("Hello, \(name)!")
    closure()
}

greetThenRunClosure(name: "Paul") {
    print("The closure was run")
}

Penangkapan Nilai oleh Penutupan

Penutupan boleh menangkap nilai pemboleh ubah daripada persekitaran yang mengelilinginya. Anda juga boleh mengubah nilai pemboleh ubah ini dari dalam badan penutupan itu sendiri dan mengaksesnya.

Hal ini tetap berlaku walaupun pemboleh ubah tersebut tidak lagi berada dalam skop asal tempat ia ditakrifkan.

Sambungan

Secara umum, fungsi bersarang dan ungkapan penutupan boleh menyimpan data ini bersama-sama. Penutupan boleh menyimpan data daripada fungsi luar.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

let incrementByTen = makeIncrementer(forIncrement: 10)

print(incrementByTen())
// returns a value of 10
print(incrementByTen())
// returns a value of 20
print(incrementByTen())
// returns a value of 30

Sambungan

Jika anda menetapkan penutupan sebagai sifat kelas, penutupan itu akan mula menyimpan rujukan kepada tika ini.

Oleh itu, kitaran rujukan kuat akan terbentuk antara penutupan dan tika tersebut.

Perhatian khusus perlu diberikan terhadap kebocoran memori.

Amaran

Penutupan dan fungsi ialah jenis rujukan.

@escaping

Kita mungkin memerlukan penggunaan ini di banyak tempat yang menggunakan penutupan secara tak segerak.

Dalam versi awal Swift (1 dan 2), penutupan dalam parameter Swift bersifat escaping dan kemudiannya menjadi tidak escaping. Jika kita perlu menghantar penutupan sebagai tidak escaping, kita perlu menyatakannya secara khusus.

Dalam versi seterusnya, parameter penutupan dijadikan tidak escaping untuk menjimatkan penggunaan memori.

Kini, jika kita mahu mentakrifkan penutupan sebagai escaping, kita perlu menggunakan kata kunci @escaping.

Kata Kunci @ESCAPING

Jika kita mahu dapat memanggil penutupan yang dihantar kepada fungsi selepas fungsi itu selesai, kita perlu menandakannya dengan kata kunci @escaping.

Penutupan yang ditakrifkan secara lalai sebagai parameter fungsi ialah jenis rujukan, tetapi penutupan itu tidak menambah kiraan rujukan. Hal ini kerana hayat penutupan tersebut berakhir sebaik sahaja panggilan selesai, jadi kita tidak perlu menambah kiraan rujukan.

Namun, jika kita memerlukan penutupan tersebut sebagai parameter selepas fungsi dipanggil, kita mungkin perlu menyatakannya menggunakan kata kunci @escaping.

nonEscaping

Mula-mula, mari kita lihat cara penutupan nonEscaping berfungsi.

Apabila penutupan ini dihantar sebagai parameter kepada fungsi, penutupan tersebut diproses dalam badan fungsi dan kemudian dikembalikan kepada pengompil.

Selepas fungsi dikembalikan, iaitu selepas pelaksanaan selesai, penutupan itu tidak lagi berada dalam skop dan memorinya dibebaskan.

Menggunakan Penutupan Escaping

Apabila fungsi penutupan dihantar sebagai argumen, penutupan itu terus disimpan walaupun fungsi tersebut dikembalikan dan pelaksanaan selesai.

Penutupan itu menggunakan ruang dalam memori sehingga dilaksanakan. Terdapat beberapa jenis penutupan escaping.

Tahniah

Tahniah 🎉

Kita telah sampai ke penghujung pelajaran ini. 

Jumpa lagi dalam pelajaran seterusnya 😎

Penutupan — ilustrasi 29
Percuma untuk bermula

Pelajari Swift dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
122
Pelajaran
409

Soalan Lazim

Adakah pelajaran “Penutupan” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Swift Academy, termasuk “Penutupan”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Swift Academy merangkumi sejumlah 1 pelajaran.

Apakah yang akan saya pelajari dalam “Penutupan”?

Penutupan Anda berlatih Swift Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Swift Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Swift Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 1.

Berapa lamakah pelajaran “Penutupan” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Swift Academy ini?

Ya. Setiap pelajaran Swift Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

← Kembali ke Swift Academy