UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

project 7 - iExpence. question

Forums > 100 Days of SwiftUI

I went back to previous projects to fill the gaps. It's also an opportunity to ask questions I was embarrassed to ask.

  1. I always wanted to know how to make a TotalAmount from all the expences in a list. Back in the days when I did this app first time I wanted to implement this but couldn't and forgot about it later. But I remember that @NigelSee did that in his app.

So @NigelSee, or anyone else, please help me with this. I tried to do this with computed var or with didSet but the amount of my experience is not enough. It's not working.

code I tried to implement but it isn't working causing several complaints from Xcode:

    @State var totalAmount = {
        let tempTotal = 0
        for expence in expences.items.amount {
            let tempTotal += expence
        }
    }

    @State var totalAmount1: Double {
        didSet {
            let tempTotal = 0
            tempTotal += expences.amount
        }
    }

I know I'm missing something and the solution is shamefully simple probably but there's no other way to learn other than to try and to ask. I want to get better.

totalAmount

  1. Second thing that was bothering me a little was a popping keyboard while entering Name or Amount of the expence. To be precise - it was staying popped out. I knew we could hide keyboard because previously Paul has shown us how to do this. So I tried to implement this with next code in AddExpenceView:
extension View {
    func hideKeyboard() {
        let resign = #selector(UIResponder.resignFirstResponder)
        UIApplication.shared.sendAction(resign, to: nil, from: nil, for: nil)
    }
}

// and 

.onTapGesture { hideKeyboard() }

But ! When I do this and launch the app a problem occurs: I cant chose the Expense Type with a Picker. It's not "tappable" The only way how it's available to select is through a long tap on a Picker Field and with only what it redirects me to next page to chose between Personal and Business.

Any ideas why this happens ?

Thanks for your advices !

2      

Don't think you need State here.

var totalAmount: Double {
  var tempTotal = 0.0 //if amount is a Double. I don't know the project
  for expence in expences {
    tempTotal += expence.amount
  }
  return tempTotal
}

For dismissing the keyboard and if you're on iOS 16 you can use https://www.hackingwithswift.com/quick-start/swiftui/how-to-dismiss-the-keyboard-when-the-user-scrolls

2      

@Hatsushira

Thanks for the proposed solution, sensei. Yes,sure it was Double as you mentioned, yes - comp.var. can't be used with @State. I remembered that moment. But something other is wrong. Tried. Here we go:

What can be wrong now ?

regarding the keyboard solution: I'm on iOS 15 still with Xcode 13. I hesitate if I should update. Still plenty of negative reviews on AppStore.

Or should I go for version 14 anyway ? 🤔

2      

For the first error, DataModel has an amount property, but [DataModel] (i.e., an array of DataModel) doesn't.

For the second error, you want to use expences.items instead of expences there. expences isn't something you can loop through, but its items property is.

2      

@roosterboy, thank you for explanation ! The code to make it work eventually be like one below. I'm happy for now.

    var totalAmount: Double {
        var tempTotal = 0.0 
        for expence in expences.items {
            tempTotal += expence.amount
        }
        return tempTotal
    }

Next thing I faced was the formatting of the result on a screen. Here are all the options I could do. Of course I didn't touch extensions here.

What would be the most elegant solution from Senior Developer point of view ? (The one with NSNumber is outdated as I understand ? )

                         Text(totalAmount, format: .currency(code: "USD")) //$22.50
                         Text(formattedTotal)                              // 22.50
//                         var formattedTotal: String {
//                             let nf = NumberFormatter()
//                             nf.minimumFractionDigits = 2
//
//                             let formatted = totalAmount
//                             return nf.string(from: formatted as NSNumber)!
//                         }
                         Text("\(totalAmount)")                           // 22.500000
                         Text(totalAmount.formatted())                     // 22.5
                         Text(formattedTotal2)                               // 22.50
//                         var formattedTotal2: String {
//                             let formattedTemp = totalAmount
//                             return String(format: "%.2f", formattedTemp)
//                         }

2      

And the problem with keyboard/picker relationship is still unresolved. Have no idea why that happens :(

2      

@Aizen  

@ngknm14, quick question: how did you acheive to place the text list of expenses below the nav bar and before the list ?

2      

@Aizen, sorry for late reply.

It's very easy. Inside of my List I put a Section, while ForEach is inside a Section, not the List. Making this you can add a "header" to your Section and make it look a way you want (sure with some limitations)

    var body: some View {
        NavigationView {
            List {
                Section {
                    ForEach(expences.items) { item in
                        HStack {
                            VStack(alignment: .leading) {
                                Text(item.name)
                                    .font(.headline)
                                Text(item.type)
                                    .font(.subheadline)
                                    .foregroundColor(.blue)
                                Text(item.notes)
                                    .font(.subheadline)
                                    .foregroundColor(.gray)
                                    .italic()
                            }
                            Spacer()
                            Text(item.amount, format: .currency(code: "USD"))
                                .foregroundColor(.black)
                                .font(.title2)
                                .bold()
                          }
                    }
                    .onDelete(perform: removeItems)
                } header: {
                    HStack {
                        Text("list of expences")
                            .font(.headline)
                            .foregroundColor(.blue)
                        Spacer()
                        // ...

2      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

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.