使用 Combine 解析 phone number String

Using Combine to parse phone number String

我正在努力了解 Combine 的工作原理。当我使用 .assign 运算符来改变我正在操作的 @Published 属性 时,我相信我做错了什么。我已阅读有关发布者、订阅者和运营商的文档。但是如果我不希望它是一个函数调用,我对创建 Publisher 的确切位置有点松散。

import SwiftUI
import Combine

struct PhoneNumberField: View {
    
    let title: String
    @ObservedObject var viewModel = ViewModel()
    
    var body: some View {
        TextField(title,text: $viewModel.text)
    }
    
    class ViewModel: ObservableObject {
        @Published var text: String = ""
        private var disposables = Set<AnyCancellable>()
        
        init() {
            $text.map { value -> String in
                    self.formattedNumber(number: value)
            }
            //something wrong here
            .assign(to: \.text, on: self)
            .store(in: &disposables)
            
        }
        
        func formattedNumber(number: String) -> String {
                let cleanPhoneNumber = number.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
                let mask = "+X (XXX) XXX-XXXX"

                var result = ""
                var index = cleanPhoneNumber.startIndex
                for ch in mask where index < cleanPhoneNumber.endIndex {
                    if ch == "X" {
                        result.append(cleanPhoneNumber[index])
                        index = cleanPhoneNumber.index(after: index)
                    } else {
                        result.append(ch)
                    }
                }
                return result
            }
    }
}

struct PhoneNumberParser_Previews: PreviewProvider {
    static var previews: some View {
        PhoneNumberField(title: "Phone Number")
    }
}

使用.receive(on:):

$text.map { self.formattedNumber(number: [=10=]) }
    .receive(on: DispatchQueue.main)
    .sink(receiveValue: { [weak self] value in
        self?.text = value
    })
    .store(in: &disposables)

这将允许您监听 text 变量的变化并在 main 队列中更新它。如果你想更新一些 View 读取的 @Published 变量,使用 main 队列是必要的。

并且为了避免保留循环(self -> disposables -> assign -> self)使用 sinkweak self.