Swift 5.1 - apa yang baru?



Swift 5.0 menjadi tersedia dengan rilis Xcode 10.2, tetapi bekerja pada versi berikutnya berlanjut dan sudah ada berita tentang apa yang dapat Anda harapkan di dalamnya.

Fitur utama dari Swift 5.1 adalah stabilitas modul , yang memungkinkan kita untuk menggunakan pustaka pihak ketiga tanpa khawatir tentang versi kompiler Swift mana mereka diciptakan. Sepertinya stabilitas ABI yang kami dapatkan di Swift 5.0, tetapi ada sedikit perbedaan: stabilitas ABI menyelesaikan perbedaan dalam versi Swift saat runtime, dan stabilitas modul pada waktu kompilasi.

Selain inovasi penting ini, kami akan menerima beberapa peningkatan penting dalam Swift, dan dalam artikel ini kami akan membahasnya dengan contoh-contoh sehingga Anda dapat melihatnya dalam aksi.

Diri Universal


SE-0068 memperluas penggunaan Diri , sehingga mengacu pada jenis yang mengandungnya dalam kelas, struktur, dan enumerasi. Ini biasanya berguna untuk tipe dinamis ketika perlu untuk menentukan tipe yang tepat dari sesuatu saat runtime.

Sebagai contoh, pertimbangkan kode berikut:

class NetworkManager { class var maximumActiveRequests: Int { return 4 } func printDebugData() { print("Maximum network requests: \(NetworkManager.maximumActiveRequests).") } } 

Di sini kita mendefinisikan properti statis maximumActiveRequests di dalam kelas NetworkManager dan menambahkan metode printDebugData () untuk mencetak properti ini. Semuanya baik-baik saja di sini, tetapi hanya sampai kami memutuskan untuk mewarisi dari NetworkManager :

 class ThrottledNetworkManager: NetworkManager { override class var maximumActiveRequests: Int { return 1 } } 

Dalam pewaris ini, kita mengubah properti maksimumActiveRequests sehingga sekarang menjadi sama dengan satu, tetapi jika kita memanggil printDebugData () , itu akan menyimpulkan nilai dari kelas induk:

 let manager = ThrottledNetworkManager() manager.printDebugData() 

Di sini kita harus mendapatkan 1 bukannya 4, dan inilah penyelamatan SE-0068: kita dapat menggunakan Self (dengan huruf kapital 'S') untuk merujuk pada tipe saat ini. Jadi sekarang kita dapat menulis ulang metode printDebugData () dari kelas induk seperti ini:

 class ImprovedNetworkManager { class var maximumActiveRequests: Int { return 4 } func printDebugData() { print("Maximum network requests: \(Self.maximumActiveRequests).") } } 

Yaitu, Self bekerja dengan cara yang sama seperti itu bekerja dalam protokol di versi Swift sebelumnya.

Peringatan untuk ambiguitas tidak ada


Opsional di Swift diimplementasikan sebagai enumerasi dengan dua opsi: beberapa dan tidak ada . Ini dapat menyebabkan kebingungan jika kita membuat enumerasi kita sendiri yang tidak memiliki opsi dan membungkusnya dalam opsional . Sebagai contoh:

 enum BorderStyle { case none case solid(thickness: Int) } 

Saat menggunakan non-opsional, semuanya bersih:

 let border1: BorderStyle = .none print(border1) 

Ini akan menghasilkan "tidak ada". Tetapi jika kita menggunakan opsional untuk enumerasi ini, maka kita akan menghadapi masalah:

 let border2: BorderStyle? = .none print(border2) 

Nil akan dicetak di sini, karena Swift percaya bahwa .none berarti opsional kosong , meskipun sebenarnya opsional dengan nilai BorderStyle.none.
Dalam Swift 5.1, jika terjadi ambiguitas, peringatan akan ditampilkan:
"Anggap saja maksudmu 'Opsional. Tidak Ada'; Apakah maksud Anda 'BorderStyle.none' bukan? "
Dengan demikian, pengembang akan diberitahu bahwa dengan kodenya tidak semuanya bisa mulus.

Pencocokan enumerasi opsional dan non-opsional


Swift cukup pintar untuk memahami konstruksi sakelar / kasus saat menggabungkan teks opsional / non-opsional dan nilai integer, tetapi tidak dalam hal enumerasi.

Sekarang di Swift 5.1 kita dapat menggunakan sakelar / kasing untuk mencocokkan opsi enumerasi-opsional dan non-opsional:

 enum BuildStatus { case starting case inProgress case complete } let status: BuildStatus? = .inProgress switch status { case .inProgress: print("Build is starting…") case .complete: print("Build is complete!") default: print("Some other build status") } 

Swift dapat memetakan enumerasi opsional ke opsi non-opsional, dan "Build sedang dimulai ..." akan ditampilkan di sini.

Bandingkan koleksi yang dipesan


SE-0240 memperkenalkan kemampuan untuk menghitung perbedaan antara koleksi yang dipesan, serta menerapkan hasil perbandingan yang dihasilkan untuk koleksi. Ini mungkin menarik bagi pengembang yang memiliki koleksi kompleks dalam tampilan tabel dan perlu menambah atau menghapus banyak elemen menggunakan animasi.

Prinsip dasarnya sederhana - Swift 5.1 menyediakan perbedaan metode baru (dari :) , yang menentukan perbedaan antara dua koleksi berurutan - elemen mana yang akan ditambahkan dan yang akan dihapus. Ini berlaku untuk semua koleksi yang dipesan yang berisi item yang mematuhi protokol Setara .

Untuk mendemonstrasikan ini, kita akan membuat dua array nilai, menghitung perbedaan satu dari yang lain, dan kemudian pergi melalui daftar perbedaan dan menerapkannya untuk membuat dua koleksi sama.

Catatan: karena Swift sekarang didistribusikan sebagai bagian dari sistem operasi Apple, alat bahasa baru harus digunakan dengan cek #available untuk memastikan bahwa kode berjalan pada OS yang mendukung fungsi yang diperlukan. Untuk fungsionalitas yang berjalan pada OS yang tidak dikenal dan tidak diumumkan yang mungkin dirilis di masa mendatang, nomor versi khusus digunakan, "9999", yang berarti: "Kami belum tahu nomor versi yang benar".

 var scores1 = [100, 91, 95, 98, 100] let scores2 = [100, 98, 95, 91, 100] if #available(iOS 9999, *) { let diff = scores2.difference(from: scores1) for change in diff { switch change { case .remove(let offset, _, _): scores1.remove(at: offset) case .insert(let offset, let element, _): scores1.insert(element, at: offset) } } print(scores1) } 

Untuk animasi yang lebih maju, kita bisa menggunakan parameter ketiga di daftar perbedaan yang dihasilkan: relatedWith . Jadi, alih-alih .insert (biarkan offset, biarkan elemen, _), kita dapat menulis .insert (biarkan offset, biarkan elemen, biarkan terkait Dengan ). Ini memberi kita kemampuan untuk melacak secara bersamaan pasangan perubahan: memindahkan elemen dalam koleksi dua posisi ke bawah menghapus elemen dan kemudian menambahkannya, dan terkait Dengan "mengikat" kedua perubahan ini bersama-sama dan memungkinkan Anda untuk mempertimbangkan gerakan ini.

Alih-alih menerapkan perbedaan secara manual, satu per satu, Anda dapat menerapkannya dalam satu gerakan menggunakan metode penerapan () baru :

 if #available(iOS 9999, *) { let diff = scores2.difference(from: scores1) let result = scores1.applying(diff) ?? [] } 

Membuat Array tidak diinisialisasi


SE-0245 memperkenalkan penginisialisasi baru untuk array yang tidak mengisinya dengan nilai default. Itu tersedia sebelumnya sebagai API pribadi, yang berarti bahwa Xcode tidak meminta itu dalam penyelesaian kode, tetapi Anda dapat menggunakannya jika Anda membutuhkannya dan Anda memahami risiko bahwa fungsi ini mungkin tidak di masa depan.

Untuk menggunakan penginisialisasi, atur ukuran array, lalu berikan penutup yang mengisi array dengan nilai. Penutupan akan menerima pointer yang tidak aman ke buffer yang bisa berubah, serta parameter kedua yang menunjukkan berapa banyak nilai yang sebenarnya Anda gunakan.

Sebagai contoh, kita dapat membuat array 10 integer acak seperti ini:

 let randomNumbers = Array<Int>(_unsafeUninitializedCapacity: 10) { buffer, initializedCount in for x in 0..<10 { buffer[x] = Int.random(in: 0...10) } initializedCount = 10 } 

Ada beberapa aturan:

  1. Anda tidak perlu menggunakan seluruh volume yang Anda minta, tetapi Anda tidak bisa melebihi itu. Artinya, jika Anda mengatur ukuran array ke 10, maka Anda dapat mengatur initializedCount dalam rentang dari 0 hingga 10, tetapi tidak 11.
  2. jika Anda tidak menginisialisasi elemen yang digunakan dalam array, misalnya, Anda menetapkan initializedCount ke 5, tetapi tidak memberikan nilai nyata ke elemen 0 hingga 4, maka mereka kemungkinan besar akan menerima nilai acak. Seperti yang Anda tahu, ini adalah pilihan yang buruk.
  3. Jika Anda tidak menyetel initializedCount , maka itu akan sama dengan 0 dan semua data yang Anda tetapkan akan hilang.

Ya, kami dapat menulis ulang kode menggunakan peta () :

 let randomNumbers2 = (0...9).map { _ in Int.random(in: 0...10) } 

Ini jelas lebih mudah dibaca, tetapi tidak begitu efektif: kami membuat rentang, lalu array kosong baru, menetapkan ukuran, dan "menelusuri" seluruh rentang, menerapkan penutupan untuk setiap elemen.

Kesimpulan


Swift 5.1 masih dalam pengembangan, dan meskipun cabang terakhir untuk Swift sendiri telah berlalu, perubahan dari beberapa proyek terkait lainnya masih terlihat.

Jadi, perubahan yang paling penting adalah stabilitas modul , dan diketahui bahwa tim pengembangan bekerja keras dalam hal ini. Mereka tidak memberikan tanggal rilis yang pasti, meskipun mereka mengatakan bahwa Swift 5.1 memiliki waktu pengembangan yang jauh lebih singkat dibandingkan dengan Swift 5.0, yang membutuhkan konsentrasi energi dan perhatian yang luar biasa. Kami dapat mengasumsikan akses ke WWDC19, tetapi jelas bahwa ini tidak terjadi ketika Anda perlu bergegas ke tanggal tertentu.

Poin lain yang patut diperhatikan. Dua perubahan pada daftar ini ("Peringatan jika ada ketidakjelasan opsi tidak ada" dan "Pencocokan enumerasi opsional dan non-opsional") bukanlah hasil dari evolusi Swift, tetapi diakui sebagai bug dan disesuaikan.

Source: https://habr.com/ru/post/id446522/


All Articles