Swift UI button action function - swift

I completely new on Swift, so excuse possible lack of precision. I am trying to build a login form that authenticates with a REST API.
Here is what I have so far following this tutorial.
My next step is understanding where to put all of the logic for submitting the form. I would like to extract it from the inline manner it is taking.
Can I pass a function to the action parameter? I tried finding some sort of extract feature on Xcode but couldn't get it to work (they are greyed).
import SwiftUI
let lightGreyColor = Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0)
let storedUsername = "john"
let storedPassword = "1234"
struct ContentView: View {
#State var username: String = ""
#State var password: String = ""
#State var authenticationDidFail: Bool = false
#State var authenticationDidSucceed: Bool = false
var body: some View {
ZStack {
VStack {
Image("logo")
EmailField(username: $username)
PasswordField(password: $password)
if authenticationDidFail {
Text("Information not correct. Try again.")
.offset(y: -10)
.foregroundColor(.red)
}
Button(action: {
if self.password == storedPassword {
print(password)
self.authenticationDidSucceed = true
self.authenticationDidFail = false
} else {
self.authenticationDidFail = true
}
}) {
LoginButtonContent()
}
}
if authenticationDidSucceed {
Text("Login succeeded!")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct LoginButtonContent: View {
var body: some View {
Text("LOGIN")
.font(.headline)
.foregroundColor(.white)
.padding()
.frame(width: 220, height: 60)
.background(Color.green)
.cornerRadius(15.0)
}
}
struct PasswordField: View {
#Binding var password: String
var body: some View {
SecureField("Password", text: $password)
.padding()
.background(lightGreyColor)
.cornerRadius(5.0)
.padding(.bottom, 20)
}
}
struct EmailField: View {
#Binding var username: String
var body: some View {
TextField("Username", text: $username)
.padding()
.cornerRadius(5.0)
.padding(.bottom, 20)
}
}

You can use an Object of your Model inside your Button's action, there you can execute your REST call and return a result to set a value to authenticationDidSucceed, so that the UI is updated.
If the used class conforms to the ObservableObject protocol you can even use its published variables to automatically update the UI.

Related

How can I give a swiftUI button multiple functions when pressed?

I created a page for users to register new accounts. I created a "continue" button that is meant to push the new data to firebase and simultaneously move the users to the next view which is my mapView(). Right now the signup fucntion is working, but I cant figure out how to implement the mapView()
Button(action:{
guard !email.isEmpty, !password.isEmpty else {
return
}
viewModel.signUp(email: email, password: password)
} , label: {
Text("Continue")
.foregroundColor(.white)
.frame(width: 350, height: 35)
.background(Color.blue)
.cornerRadius(20)
})
}
Ive tried adding map view inside of the function but Xcode returns a warning that says "Result of 'mapView' initializer is unused".
Button(action:{
guard !email.isEmpty, !password.isEmpty else {
return
}
viewModel.signUp(email: email, password: password)
mapView()
} , label: {
Text("Continue")
.foregroundColor(.white)
.frame(width: 350, height: 35)
.background(Color.blue)
.cornerRadius(20)
})
There are a few ways to pull this off, but using a NavigationStack works really well. Something like this:
//
// ContentView.swift
// animation-example
//
// Created by Andrew Carter on 12/15/22.
//
import SwiftUI
enum SignUpFlow {
case name
case age
case welcome
}
struct SignUpInfo {
var name: String
var age: String
}
struct NameView: View {
#Binding var name: String
var body: some View {
VStack {
TextField("Name", text: $name)
NavigationLink("Next", value: SignUpFlow.age)
.disabled(name.isEmpty)
}
}
}
struct AgeView: View {
#Binding var age: String
var body: some View {
VStack {
TextField("Age", text: $age)
NavigationLink("Next", value: SignUpFlow.welcome)
.disabled(age.isEmpty)
}
}
}
struct WelcomeView: View {
var body: some View {
Text("Welcome")
}
}
struct ContentView: View {
#State private var path: [SignUpFlow] = []
#State private var signUpInfo = SignUpInfo(name: "", age: "")
var body: some View {
NavigationStack(path: $path) {
NavigationLink("Create Account", value: SignUpFlow.name)
.navigationDestination(for: SignUpFlow.self) { flow in
switch flow {
case .age:
AgeView(age: $signUpInfo.age)
case .name:
NameView(name: $signUpInfo.name)
case .welcome:
WelcomeView()
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
In the example above with mapView() just placed in the buttons action, it's unused because, well, it's unused. The Button closure expects a Void return, you're just making a map view than instantly throwing it away- it's not used in any way.

CocoaMQTT init, Can't seem to connect to MQTT Broker

Please excuse how much of a newbie I am. I started on swift at the beginning of last week...
I am trying to make an app that uses BLE and or MQTT to talk to a raspberry pi through a broker. the BLE side is ok but the MQTT (for when out of BLE range) I'm having trouble with.
This is in a swift file of a couple of classes:
import Foundation
import CocoaMQTT
class MQTTManager{
static let shared = MQTTManager()
private var mqttClient: CocoaMQTT
init() {
let clientID = "swift-Trial-13579"
let host = "IP.Goes.Here"
let port = UInt16(1883)
self.mqttClient = CocoaMQTT(clientID: clientID, host: host, port: port)
self.mqttClient.username = "User"
self.mqttClient.password = "Pass"
self.mqttClient.keepAlive = 60
self.mqttClient.connect()
sendMessage(topic: "app/init", message: "init called")
print("MQTT Init Called")
}
func sendMessage(topic:String, message:String){
self.mqttClient.publish(topic, withString: message)
print("publish MQTT called with message: \(message) and a topic of: \(topic)")
}
}
class useProperties: ObservableObject{
#Published var useMQTT = false
#Published var recallMQTTScene = false
#Published var MQTTScene = 0
init(){
}
}
I then have 3 views, ContentView
import SwiftUI
import CocoaMQTT
struct ContentView: View {
#State public var Connection:Bool = false
#State public var SceneMessqe: String = ""
let MQTTHandle = MQTTManager()
// the main view actually is here
var body: some View{
// SceneButton(function: { self.MQTTPub})
VStack{
HStack {
Text("MultiControl POC")
.font(.title)
//.padding()
}
Spacer()
mainSwitch()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(BLEManager())
}
}
mainSwitch
import SwiftUI
import CocoaMQTT
struct mainSwitch: View {
#State public var Connection:Bool = false
#State private var selection: String? = nil
#StateObject var bleManager = BLEManager() // gets from environment.
public var properties = useProperties()
#State private var selectDeviceShown = false
#State var isPresenting = false
public var MQTTHandle = MQTTManager()
var body: some View {
VStack (spacing: 0){
NavigationView{
HStack {
Spacer()
NavigationLink(destination: sheetView(), isActive: $isPresenting) { EmptyView() }// added for nav but not working
Menu("Menu") {
Button("BLE Setup", action: {
self.isPresenting = true // added to trigger nav not workinh
print("Setup button pressed")
//selectDeviceShown = true
})
Button("Reconnect", action: {
bleManager.myCentral.connect(bleManager.wrappedControllers[bleManager.currentSceneSwitchControllerUUID]!.wrappedPerh)
})
Button(action: {
MQTTManager.init()
Connection.toggle()
properties.useMQTT = true
print("connect/disconnect pressed useMQTT = \(properties.useMQTT)")
}, label: {
Text(Connection ? "MQTT Disconnect":"MQTT Connect")
})
Button("Cancel", action: {
print("oops")
})
}
.foregroundColor(Connection ? .green : .red)
.padding(38)
.overlay(
RoundedRectangle(cornerRadius: 15)
.stroke(lineWidth: 2)
.foregroundColor(Connection ? .green : .red)
)
Spacer()
Spacer()
}
.fixedSize(horizontal: false, vertical: true)
.frame(maxHeight: 10)
.padding()
}
HStack{
Spacer()
VStack{
Spacer()
SceneButton(sceneName: "Scene 1", sceneNumber: 1)
Spacer()
SceneButton(sceneName: "Scene 3" , sceneNumber: 3)
Spacer()
SceneButton(sceneName: "Scene 5", sceneNumber: 5)
Spacer()
}
Spacer()
VStack{
Spacer()
SceneButton(sceneName: "Scene 2", sceneNumber: 2)
Spacer()
SceneButton(sceneName: "Scene 4", sceneNumber: 4)
Spacer()
SceneButton(sceneName: "Off", sceneNumber: 6)
Spacer()
}
Spacer()
}
Spacer()
}
.environmentObject(useProperties())
.environmentObject(BLEManager())
}
}
struct mainSwitch_Previews: PreviewProvider {
static var previews: some View {
Group {
mainSwitch()
.environmentObject(BLEManager())
.environmentObject(useProperties())
}
}
}
and finally sceneButton
import SwiftUI
import CocoaMQTT
struct SceneButton: View {
var sceneName: String
var sceneNumber: Int
let properties = useProperties()
#State private var isDisabled: Bool = true
#State private var isDuringGesture: Bool = false
#StateObject private var bleManager = BLEManager()
let btnClr:Color = Color.orange
let btnClrOutr:Color = Color.red
let btnPressedClr:Color = Color.gray
let MQTTHandle = MQTTManager()
var body: some View {
if (properties.useMQTT){
Button(sceneName) {
bleManager.writeToCharacteristicButtonPress(peripheral: bleManager.currentSceneSwitchControllerUUID, sceneToGoToo: (sceneNumber).description, setButtonPressed: true) // Note the number is the same number as the button.
bleManager.writeToCharacteristicButtonPress(peripheral: bleManager.currentSceneSwitchControllerUUID, sceneToGoToo: (sceneNumber).description, setButtonPressed: false)
print("BLE Button" + sceneName)
print("\(properties.useMQTT)")
}
.foregroundColor(.white)
.frame(minWidth: 100)
.padding()
.background(Color(red: 1, green: 0.1, blue: 0.1))
.cornerRadius(10)
.padding(10)
.font(.title2)
.font(.system(size: 20))
}else{
Button(sceneName) {
print("\(properties.useMQTT)")
MQTTHandle.sendMessage(topic: "apptest/scene", message: "\(sceneNumber)")
}
.frame(minWidth: 100)
.padding()
.background(Color(red: 0.40, green: 0.60, blue: 0))
.cornerRadius(10)
.padding(10)
}
}
}
struct SceneButton_Previews: PreviewProvider {
static var previews: some View {
SceneButton(sceneName: "Scene X", sceneNumber: 42) //, publishSceneMQTT: sceneHandle
.environmentObject(BLEManager())
.environmentObject(useProperties())
}
}
Currently when the app loads it calls the MQTT init many times, and then doesn't connect reliably, occasionally, maybe 1 in 10 times it connects to send a single message then I can't send more.
Ideally it would only connect when I press the connect button in the menu in mainSwitch. However each button (SceneButton) should publish something slightly different.
Firstly, is it an issue that it keeps calling init at start?
Secondly, is there something visible that I am doing wrong to mean its not reliably connecting?
thirdly, (least important) in sceneButton the button should change whether using BLE or MQTT, this variable, useMQTT is set in the mainSwitch file. but doesn't change in sceneButton, what have I done wrong?
You use everywhere (!) different instances of MQTTManager, because create it via init, instead you should use everywhere MQTTManager.shared, like
struct ContentView: View {
#State public var Connection:Bool = false
#State public var SceneMessqe: String = ""
// let MQTTHandle = MQTTManager() // << not this !!
let MQTTHandle = MQTTManager.shared // << this one !!
so review all your code and fix as above.

How to setup NavigationLink in SwiftUI sheet to redirect to new view

I am attempting to build a multifaceted openweathermap app. My app is designed to prompt the user to input a city name on a WelcomeView, in order to get weather data for that city. After clicking search, the user is redirected to a sheet with destination: DetailView, which displays weather details about that requested city. My goal is to disable dismissal of the sheet in WelcomeView and instead add a navigationlink to the sheet that redirects to the ContentView. The ContentView in turn is set up to display a list of the user's recent searches (also in the form of navigation links).
My issues are the following:
The navigationLink in the WelcomeView sheet does not work. It appears to be disabled. How can I configure the navigationLink to segue to destination: ContentView() ?
After clicking the navigationLink and redirecting to ContentView, I want to ensure that the city name entered in the WelcomeView textfield is rendered as a list item in the ContentView. For that to work, would it be necessary to set up an action in NavigationLink to call viewModel.fetchWeather(for: cityName)?
Here is my code:
WelcomeView
struct WelcomeView: View {
#StateObject var viewModel = WeatherViewModel()
#State private var cityName = ""
#State private var showingDetail: Bool = false
#State private var linkActive: Bool = true
#State private var acceptedTerms = false
var body: some View {
Section {
HStack {
TextField("Search Weather by City", text: $cityName)
.padding()
.overlay(RoundedRectangle(cornerRadius: 10.0).strokeBorder(Color.gray, style: StrokeStyle(lineWidth: 1.0)))
.padding()
Spacer()
Button(action: {
viewModel.fetchWeather(for: cityName)
cityName = ""
self.showingDetail.toggle()
}) {
HStack {
Image(systemName: "plus")
.font(.title)
}
.padding(15)
.foregroundColor(.white)
.background(Color.green)
.cornerRadius(40)
}
.sheet(isPresented: $showingDetail) {
VStack {
NavigationLink(destination: ContentView()){
Text("Return to Search")
}
ForEach(0..<viewModel.cityNameList.count, id: \.self) { city in
if (city == viewModel.cityNameList.count-1) {
DetailView(detail: viewModel.cityNameList[city])
}
}.interactiveDismissDisabled(!acceptedTerms)
}
}
}.padding()
}
}
}
struct WelcomeView_Previews: PreviewProvider {
static var previews: some View {
WelcomeView()
}
}
ContentView
let coloredToolbarAppearance = UIToolbarAppearance()
struct ContentView: View {
// Whenever something in the viewmodel changes, the content view will know to update the UI related elements
#StateObject var viewModel = WeatherViewModel()
#State private var cityName = ""
#State var showingDetail = false
init() {
// toolbar attributes
coloredToolbarAppearance.configureWithOpaqueBackground()
coloredToolbarAppearance.backgroundColor = .systemGray5
UIToolbar.appearance().standardAppearance = coloredToolbarAppearance
UIToolbar.appearance().scrollEdgeAppearance = coloredToolbarAppearance
}
var body: some View {
NavigationView {
VStack() {
List () {
ForEach(viewModel.cityNameList) { city in
NavigationLink(destination: DetailView(detail: city)) {
HStack {
Text(city.name).font(.system(size: 32))
Spacer()
Text("\(city.main.temp, specifier: "%.0f")°").font(.system(size: 32))
}
}
}.onDelete { index in
self.viewModel.cityNameList.remove(atOffsets: index)
}
}.onAppear() {
viewModel.fetchWeather(for: cityName)
}
}.navigationTitle("Weather")
.toolbar {
ToolbarItem(placement: .bottomBar) {
HStack {
TextField("Enter City Name", text: $cityName)
.frame(minWidth: 100, idealWidth: 150, maxWidth: 240, minHeight: 30, idealHeight: 40, maxHeight: 50, alignment: .leading)
Spacer()
Button(action: {
viewModel.fetchWeather(for: cityName)
cityName = ""
self.showingDetail.toggle()
}) {
HStack {
Image(systemName: "plus")
.font(.title)
}
.padding(15)
.foregroundColor(.white)
.background(Color.green)
.cornerRadius(40)
}.sheet(isPresented: $showingDetail) {
ForEach(0..<viewModel.cityNameList.count, id: \.self) { city in
if (city == viewModel.cityNameList.count-1) {
DetailView(detail: viewModel.cityNameList[city])
}
}
}
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
DetailView
struct DetailView: View {
var detail: WeatherModel
var body: some View {
VStack(spacing: 20) {
Text(detail.name)
.font(.system(size: 32))
Text("\(detail.main.temp, specifier: "%.0f")°")
.font(.system(size: 44))
Text(detail.firstWeatherInfo())
.font(.system(size: 24))
}
}
}
struct DetailView_Previews: PreviewProvider {
static var previews: some View {
DetailView(detail: WeatherModel.init())
}
}
ViewModel
class WeatherViewModel: ObservableObject {
#Published var cityNameList = [WeatherModel]()
func fetchWeather(for cityName: String) {
guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=\(cityName)&units=imperial&appid=<MyAPIKey>") else { return }
let task = URLSession.shared.dataTask(with: url) { data, _, error in
guard let data = data, error == nil else { return }
do {
let model = try JSONDecoder().decode(WeatherModel.self, from: data)
DispatchQueue.main.async {
self.cityNameList.append(model)
}
}
catch {
print(error) // <-- you HAVE TO deal with errors here
}
}
task.resume()
}
}
Model
struct WeatherModel: Identifiable, Codable {
let id = UUID()
var name: String = ""
var main: CurrentWeather = CurrentWeather()
var weather: [WeatherInfo] = []
func firstWeatherInfo() -> String {
return weather.count > 0 ? weather[0].description : ""
}
}
struct CurrentWeather: Codable {
var temp: Double = 0.0
}
struct WeatherInfo: Codable {
var description: String = ""
}
DemoApp
#main
struct SwftUIMVVMWeatherDemoApp: App {
var body: some Scene {
WindowGroup {
// ContentView()
WelcomeView()
}
}
}

Getting Values from own PickerView

I'm new to Swift and I'm currently developing my own Timer Application for practice purposes. (I do it without storyboard)
Now I have the Problem that i made a View called "TimePickerView" (Code below), where I created my own Picker. Then I use that TimePickerView in another part of my Application with other Views (in a View). In that View I want to pick my time but I don't know how i can get the Values of the Picker (The Picker works by the way)
This is my TimePickerView
import SwiftUI
struct TimePickerView: View {
#State private var selectedTimeIndexSecond = 0
#State private var selectedTimeIndexMinutes = 0
#State private var seconds : [Int] = Array(0...59)
#State private var minutes : [Int] = Array(0...59)
var body: some View {
VStack{
Text("Select Your Time")
HStack{
//minutes-Picker
Picker("select time", selection: $selectedTimeIndexMinutes, content: {
ForEach(0..<minutes.count, content: {
index in
Text("\(minutes[index]) min").tag(index)
})
})
.padding()
.frame(width: 120)
.clipped()
//seconds-Picker
Picker("select time", selection: $selectedTimeIndexSecond, content: {
ForEach(0..<seconds.count, content: {
index in
Text("\(seconds[index]) sec").tag(index)
})
})
.padding()
.frame(width: 120)
.clipped()
Spacer()
}
Text("You picked the time")
.multilineTextAlignment(.center)
.font(.title2)
.padding()
Text("\(minutes[selectedTimeIndexMinutes]) min : \(seconds[selectedTimeIndexSecond]) sec")
.font(.title)
.bold()
.padding(.top, -14.0)
}
}
func getValues() -> (Int, Int) {
return (self.minutes[selectedTimeIndexMinutes] ,self.seconds[selectedTimeIndexSecond])
}
}
and that is the View I want to use my Picker, but I don't know how I get those values from the Picker:
struct SetTimerView: View {
#State var timepicker = TimePickerView()
var body: some View {
NavigationView{
VStack{
//Select the time
timepicker
//Timer variables (This doesn't work)
var timerTime = timepicker.getValues()
var minutes = timerTime.0
var seconds = timerTime.1
Spacer()
let valid : Bool = isValid(timerTime: minutes+seconds)
//Confirm the time
NavigationLink(
destination:
getRightView(
validBool: valid,
timerTime: minutes*60 + seconds),
label: {
ConfirmButtonView(buttonText: "Confirm")
});
Spacer()
}
}
}
func isValid(timerTime : Int) -> Bool {
if (timerTime == 0) {
return false
} else {
return true
}
}
#ViewBuilder func getRightView(validBool : Bool, timerTime : Int) -> some View{
if (validBool == true) {
TimerView(userTime: CGFloat(timerTime), name: "David", isActive: true)
} else {
UnvalidTimeView()
}
}
}
I think main problem is misunderstanding conceptions between data and views.
At first you need a model witch will override your data (create it in separate swift file):
import Foundation
class Time: ObservableObject {
#Published var selectedTimeIndexMinutes: Int = 0
#Published var selectedTimeIndexSecond: Int = 0
}
Pay attention on ObservableObject so that swiftUI can easily detect changes to it that trigger any active views to redraw.
Next I try to change the value of the model in the view
import SwiftUI
struct TimePickerView: View {
#EnvironmentObject var timeData: Time
#State private var seconds : [Int] = Array(0...59)
#State private var minutes : [Int] = Array(0...59)
var body: some View {
VStack{
Text("Select Your Time")
HStack{
//minutes-Picker
Picker("select time", selection: $timeData.selectedTimeIndexMinutes, content: {
ForEach(0..<minutes.count, content: {
index in
Text("\(minutes[index]) min").tag(index)
})
})
.padding()
.frame(width: 120)
.clipped()
//seconds-Picker
Picker("select time", selection: $timeData.selectedTimeIndexSecond, content: {
ForEach(0..<seconds.count, content: {
index in
Text("\(seconds[index]) sec").tag(index)
})
})
.padding()
.frame(width: 120)
.clipped()
Spacer()
}
Text("You picked the time")
.multilineTextAlignment(.center)
.font(.title2)
.padding()
Text("\(timeData.selectedTimeIndexMinutes) min : \(timeData.selectedTimeIndexSecond) sec")
.font(.title)
.bold()
.padding(.top, -14.0)
}
}
}
struct TimePickerView_Previews: PreviewProvider {
static var previews: some View {
TimePickerView()
.environmentObject(Time())
}
}
Like you can see I don't using #Blinding, instead of it I connecting our Model with a View
On the next view I can see changes, I created a new one because your example have view that don't indicated here...
import SwiftUI
struct ReuseDataFromPicker: View {
#EnvironmentObject var timeData: Time
var body: some View {
VStack{
Text("You selected")
Text("\(timeData.selectedTimeIndexMinutes) min and \(timeData.selectedTimeIndexSecond) sec")
}
}
}
struct ReuseDataFromPicker_Previews: PreviewProvider {
static var previews: some View {
ReuseDataFromPicker()
.environmentObject(Time())
}
}
And collect all in a Content View
struct ContentView: View {
var body: some View {
TabView {
TimePickerView()
.tabItem {Label("Set Timer", systemImage: "clock.arrow.2.circlepath")}
ReuseDataFromPicker()
.tabItem {Label("Show Timer", systemImage: "hourglass")}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(Time())
}
}
Like that you can easily change or reuse your data on any other views

Get a specific id in a modal

I'm still learning on the job and my question may seem stupid.
I've got a list of movies and on the tap I want to show card of the selected movie.
So I've got my ResultsView
var results:[DiscoverResult]
#State private var resultsCount:Int = 0
#State private var isPresented:Bool = false
#EnvironmentObject private var genres:Genres
var body: some View {
ScrollView {
ForEach (results){ result in
Button(action: {
isPresented.toggle()
}, label: {
ZStack {
ZStack {
KFImage(URL (string: baseUrlForThumb + result.posterPath)).resizable().scaledToFill()
.frame( height: 150)
.mask(Rectangle().frame( height: 150))
Rectangle().foregroundColor(.clear) // Making rectangle transparent
.background(LinearGradient(gradient: Gradient(colors: [.clear, .clear, .black]), startPoint: .top, endPoint: .bottom))
}.frame( height: 150)
// Titre du film
VStack(alignment: .center) {
Spacer()
Text(result.title)
.fontWeight(.bold)
.foregroundColor(.white)
.multilineTextAlignment(.center)
// Genres du film
Text(genres.generateGenresList(genreIDS: result.genreIDS)).font(.caption).foregroundColor(.white).multilineTextAlignment(.center)
} .padding()
}.padding(.horizontal)
})
.sheet(isPresented: $isPresented, content: {
MovieView(isPresented: $isPresented, movieId: result.id)
})
.navigationTitle(result.title)
}
}
}
}
And my MovieView
import SwiftUI
struct MovieView: View {
#Binding var isPresented: Bool
var movieId:Int
var body: some View {
VStack {
Text(String(movieId))
.padding()
Button("Fermer") {
isPresented = false
}
}
}
}
But the movie card still the same even list element selected.
I think that the 'result.id' is overwrite at every loop but i don't know how to fix it.
Sorry for my english mistakes.
thank for your purpose.
Instead of using isPresented for .sheet you can use .sheet(item:, content:) and pass the whole result object
.sheet(item: $selecteditem( { result in
MovieView(item: result)
}
To make this work you need a new property (you can remove isPresented)
#State private var selectedItem: DiscoverResult?
and you need update your MovieView struct
struct MovieView: View {
let result: DiscoverResult
var body: some View {
//...
}
}
or pass only the movie id to your MovieView if you prefer that.