如何通过函数格式化TextField输入字符串?

时间:2019-10-28 09:16:39

标签: ios swift swiftui combine

我有一个简单的TextField用于电话输入,并且想在每次更改时对其进行格式化。

我正在使用PhoneNumberKit,它工作正常,但是在textField中的值更改后,我不明白如何调用格式化函数。

电话格式化功能。

import SwiftUI
import PhoneNumberKit
import Combine

func formatTelephone(telephone : String) -> String
    {

        do {
            let phoneNumber =  PartialFormatter().formatPartial(telephone)

            print(phoneNumber)
            return phoneNumber
        }
        catch {
            print("Generic parser error")

        }
    }

它执行以下操作:

formatTelephone("79152140700") -> "7 (915) 214 08-00" 
formatTelephone("791521") -> "7 (915) 21" 

我有一个像这样的TextField

TextField("915 214 07 00" , text: $telephoneManager.telephone)

每次输入数字后,整个文本字段标签都需要用func格式化,并以更好的方式显示用户的输入。

1 个答案:

答案 0 :(得分:0)

为了获得想要的东西,您需要使用Combine(视图模型中两种方法的实现完全取决于您,因为它们严格取决于您的需求):

import SwiftUI
import Combine

class ContentViewModel: ObservableObject {
    @Published var phoneNumber = ""
    private var toCancel: AnyCancellable!

    init() {
        toCancel = $phoneNumber
            .filter { !self.isFormatValid($0) }
            .map { self.convert($0) }
            .receive(on: RunLoop.main)
            .assign(to: \.phoneNumber, on: self)
    }

    private func isFormatValid(_ str: String) -> Bool {
        //here you must check if _str_ is already in the right format
        true //just to make this example compile, but clearly this must be replaced with your code
    }

    private func convert(_ str: String) -> String {
        //convert your string to be in the right format
        "string in the correct format" //just to make this example compile, but clearly this must be replaced with your code
    }

    deinit {
        toCancel.cancel()
    }
}

struct ContentView: View {
    @ObservedObject var contentViewModel = ContentViewModel()

    var body: some View {
        TextField("Your phone number...", text: $contentViewModel.phoneNumber)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

步骤如下(查看视图模型的初始化):

  1. phoneNumber@Published的属性,因此可以由订阅的发布者“支持”。因此,让我们订阅该发布者。
  2. 您必须检查文本字段中的字符串是否已经采用正确的格式。这是至关重要的:如果您错过了这一步,您将陷入无限循环。这是通过.filter运算符完成的。仅当.filter运算符返回true时才向下转发事件(在这种情况下,如果字符串格式无效,则返回true)。
  3. 使用.map运算符,您可以更改字符串(格式错误)并以正确的格式返回字符串。
  4. .receive可让您在感兴趣的线程上转发事件。在这种情况下,主线程(因为您要更新文本字段)。
  5. .assign只是将新值分配给文本字段。