I'm trying to understand Equatable. When I using Equatable
on my CreateCustomer struct why can I not add more phone types if I set one, or when I have added more why can I only set one? Without Equatable
on my struct it works fine.
Here is my SwiftUI view to set the phone type
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 = ""
}
}
Thanks for any help!!!!
CodePudding user response:
This is how I would implement Customer and CustomerPhone and how to check if a Customer object is empty
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
}
}
CodePudding user response:
With a bit of tidying up and renaming, and making Customer
an ObservableObject
, I think this does what you want…
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())
}
}