2

I am still totally new to the whole SwiftUI concept and I find it quite difficult compared to other (or lets call them older) programing styles. I know this might sound silly, but I still don't grasp the concept of how to use functions. In most tutorials they use lots of structs and computed properties and apparently not many functions (but why?). I can design nice looking apps though and SwiftUI is so simply compared to normal Swift / UIKit, but I don't understand how to fill my apps with meaningful code so that they actually do something.

Okay here is some example code with a function. Is this the right way to do this or should I use structs or something else?

This code lets the user enter a number, and when the button is pressed "5" is added to the number and the result is shown above the TextField. Nothing special, but my question is would one use a function like this or is there a better way to do this with SwiftUI?

struct ContentView: View {
    @State private var result: String = "0"
    @State private var number: String = ""
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("Result:")
                .font(.title)
                .fontWeight(.bold)
            Text(String(result)).padding()
            Text("Enter a number:")
                .font(.title)
                .fontWeight(.bold)
            TextField("Enter a number", text: $number)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .keyboardType(.numberPad)
            Button("Add 5") {
                result = AddFive()
            }
                .frame(minWidth: 0, maxWidth: .infinity)
                .padding()
                .foregroundColor(.white)
                .background(Color.red)
                .cornerRadius(40)
                .padding(.horizontal, 20)
        }
        .padding()
    
    }
    
    func AddFive() -> String {
        let num = Int(number) ?? 0
        let result = num + 5
        return String(result)
    }
    
}

Of course I could use a computed property in this case, but I am thinking about much more complex code. In Swift I just pilled one function on top of the other.

2
  • 1
    I think most of the time you will fire a action from an event like Button action, onAppear. You can execute your commands in the Button action directly or just outsource your code to a function like you did above. Mostly it's all about modifing class/struct data or changing States/Binding. Many different approachs, but sure yours above does work fine. Commented Jul 5, 2020 at 10:53
  • You start to use func/struct when your app grows. Throw in some networking to have a more in-depth discussion. Commented Jul 5, 2020 at 13:54

1 Answer 1

1

Your original approach is mostly fine. Just a few points:

  • if possible try not to store numbers as String variables. Use Int for data manipulation.

  • if you need to parse a number from a String input you can use computed properties.

  • simple functions can be placed directly inside buttons. They can be also extracted as methods. However, more complex logic is usually stored inside some @ObservedObject and that's why there aren't many functions in views. The logic is moved outside the view.

You may try the following:

struct ContentView: View {
    @State private var result = 0 // <- store as number
    @State private var numberInput: String = ""
    
    var number: Int { // <- computed property for calculations using `numberInput`
        Int(numberInput) ?? 0
    }

    var body: some View {
        VStack(alignment: .leading) {
            Text("Result:")
                .font(.title)
                .fontWeight(.bold)
            Text("\(result)") // <- display `Int` in `Text` views
                .padding()
            Text("Enter a number:")
                .font(.title)
                .fontWeight(.bold)
            TextField("Enter a number", text: $numberInput)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .keyboardType(.numberPad)
            Button("Add 5") {
                self.result = self.number + 5
            }
            .frame(minWidth: 0, maxWidth: .infinity)
            .padding()
            .foregroundColor(.white)
            .background(Color.red)
            .cornerRadius(40)
            .padding(.horizontal, 20)
        }
        .padding()
    }
}

Here is an alternative approach using an @ObservedObject:

class ViewModel: ObservableObject {
    @Published var result = 0
    @Published var numberInput: String = ""
    
    var number: Int {
        Int(numberInput) ?? 0
    }
    
    func incrementNumber(by number: Int) {
        self.result = self.number + number
    }
}
struct ContentView: View {
    @ObservedObject private var viewModel = ViewModel()
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("Result:")
                .font(.title)
                .fontWeight(.bold)
            Text("\(viewModel.result)").padding()
            Text("Enter a number:")
                .font(.title)
                .fontWeight(.bold)
            TextField("Enter a number", text: $viewModel.numberInput)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .keyboardType(.numberPad)
            Button("Add 5") {
                self.viewModel.incrementNumber(by: 5)
            }
            .frame(minWidth: 0, maxWidth: .infinity)
            .padding()
            .foregroundColor(.white)
            .background(Color.red)
            .cornerRadius(40)
            .padding(.horizontal, 20)
        }
        .padding()
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.