首页 > 解决方案 > 使用组合解析电话号码字符串

问题描述

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

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")
    }
}

标签: swiftswiftuicombine

解决方案


使用.receive(on:)

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

这将允许您监听变量的变化并在队列text中更新它。如果要更新some 读取的变量,则必须main使用queue 。main@PublishedView

并且为了避免保留循环(self-> disposables-> assign-> selfsinkweak self.


推荐阅读