6 Operator Swift Combine Yang Harus Anda Ketahui

Terjemahan artikel disiapkan untuk mengantisipasi dimulainya kursus lanjutan "Pengembang iOS".








Pada artikel ini, kita akan melihat enam operator Gabungkan yang berguna. Kami akan melakukan ini dengan contoh, bereksperimen dengan masing-masing di Xcode Playground.



Kode sumber tersedia di akhir artikel.



Nah, tanpa basa-basi lagi, mari kita mulai.



1. tambahkan



Kelompok pernyataan ini memungkinkan kami untuk menambahkan (secara harfiah "menambahkan") acara, nilai, atau penerbit lain ke penerbit asli kami:



import Foundation
import Combine

var subscriptions = Set<AnyCancellable>()

func prependOutputExample() {
    let stringPublisher = ["World!"].publisher
    
    stringPublisher
        .prepend("Hello")
        .sink(receiveValue: { print($0) })
        .store(in: &subscriptions)
}


Hasil: Hellodan World! adalah keluaran dalam urutan berurutan:







Sekarang mari tambahkan penerbit lain dengan tipe yang sama:



func prependPublisherExample() {
    let subject = PassthroughSubject<String, Never>()
    let stringPublisher = ["Break things!"].publisher
    
    stringPublisher
        .prepend(subject)
        .sink(receiveValue: { print($0) })
        .store(in: &subscriptions)
    
    subject.send("Run code")
    subject.send(completion: .finished)
}


Hasilnya mirip dengan yang sebelumnya (perhatikan bahwa kita perlu mengirim acara .finishedke subjek agar operator .prependberfungsi):







2. menambahkan



Operator .append(secara harfiah "tambahkan ke akhir") bekerja dengan cara yang sama .prepend, tetapi dalam kasus ini kami menambahkan nilai ke penerbit asli:



func appendOutputExample() {
    let stringPublisher = ["Hello"].publisher
    
    stringPublisher
        .append("World!")
        .sink(receiveValue: { print($0) })
        .store(in: &subscriptions)
}


Hasilnya, kami melihat Hellodan World! dikeluarkan ke konsol:







Mirip dengan apa yang kita gunakan sebelumnya .prependuntuk menambahkan Publishera, kita juga memiliki opsi ini untuk operator .append:







3. beralih ke terbaru



Operator yang lebih kompleks .switchToLatestmemungkinkan kami menggabungkan serangkaian penayang menjadi satu aliran peristiwa:



func switchToLatestExample() {
    let stringSubject1 = PassthroughSubject<String, Never>()
    let stringSubject2 = PassthroughSubject<String, Never>()
    let stringSubject3 = PassthroughSubject<String, Never>()
    
    let subjects = PassthroughSubject<PassthroughSubject<String, Never>, Never>()
    
    subjects
        .switchToLatest()
        .sink(receiveValue: { print($0) })
        .store(in: &subscriptions)
    
    subjects.send(stringSubject1)
    
    stringSubject1.send("A")
    
    subjects.send(stringSubject2)
    
    stringSubject1.send("B") // 
    
    stringSubject2.send("C")
    stringSubject2.send("D")
    
    subjects.send(stringSubject3)
    
    stringSubject2.send("E") // 
    stringSubject2.send("F") // 
    
    stringSubject3.send("G")
    
    stringSubject3.send(completion: .finished)
}


Inilah yang terjadi di kode:



  • Kami membuat tiga objek PassthroughSubjectyang akan kami kirim nilai.
  • Kami membuat objek utama PassthroughSubjectyang mengirimkan objek lain PassthroughSubject.
  • Kami mengirim stringSubject1ke subjek utama.
  • stringSubject1 mendapat nilai A.
  • Kami mengirimkan stringSubject2ke subjek utama, secara otomatis membuang peristiwa stringSubject1.
  • Demikian pula, kami mengirim nilai ke stringSubject2, terhubung ke, stringSubject3dan mengirimkan acara penyelesaian ke sana.


Hasilnya adalah output A, C, Ddan G:







Untuk mempermudah, fungsi isAvailablemengembalikan nilai acak Boolsetelah beberapa penundaan.



func switchToLatestExample2() {
    func isAvailable(query: String) -> Future<Bool, Never> {
        return Future { promise in
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                promise(.success(Bool.random()))
            }
        }
    }
    
    let searchSubject = PassthroughSubject<String, Never>()
    
    searchSubject
        .print("subject")
        .map { isAvailable(query: $0) }
        .print("search")
        .switchToLatest()
        .sink(receiveValue: { print($0) })
        .store(in: &subscriptions)
    
    searchSubject.send("Query 1")
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
        searchSubject.send( "Query 2")
    }
}


