【问题标题】:Swift Equatable Struct doesn't allow updating?Swift Equatable Struct 不允许更新?
【发布时间】:2023-01-11 01:40:47
【问题描述】:

我试图理解 Equatable。当我在我的 CreateCustomer 结构上使用 Equatable 时,如果我设置了一个,为什么我不能添加更多电话类型,或者当我添加了更多电话类型时,为什么我只能设置一个?在我的结构上没有 Equatable 它工作正常。

这是我设置电话类型的 SwiftUI 视图

struct T01: View{
    @State var phoneTypes: [String] = ["Other", "Home", "Service", "Work", "Cell"]
    @State var customerCreate: CreateCustomer = CreateCustomer()
    var body: some View {
        VStack{
            if (customerCreate != CreateCustomer()){
                Button(action: {
                    customerCreate = CreateCustomer()
                }, label: {
                    Text("Clear").padding()
                })
            }
            ForEach($customerCreate.phone.indices, id: \.self) { i in
                Menu {
                    ForEach(phoneTypes, id: \.self){ client in
                        Button() {
                            let x = client
                            customerCreate.phone[i].phoneType = x
                            print(customerCreate.phone[i].phoneType)
                        } label:{
                            Text(client)
                            if customerCreate.phone[i].phoneType == client
                            {
                                Image(systemName: "checkmark")
                            }
                        }
                    }
                } label: {
                    VStack{
                        HStack{
                            Spacer()
                            Text(customerCreate.phone[i].phoneType.isEmpty ? "Select the phone type *" : customerCreate.phone[i].phoneType)
                                .foregroundColor(customerCreate.phone[i].phoneType.isEmpty ? .gray : .black)
                            Image(systemName: "chevron.down")
                                .foregroundColor(Color.green)
                            Spacer()
                        }
                    }
                }
            }
            Button(action: {
                customerCreate.addPhone()
            }, label: {
                HStack {
                    Image(systemName: "plus.circle")
                        .font(.system(size: 15))
                    Text("Add Phone")
                        .fontWeight(.thin)
                        .font(.system(size: 15))
                }
            })
        }
    }
}

struct CreateCustomer: Codable, Equatable {
    static func == (lhs: CreateCustomer, rhs: CreateCustomer) -> Bool {
        // It can be fixed by changing == to > but I want the == so I can know if I should display the clear button or not.
        return String(lhs.phone.first?.phoneType ?? "") == String(rhs.phone.first?.phoneType ?? "")
    }
    
    var phone: [CustomerPhone]
    init() {
        phone = [CustomerPhone()]
    }
    public mutating func addPhone(){
        phone.append(CustomerPhone())
    }
}

struct CustomerPhone: Codable {
    var phone: String
    var phoneType: String
    init(){
        phone = ""
        phoneType = ""
    }
}

谢谢你的帮助!!!!

【问题讨论】:

  • 在尝试回答问题之前的一些事情。使用 Swift 编码约定使您的代码更易于阅读,因此使用 UpperCamelCase 来命名类型和协议,并使用 lowerCamelCase 来命名其他所有内容(不使用蛇形命名法)。所以customerCreate而不是Customer_Createvar phone: String而不是var Phone: String,等等。另外,请只使用演示问题的最少代码,并确保它编译(上面的代码没有)。如需帮助,请参阅minimal reproducible example
  • @AshleyMills 谢谢,我试着让它变得更小。当另一个结构中有一个结构确实使代码有点难以阅读时,这似乎只是一个错误。
  • 很难理解您的代码,例如customerCreate != CreateCustomer()phone.append(CustomerPhone())。为什么要在这么多地方创建新对象?
  • @JoakimDanielson customerCreate != CreateCustomer() 这会检查本地对象是否为空,以确定清除按钮是否可见,这需要Equatable 。虽然 phone.append(CustomerPhone()) 应该向数组添加一个新的客户电话,但只有在没有 Equatable 的情况下才能工作。我将尝试添加一些 cmets。
  • 在 IMO 中,这不是一个好方法,比拥有一个无论对象是否为空都返回布尔值的计算属性或函数要好。

标签: swift swiftui


【解决方案1】:

通过一些整理和重命名,并将 Customer 变为 ObservableObject,我认为这可以满足您的需求……

struct ContentView: View {
    @State var phoneTypes: [String] = ["Other", "Home", "Service", "Work", "Cell"]
    @StateObject var customer = Customer()
        
    
    var body: some View {
        VStack{
            if !customer.isEmpty {
                Button(action: {
                    customer.phones = []
                }, label: {
                    Text("Clear").padding()
                })
            }
            ForEach($customer.phones.indices, id: .self) { i in
                Menu {
                    ForEach(phoneTypes, id: .self) { phoneType in
                        Button() {
                            customer.phones[i].phoneType = phoneType
                            
                            print(customer.phones)
                        } label:{
                            Text(phoneType)
                            if customer.phones[i].phoneType == phoneType {
                                Image(systemName: "checkmark")
                            }
                        }
                    }
                } label: {
                    VStack{
                        HStack{
                            Spacer()
                            Text(customer.phones[i].phoneType.isEmpty ? "Select the phone type *" : customer.phones[i].phoneType)
                                .foregroundColor(customer.phones[i].phoneType.isEmpty ? .gray : .black)
                            Image(systemName: "chevron.down")
                                .foregroundColor(Color.green)
                            Spacer()
                        }
                    }
                }
            }
            
            Button(action: {
                customer.addPhone()
                
                print(customer.phones)
            }, label: {
                HStack {
                    Image(systemName: "plus.circle")
                    Text("Add Phone")
                        .fontWeight(.thin)
                }
            })
            .font(.system(size: 15))
        }
    }
}

final class Customer: ObservableObject {
    
    @Published var phones: [CustomerPhone]
    
    var isEmpty: Bool {
        phones == [CustomerPhone()]
    }
    
    init() {
        phones = [CustomerPhone()]
    }
    
    public func addPhone(){
        phones.append(CustomerPhone())
    }    
}

【讨论】:

    【解决方案2】:

    这就是我将如何实现 Customer 和 CustomerPhone 以及如何检查 Customer 对象是否为空

    struct Customer: Codable, Equatable {
        var phones: [CustomerPhone]
    
        init() {
            phones = [CustomerPhone()]
        }
    
        public mutating func add(phone: CustomerPhone = CustomerPhone()){
            phones.append(phone)
        }
    
        var isEmpty: Bool {
            phones.isEmpty || phones.allSatisfy(.isEmpty)
        }
    }
    
    struct CustomerPhone: Codable, Equatable {
        var phone: String
        var phoneType: String
        init(){
            phone = ""
            phoneType = ""
        }
    
        var isEmpty: Bool {
            phone.isEmpty && phoneType.isEmpty
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-09-29
      • 1970-01-01
      • 2023-04-10
      • 2018-08-13
      • 2021-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-27
      相关资源
      最近更新 更多