WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

SOLVED: Project 7: iExpense, Error

Forums > 100 Days of SwiftUI

Is anyone else getting an error for the TextField .keyboardType(.decimalPad)? I keep getting 2 errors: Cannot infer contextual base in reference to member 'numberPad' Value of type 'TextField<Text>' has no member 'keyboardType'

which I think is weird because I'm pretty sure that Text field does have keyboardTypes as an imput type.

`import SwiftUI

struct AddView: View { @State private var name = "" @State private var type = "Personal" @State private var amount = 0.0

let types = ["Buisness", "Personal"]
var body: some View {
    NavigationView{
        Form {
            TextField("Name", text: $name)

            Picker("Type", selection: $type){
            ForEach(types, id:\.self){
                Text($0)
            }
        }
        TextField("Amount", value: $amount, format: .currency(code: "USD"))
            .keyboardType(.decimalPad)
    }
    .navigationTitle("Add New Expense")
}

} } struct AddView_Previews: PreviewProvider { static var previews: some View { AddView() } }`

   

I copied and paste your code and it compiled and ran correctly with no errors.

import SwiftUI

struct AddView: View {
    @State private var name = ""
    @State private var type = "Personal"
    @State private var amount = 0.0

    let types = ["Buisness", "Personal"]

    var body: some View {
        NavigationView{
            Form {
                TextField("Name", text: $name)

                Picker("Type", selection: $type){
                    ForEach(types, id:\.self){
                        Text($0)
                    }
                }
                TextField("Amount", value: $amount, format: .currency(code: "USD"))
                    .keyboardType(.decimalPad)
            }
            .navigationTitle("Add New Expense")
        }
    }
}

struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView()
    }
}

   

Other errors: I am also getting an error in the Picker aftert Text($0): Cannot infer contextual base in reference to member 'numberPad' and after @ObservedObject var expense = Expenses: Type 'Expenses.Type' cannot conform to 'ObservableObject'

import SwiftUI

@available(macOS 12.0, *)
struct AddView: View {
    @ObservedObject var expense = Expenses
    @Environment(\.dismiss) var dismiss

    @State private var name = ""
    @State private var type = "Personal"
    @State private var amount = 0.0

    let types = ["Buisness", "Personal"]
    var body: some View {
        NavigationView{
            Form {
                TextField("Name", text: $name)

                Picker("Type", selection: $type){
                ForEach(types, id:\.self){
                    Text($0)
                }
            }
            TextField("Amount", value: $amount, format: .currency(code: "USD"))
                .keyboardType(.decimalPad)
        }
        .navigationTitle("Add New Expense")
        .toolbar {
            Button("Save") {
                let item = ExpenseItem(name: name, type: type, amount: amount)
                expenses.items.append(item)
                dismiss()
            }
        }
    }
}
}
struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView(expenses: Expenses())
    }
}

   

Save 50% in my Black Friday sale.

SAVE 50% To celebrate WWDC22, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Sponsor Hacking with Swift and reach the world's largest Swift community!

try

@ObservedObject var expenses: Expenses

instead of

@ObservedObject var expense = Expenses

You're not creating a new instance, you're refering to the one you already created in ContentView and if you were creating a new instance of Expenses you would need Expenses()

plus, these two don't match:

@ObservedObject var expense = Expenses

AddView(expenses: Expenses())

you have expense up at top and expenses in the previews

Using:

@ObservedObject var expenses: Expenses

should fix that.

   

I don't understand why it would compile for you but not for me. I am running Xcode Version 13.3 (13E113). Are you running an older version? and my code is not compatible with the newer version?

Also, I changed "@ObservedObject var expense: Expenses" to "@ObservedObject var expenses: Expenses", but I'm still getting the same error.

   

Here's my old one I pulled from backup with your modified AddView added. Xcode 13.3 13E113, complies and runs. You should be able to create a new test app, copy and paste all the code below over the ContentView content and be able to build and run it. If you've verified that works then you can compare your original one with this version.

import SwiftUI

struct ContentView: View {
    @StateObject var expenses = Expenses()
    @State private var showingAddExpense = false
    var body: some View {
        NavigationView {
            List {
                ForEach(expenses.items) { item in
                    HStack {
                        VStack(alignment: .leading) {
                            Text(item.name)
                                .font(.headline)
                            Text(item.type)
                        }
                        Spacer()
                        Text(item.amount, format: .currency(code: "USD"))
                    }
                }
                .onDelete(perform: removeItems)
            }
            .navigationTitle("iExpense")
            .toolbar {
                Button {
                    showingAddExpense = true
                } label: {
                    Image(systemName: "plus")
                }
            }
            .sheet(isPresented: $showingAddExpense) {
                AddView(expenses: expenses)
            }

        }

    }
    func removeItems(at offsets: IndexSet) {
        expenses.items.remove(atOffsets: offsets)
    }
}

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

@available(macOS 12.0, *)
struct AddView: View {
    @ObservedObject var expenses: Expenses
    @Environment(\.dismiss) var dismiss

    @State private var name = ""
    @State private var type = "Personal"
    @State private var amount = 0.0

    let types = ["Buisness", "Personal"]
    var body: some View {
        NavigationView{
            Form {
                TextField("Name", text: $name)

                Picker("Type", selection: $type){
                ForEach(types, id:\.self){
                    Text($0)
                }
            }
            TextField("Amount", value: $amount, format: .currency(code: "USD"))
                .keyboardType(.decimalPad)
        }
        .navigationTitle("Add New Expense")
        .toolbar {
            Button("Save") {
                let item = ExpenseItem(name: name, type: type, amount: amount)
                expenses.items.append(item)
                dismiss()
            }
        }
    }
}
}
struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView(expenses: Expenses())
    }
}
import Foundation

struct ExpenseItem: Identifiable, Codable {
    var id = UUID()
    let name: String
    let type: String
    let amount: Double
}
import Foundation

class Expenses: ObservableObject {
    @Published var items = [ExpenseItem]() {
        didSet {
            if let encoded = try? JSONEncoder().encode(items) {
                UserDefaults.standard.set(encoded, forKey: "Items")
            }
        }
    }
    init() {
        if let savedItems = UserDefaults.standard.data(forKey: "Items") {
            if let decodedItems = try? JSONDecoder().decode([ExpenseItem].self, from: savedItems) {
                items = decodedItems
                return
            }
        }
        items = []
    }
}

   

=..( So frustrating. I copied all of the code that you gave into my Xcode, (after getting 3 errors to add "if #available(macOS 12.0, ) { AddView(expenses: Expenses()) } else {" and adding those) but it's still giving me the error "Cannot infer contextual base in reference to member 'numberPad' " and "Value of type 'TextField<Text>' has no member 'keyboardType' " in the Amount TextField. I don't know what to do when it works for others but not in mine.

   

The only other thing I can think to suggest is to start a new app from scratch and slowly rebuild the code a little bit at a time. Do a CMD+B frequently to make sure it's building as you go. If it fails to build at some point then undo whatever changes you made and build again to see if you can figure out what's causing the problem.

   

I agree with Vince. Start from scratch. Also, I went throught the 100 Days tutorials always with iOS in mind. There may be some shennanigans going on with your code and certain Targets? Not sure I know how this magic works.

This next part may be nonsense.

But if you're adding code like @available(macOS 12.0, *) to your logic, and compilling a MacOS app but trying to run in an iOS simulator, not sure if this would result in some of the errors you're seeing.

   

I just realized that there is an option when creating a new project to change what platform you are coding for. And there is a way to change from macOS to iOS at the top of the window. Looks like that fixed it. Thanks!!

   

Save 50% in my Black Friday sale.

SAVE 50% To celebrate WWDC22, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.