Function in Swift

Viewed 98

I am trying to learn swift by building out a very basic barbell weight plate calculator - the user enters a number in the text field and it displays the plates needed.

I wrote a function in Swift Playgrounds that works well for I am trying to do, but I don't understand how to move it into an app view where the user enters a number and it filters.

I have tried looking online for an explanation to this without any luck: Here is my Swift Playground code which is ideally what I would like to use:

import UIKit

func barbellweight (weight: Int){
    var plate_hash : [Int:Int] = [:]

    if weight == 45 {
        print("You only need the bar!")
    }else if weight < 45{
        print("Must be divisible by 5!")
    }else if (weight % 5 != 0){
           print("Must be divisible by 5!")
    }else{
        
        let plate_array = [45, 35, 25, 10, 5, 2.5]
        var one_side_weight = Double(weight - 45) / 2.0

        for plate_size in plate_array {
            var plate_amount = (one_side_weight / plate_size)
            plate_amount.round(.towardZero)
            one_side_weight -= (plate_size * plate_amount)
            plate_hash[Int(plate_size)] = Int(plate_amount)
        }
    }
    let plate_hash_filtered = plate_hash.filter { $0.value > 0 }
    //print(plate_hash_filtered)
    print(plate_hash_filtered)
}

barbellweight(weight: 225)

Here is attempt to implement it in Swift UI but without any luck. I know it's deconstructed and slightly different - I don't quite understand how to integrate a function into SwiftUI. If someone has any recommendations for resources to look at for this specific ask I would really appreciate it.

import SwiftUI

struct Weight_Plate: View {
    @State var weight: String = "135"
    @State var plate_hash = [String]()
    @State var plate_array = [45, 35, 25, 10, 5, 2.5]
    
    
    var body: some View {
        var one_side_weight = Double(Int(weight)! - 45) / 2.0
                
        List{
            Text("Number of Plates Needed Per Side")
                .multilineTextAlignment(.center)
            ForEach(self.plate_array, id: \.self) { plate_size in
                var plate_amount = (one_side_weight / plate_size)
                if Int(weight) == 45 {
                    Text("You only need the bar!")
                } else if Int(weight)! < 45 {
                    Text("Must be divisible by 5!")
                } else if (Int(weight)! % 5 != 0) {
                       Text("Must be divisible by 5!")
                } else {
                        //Text("Error")
                        plate_amount.round(.towardZero)
                        one_side_weight -= (plate_size * plate_amount)
                    Text("\(Int(plate_size)) x \(Int(plate_amount))")
                            
                       // Text("\(plate):\(Int(plate_amount))")
            }
        }
            
        HStack(alignment: .center) {
            Text("Weight:")
                .font(.callout)
                .bold()
            TextField("Enter Desired Weight", text: $weight)
                .textFieldStyle(RoundedBorderTextFieldStyle())
        }.padding()
    }
}

}
struct Weight_Plate_Previews: PreviewProvider {
    static var previews: some View {
        Weight_Plate()
    }
}

I appreciate any help and recommendations on references that would assist me with this. Thank you!

1 Answers

You know you can still define and call functions right?

Change your code to this

import SwiftUI
func barbellWeight (weight: Int) -> [String] { // naming convention in Swift is camelcase
    var plate_hash = [Int: Int]()

    if weight == 45 {
        return ["You only need the bar!"]
    } else if weight < 45 {
        return ["Insufficient weight!"]
    } else if weight % 5 != 0 {
        return ["Must be divisible by 5!"]
    } else {
        let plate_array = [45, 35, 25, 10, 5, 2.5]
        var one_side_weight = Double(weight - 45) / 2.0

        for plate_size in plate_array {
            var plate_amount = (one_side_weight / plate_size)
            plate_amount.round(.towardZero)
            one_side_weight -= plate_size * plate_amount
            plate_hash[Int(plate_size)] = Int(plate_amount)
        }
    }
    
    return plate_hash.compactMap {
        if $0.value < 0 {
            return nil
        } else {
            return "\($0.key): \($0.value)"
        }
    }
    
}
    
struct Weight_Plate: View {
    @State var weight = "135"
    
    var body: some View {
        List {
            ForEach(barbellWeight(weight: Int(weight) ?? 135), id: \.self) {
                Text($0)
            }
        }
            
        HStack(alignment: .center) {
            Text("Weight:")
                .font(.callout)
                .bold()
            TextField("Enter Desired Weight", text: $weight)
                .textFieldStyle(RoundedBorderTextFieldStyle())
        }.padding()
    }
}
struct Weight_Plate_Previews: PreviewProvider {
    static var previews: some View {
        Weight_Plate()
    }
}

Of course you can play around with this and make it look better. There are also other ways of doing this that could be more efficient, but this works.

Edit: You just define functions the same way you normally would! I rewrote your function to return an array of strings, each string corresponding to a plate, count pair as you can see when you run it. Since weight is a @State variable, when you change it by accepting your user's input, SwiftUI automatically reloads any view dependent on that variable. This causes the ForEach to be reloaded and your function to be called again. ForEach accepts an array of items, so that's why I glued the key and value of the dictionary together. Maybe this clears it up a little bit.

For help learning SwiftUI, check out Paul Hudson's site. It's how I started learning SwiftUI and how I transitioned to UIKit.

https://www.hackingwithswift.com/100/swiftui

Related