空白时自定义文本输入更改标签

Posted

技术标签:

【中文标题】空白时自定义文本输入更改标签【英文标题】:Custom Text Input Change Label when blank 【发布时间】:2021-12-28 14:57:18 【问题描述】:

我正在为文本输入制作自定义标签。 这个想法是当文本输入改变时,标签也会随之改变。

我可以让它工作,只要我加载带有 id 值的视图,其中包含一些值,例如 1234 但如果我把它留空......

另外,它只存储那些值,当你输入文本输入时它不会改变。

效果有效,只是数字无效。

VStack 
                Custom_Input(id: "")
            

它会引发以下错误。

Thread 1: Fatal error: String index is out of bounds

这很好用

VStack 
                Custom_Input(id: "1234")
            

我不确定如何处理这个问题。

这是这里的整个视图。

import SwiftUI

struct Custom_Input: View 
    @State var id: String = " "
    @State var label1: Character = Character(" ")
    @State var label2: Character = Character(" ")
    @State var label3: Character = Character(" ")
    @State var label4: Character = Character(" ")

    
    var body: some View 

        ZStack 
            Color.green
            VStack 
                HStack(spacing: 13)
                    if(id.count < 1) 
                        Label("0", systemImage: "")
                            .frame(height: 48)
                            .padding(.leading, -7)
                            .foregroundColor(.black)
                     else 
                        Label(String(label1), systemImage: "")
                        .foregroundColor(.white)
                        .frame(height: 48)
                        .padding(.leading, -7)
                        .foregroundColor(.white)
                    
                    if(id.count < 2) 
                        Label("0", systemImage: "")
                            .frame(height: 48)
                            .padding(.leading, -7)
                            .foregroundColor(.black)
                     else 
                    Label(String(label2), systemImage: "")
                        .foregroundColor(.white)
                        .frame(height: 48)
                        .padding(.leading, -7)
                        .foregroundColor(.white)
                    
                    if(id.count < 3) 
                        Label("0", systemImage: "")
                            .frame(height: 48)
                            .padding(.leading, -7)
                            .foregroundColor(.black)
                     else 
                    Label(String(label3), systemImage: "")
                        .foregroundColor(.white)
                        .frame(height: 48)
                        .padding(.leading, -7)
                        .foregroundColor(.white)
                    
                    if(id.count < 4) 
                        Label("0", systemImage: "")
                            .frame(height: 48)
                            .padding(.leading, -7)
                            .foregroundColor(.black)
                     else 
                    Label(String(label4), systemImage: "")
                        .foregroundColor(.white)
                        .frame(height: 48)
                        .padding(.leading, -7)
                        .foregroundColor(.white)
                    
                
                .onAppear 
                    label1 = id[0]
                    label2 = id[1]
                    label3 = id[2]
                    label4 = id[3]
                
            .frame(width: 311, height: 48)
                
                TextField("", text: $id)
                    .background(.red)
                    .frame(width: 311, height: 48)
            

        
        
        .frame(width: 311, height: 48)
            
    



extension StringProtocol 
    subscript(offset: Int) -> Character 
        self[index(startIndex, offsetBy: offset)]
    



struct Custom_Input_Previews: PreviewProvider 
    static var previews: some View 
        Custom_Input(id: "1234")
    

【问题讨论】:

【参考方案1】:

很多代码是重复的,可以简化。

首先,为什么您的解决方案不起作用,为什么会导致运行时错误?好吧,当您使用 less 少于 4 个字符的字符串对其进行初始化时,您正在访问越界索引中的 StringonAppear(perform:) 在视图可见时立即运行,因此这是访问索引的位置导致错误。

要解决此问题,您可以在需要/知道该角色存在时获取该角色。在下面的解决方案中,我创建了一个扩展来安全地获取索引,否则它返回nil

extension StringProtocol 
    subscript(safe offset: Int) -> Character? 
        guard 0 ..< count ~= offset else 
            return nil
        
        return self[index(startIndex, offsetBy: offset)]
    

主视图代码已用ForEach 进行了简化,因此不必重复代码。布局也几乎相同,但大大简化。代码:

struct CustomInput: View 
    @Binding var id: String

    var body: some View 
        VStack(spacing: 20) 
            HStack(spacing: 13) 
                ForEach(0 ..< 4)  index in
                    Text(String(id[safe: index] ?? "0"))
                        .foregroundColor(id.count <= index ? .black : .white)
                
            

            TextField("", text: $id)
                .background(.red)
        
        .padding(.vertical)
        .background(Color.green)
        .padding(30)
    

用法:

struct ContentView: View 
    @State private var id = ""

    var body: some View 
        CustomInput(id: $id)
    

结果:

【讨论】:

太棒了!谢谢 太棒了!谢谢你,我打算删除所有重复的代码,但我很感激你所做的。 @Bnd10706 太好了,很高兴它有用!

以上是关于空白时自定义文本输入更改标签的主要内容,如果未能解决你的问题,请参考以下文章

滚动 UITableView 时自定义单元格中的 UITextField 文本正在更改

滚动时自定义uitableviewcell空白

滚动时自定义 UITableViewCell 中的 UITextFields 文本出现在其他单元格中

基于控件可见性在运行时自定义动态布局

状态更改时自定义 SwiftUI 视图不会更新

方向更改时自定义UITableViewCell自动布局问题