1

I just started to learn Swift programing language and have a question. I'm trying to create a simple one-page application where you can add movies to a favorite list. Movies must have 2 properties: title (string, mandatory) and year (integer, mandatory). But I have a problem, I don't know how to put it in one row. And also, how to ignore duplicate movies?

import SwiftUI

struct Movie: Identifiable {
    let id = UUID()
    var title: String
}

class Model: ObservableObject {
    @Published var movies: [Movie] = []
}

struct DynamicList: View {
    
    @StateObject var model = Model()
    @State var text = ""
    @State var year = ""
    
    var body: some View {
            VStack {
                Section() {
                    TextField("Title", text: $text)
                        .padding()
                        .border(.gray)
                    TextField("Year", text: $year)
                        .padding()
                        .border(.gray)
                        .keyboardType(.numberPad)
                    Button(action: {
                        self.addToList()
                    }, label: {
                        Text("Add")
                            .frame(width: 80, height: 40, alignment: .center)
                            .background(Color.blue)
                            .cornerRadius(8)
                            .foregroundColor(.white)
                    })
                    .padding()
                }
                List {
                    ForEach(model.movies) { movie in
                        MovieRow(title: movie.title)
                    }
                }
            }
            .padding()
    }
    
    func addToList() {
        guard !text.trimmingCharacters(in: .whitespaces).isEmpty else {
            return
        }
        
        guard !year.trimmingCharacters(in: .whitespaces).isEmpty else {
            return
        }
        
        let newMovie = Movie(title: text)
        model.movies.append(newMovie)
        
        Spacer()

        let newYear = Movie(title: year)
        model.movies.append(newYear)
    }
    
}

struct MovieRow: View {
    let title: String
    
    var body: some View {
        Label (
            title: { Text(title)},
            icon: { Image(systemName: "film") }
        )
    }
}
1
  • Add year as a property to Movie to start with, you should only create and append one Movie object in addToList. If you also change the guard statement in addToList for year to guard let yearValue = Int(year) else { return } and then use yearValue your code should work fine Commented Sep 2, 2022 at 12:36

2 Answers 2

1

Here is the solution. It will show the data in one row and also how to ignore duplicate movies to show into the list. Check the below code:

import SwiftUI

struct Movie: Identifiable {
    var id = UUID()
    let title: String
    let year: String
}

class MoviesViewModel: ObservableObject {
    @Published var movies: [Movie] = []
}

struct ContentView: View {
    
    @State var boolValue = false
    @StateObject var viewModel = MoviesViewModel()
    @State var text = ""
    @State var year = ""
    
    var body: some View {
            VStack {
                Section() {
                    TextField("Title", text: $text)
                        .padding()
                        .border(.gray)
                    TextField("Year", text: $year)
                        .padding()
                        .border(.gray)
                        .keyboardType(.numberPad)
                    Button(action: {
                        self.addToList()
                    }, label: {
                        Text("Add")
                            .frame(width: 80, height: 40, alignment: .center)
                            .background(Color.blue)
                            .cornerRadius(8)
                            .foregroundColor(.white)
                    })
                    .padding()
                }
                // Show the data in list form
                List {
                    ForEach(viewModel.movies) { movie in
                        MovieRow(title: movie.title, year: movie.year)
                    }
                }
            }
            .padding()
    }
    
    func addToList() {
        guard !text.trimmingCharacters(in: .whitespaces).isEmpty else {
            return
        }
        
        guard !year.trimmingCharacters(in: .whitespaces).isEmpty else {
            return
        }
        
        
        // Condition to check whether the data is already exit or not
        boolValue = false
        let newMovie = Movie(title: text, year: year)
        for movie in viewModel.movies{
            if ((movie.title.contains(text)) && (movie.year.contains(year))){
                boolValue = true
            }
        }
        // check if boolValue is false so the data will store into the array.
        if boolValue == false{
            viewModel.movies.append(newMovie)
            text = ""
            year = ""
        }
    }
    
}

struct MovieRow: View {
    let title: String
    let year: String
    
    var body: some View {
        // Show the data insert into the textfield
        HStack{
            Label (
                title: { Text(title)},
                icon: { Image(systemName: "film") }
            )
            Spacer()
            Label (
                title: { Text(year)},
                icon: { Image(systemName: "calendar") }
            )
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

Maybe someone will need a similar solution, here is my result:

import SwiftUI

struct Movie: Identifiable {
    let id = UUID()
    var title: String
    var year: String
}

class Model: ObservableObject {
    @Published var movies: [Movie] = []
}

struct DynamicList: View {
    
    @StateObject var model = Model()
    @State var text = ""
    @State var year = ""
    
    var body: some View {
        VStack {
            Section() {
                TextField("Title", text: $text)
                    .padding()
                    .border(.gray)
                TextField("Year", text: $year)
                    .padding()
                    .border(.gray)
                    .keyboardType(.numberPad)
                Button(action: {
                    self.addToList()
                }, label: {
                    Text("Add")
                        .frame(width: 80, height: 40, alignment: .center)
                        .background(Color.blue)
                        .cornerRadius(8)
                        .foregroundColor(.white)
                })
                .padding()
            }
            List {
                ForEach(model.movies) { movie in
                    MovieRow(title: movie.title, year: movie.year)
                }
            }
        }
        .padding()
    }
    
    func addToList() {
        guard !text.trimmingCharacters(in: .whitespaces).isEmpty else {
            return
        }
        
        guard !year.trimmingCharacters(in: .whitespaces).isEmpty else {
            return
        }
        
        let newMovie = Movie(title: text, year: year)
        model.movies.append(newMovie)
        text = ""
        year = ""
    }
    
}

struct MovieRow: View {
    let title: String
    let year: String
    
    var body: some View {
        Label (
            title: { Text(title + " " + year)},
            icon: { Image(systemName: "film") }
        )
    }
}

struct DynamicList_Previews: PreviewProvider {
    static var previews: some View {
        DynamicList()
    }
}

1 Comment

You said in the question that year should be an integer...

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.