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

Posted

技术标签:

【中文标题】如何通过函数格式化 TextField 输入字符串?【英文标题】:How to format TextField input string by function? 【发布时间】:2019-10-28 09:16:39 【问题描述】:

我有一个用于电话输入的简单 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 格式化,并以更好的方式显示用户的输入。

【问题讨论】:

您应该监听文本更改并在每次更改后调用您的 formatTelephone 方法。你可以在这里看到如何做到这一点:***.com/questions/28394933/… 如果您想支持多个国家/地区,自己实施是一场噩梦。我使用了一个很酷的库 -> github.com/marmelroy/PhoneNumberKit 【参考方案1】:

为了得到你想要的,你需要使用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()
    

步骤是(查看视图模型初始化):

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

【讨论】:

非常感谢。效果很好!但是现在我有一个问题,文本光标(插入符号)在格式化后没有停留在单词的末尾。示例:输入在文本字段“1234”中,当我输入“5”时,字符串“12345”触发格式化功能,它变成类似于“1234-5”的东西,所以字符串变长了,但是光标(插入符号) 像“1234-|5”一样停留在“-”和“5”之间,因此下一个字符将不会拼写在数字的末尾。也许你经历过,如果你再次提供帮助,我会很高兴。 @NikitaK。你找到解决办法了吗?

以上是关于如何通过函数格式化 TextField 输入字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何以特殊格式输入 textfield.text

如何通过格式化数字来设置TextField的字符长度

如何在附加到 TextField 的 swift @Published didSet 中正确格式化字符串?

如何从 JSFL 中的 TextField 获取 HTML 格式字符串

将 TextField 文本格式化为价格

python中input函数可以通过格式控制字符串来限定输入的数据吗?