How to Return a Button from a Function in Swiftui

How to return a Button from a function in SwiftUI?

I'm not sure how important it is that you get a Button, but if you just need it to be displayed in another SwiftUI View without further refinements, you can just return some View. You only have to embed all your Buttons in AnyView's.

func buildButton(parameter : Parameter) -> some View {
switch (parameter){
case Parameter.Value1:
return AnyView(Button(
action: {
...
},
label: {
...
})
)
case Parameter.Value2:
return AnyView(Button(
action: {...},
label: {
...
})
)
}
}

How to return a button from a function WITH modifiers in SwiftUI?

Swift/SwiftUI is picky with the syntax of these things.

To return different types and still conform to some View, you have to use @ViewBuilder. Using @ViewBuilder also means that you use implicit returns, so the structure will be slightly different (no guard let):

@ViewBuilder func makeButton() -> some View {
if let variable = value {
Button(action: {
//execute a function here
}, label: {
Text("Other Label")
.padding(.vertical, 20)
.frame(width: UIScreen.main.bounds.width * 0.8)
.background(Color.white)

})
} else {
Button(action: {
print("printing now...")
}, label: {
Text("Label")
})
}
}

SwiftUI function that returns either Text or Button?

Here is correct variant.

Note: ViewBuilder is disabled when you use explicitly return, so you have to remove return(s) when use it otherwise you'll get compiler errors again.

Tested with Xcode 12 / iOS 14

@ViewBuilder
private func cellContent(for cell: Cell) -> some View {
if (cell.editable) {
Button(action: { print("hi") }) { Text(cell.content) }
}
Text(cell.content)
}

Returning a SwiftUI List in a function

Option #1:

Return some View:

func myList() -> some View {
List(items, id:\.self) { item in
Text("Hello")
}
}

Option #2:

Use the specific type. The easiest way I can think of to get this is to temporarily set a variable to the List. For example:

var myList = List(items, id:\.self) { item in
Text("Hello")
}

If I then Option-Click on myList, Xcode will display a popup showing the exact type that myList is inferred to be. You can use that as the return type for your function. In the case of my contrived example, it is List<Never, ForEach<[GameModel], GameModel, Text>> where items is [GameModel]

Return value from function (action button)

@IBAction function is system based functions based on user interaction. They don't return anything and the return type is Void for this type function

SwiftUI: Button inside function doesn't update view

You have @State defined inside a member function. Instead, it should be defined at the top level of your View -- that's the only way it will retain/update state. The smallest working change would be this:

struct TestView: View {
@State var testBool: Bool? //<-- Here

var body: some View {
buttonView()
}

func buttonView() -> some View {
Button(action: {
testBool = Bool.random()
}, label: {
VStack {
Text("click me")
Text(testBool == nil ? "nil" : String(testBool!))
}
})
}
}

A further refactor to get it to look a little Swift-ier might be:

struct TestView: View {
@State var testBool: Bool?

var body: some View {
Button(action: {
testBool = Bool.random()
}) {
VStack {
Text("click me")
if let testBool = testBool {
Text(testBool ? "true" : "false")
} else {
Text("nil")
}
}
}
}
}

Button with NavigationLink and function call SwiftUI

The answer from Yodagama works if you were trying to present a sheet (because you called your navigation destination SheetView), but if you were trying to navigate to SheetView instead of present a sheet, the following code would do that.

struct LoginView: View {
@State var check = false
@State var answer = false

var body: some View {
NavigationView {
VStack{
Text("it doesn't work")
NavigationLink(destination: SheetView(), isActive: $answer, label: {
Button(action: {
answer = test(value: 2)
}, label: {
Text("Calculate")
})
})



}
}
}

func test(value: Int) -> Bool {

if value == 1 {
check = false
} else {
print("Succes")
check = true
}

return check
}

}

struct SheetView: View {

var body: some View {
NavigationView {
VStack{
Text("Test")
.font(.title)
}
}
}
}


Related Topics



Leave a reply



Submit