Terima kasih kepada operator, .switchToLatestkami mencapai apa yang kami inginkan. Hanya satu nilai Bool yang akan ditampilkan:







4. bergabung (dengan :)



Kami menggunakan .merge(with:)untuk menggabungkan dua Publishersseolah-olah kami mendapatkan nilai hanya dari satu:



func mergeWithExample() {
    let stringSubject1 = PassthroughSubject<String, Never>()
    let stringSubject2 = PassthroughSubject<String, Never>()
    
    stringSubject1
        .merge(with: stringSubject2)
        .sink(receiveValue: { print($0) })
        .store(in: &subscriptions)
    
    stringSubject1.send("A")
    
    stringSubject2.send("B")
    
    stringSubject2.send("C")
    
    stringSubject1.send("D")
}


Hasilnya adalah urutan elemen yang bergantian:







5.combineLatest



Operator .combineLatestmenerbitkan tupel yang berisi nilai terbaru dari setiap penerbit.



Untuk menggambarkan hal ini, pertimbangkan contoh dunia nyata berikut: kami memiliki nama pengguna, kata sandi, UITextFieldsdan tombol lanjutkan. Kami ingin tetap menonaktifkan tombol hingga nama pengguna setidaknya terdiri dari lima karakter dan kata sandi setidaknya delapan karakter. Kami dapat dengan mudah mencapai ini menggunakan operator .combineLatest:



func combineLatestExample() {
    let usernameTextField = CurrentValueSubject<String, Never>("")
    let passwordTextField = CurrentValueSubject<String, Never>("")
    
    let isButtonEnabled = CurrentValueSubject<Bool, Never>(false)
    
    usernameTextField
        .combineLatest(passwordTextField)
        .handleEvents(receiveOutput: { (username, password) in
            print("Username: \(username), password: \(password)")
            let isSatisfied = username.count >= 5 && password.count >= 8
            isButtonEnabled.send(isSatisfied)
        })
        .sink(receiveValue: { _ in })
        .store(in: &subscriptions)
    
    isButtonEnabled
        .sink { print("isButtonEnabled: \($0)") }
        .store(in: &subscriptions)
    
    usernameTextField.send("user")
    usernameTextField.send("user12")
    
    passwordTextField.send("12")
    passwordTextField.send("12345678")
}


Sekali usernameTextField dan passwordTextFieldterima user12, dan dengan 12345678demikian, kondisinya terpenuhi, dan tombol diaktifkan:







6. zip



Operator .zipmengirimkan sepasang nilai yang cocok dari setiap penerbit. Katakanlah kita ingin menentukan apakah kedua penerbit telah menerbitkan nilai yang sama Int:



func zipExample() {
    let intSubject1 = PassthroughSubject<Int, Never>()
    let intSubject2 = PassthroughSubject<Int, Never>()
    
    let foundIdenticalPairSubject = PassthroughSubject<Bool, Never>()
    
    intSubject1
        .zip(intSubject2)
        .handleEvents(receiveOutput: { (value1, value2) in
            print("value1: \(value1), value2: \(value2)")
            let isIdentical = value1 == value2
            foundIdenticalPairSubject.send(isIdentical)
        })
        .sink(receiveValue: { _ in })
        .store(in: &subscriptions)
    
    foundIdenticalPairSubject
        .sink(receiveValue: { print("is identical: \($0)") })
        .store(in: &subscriptions)
    
    intSubject1.send(0)
    intSubject1.send(1)
    
    intSubject2.send(4)
    
    intSubject1.send(6)
    intSubject2.send(1)
    intSubject2.send(7)
    
    intSubject2.send(9) //  ,       
}


Kami memiliki nilai yang sesuai berikut dari intSubject1dan intSubject2:



  • 0 dan 4
  • 1 dan 1
  • 6 dan 7


Nilai terakhir 9tidak ditampilkan karena nilai intSubject1terkait belum dipublikasikan:







Sumber daya



Kode sumber tersedia di Gist .



Kesimpulan



Tertarik dengan jenis operator Combine lainnya? Silakan kunjungi artikel saya yang lain:



  • 5 operator Gabungkan transformatif yang harus Anda ketahui
  • 9 Gabungkan Operator Filter Yang Harus Anda Ketahui




All Articles