简体   繁体   中英

SwiftUI - how to properly use func / struct in an app compared to Swift?

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.

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()
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM