I have a problem with a Text view. I have a List of menu products, and the products contains a description. But, when a product don't have a description, there is a blank space. I do not want the blank space. How can I remove the blank space ?
This is what I Have : [First Picture]
This is what I want : Second Picture
I will share the code Below :
struct SectionVieww: View {
#EnvironmentObject var syncViewModel : SyncViewModel
#StateObject var coreDataViewModel = CoreDataViewModel()
#Environment(\.managedObjectContext) private var viewContext
#FetchRequest(sortDescriptors: [])
private var menus : FetchedResults<LocalMenu>
var menuType : MenuType
var body: some View {
let filteredMenus = syncViewModel.menu
.filter({$0.type == menuType.id})
if !filteredMenus.isEmpty {
Section(header:
Text("\(menuType.text.capitalized)")
.font(.system(size: 20, weight: .bold, design: .rounded))
.foregroundColor(.black)
) {
ForEach(filteredMenus) { men in
HStack {
WebImage(url: men.image.getThumbnailUrl(), options: .refreshCached)
.onFailure(perform: { (error) in
} )
.resizable()
.frame(width: 80, height: 80)
.cornerRadius(10)
VStack(alignment: .leading, spacing: 10) {
Spacer()
Text(men.name)
.font(.system(size: 16))
.foregroundColor(.black)
.fontWeight(.semibold)
Text(men.welcomeDescription ?? "")
.font(.caption)
.foregroundColor(.gray)
HStack {
Text("\(men.price) lei")
.fontWeight(.bold)
Text("\(men.ingredients.map({$0.grams}).reduce(0, +), specifier: "%.0f")g")
.font(.system(size: 16))
.fontWeight(.medium)
.foregroundColor(.gray)
}
Spacer()
}
Spacer()
Button {
coreDataViewModel.addTask(name: men.name, grams: men.ingredients.map({$0.grams}).reduce(0, +), price: Int((men.price)), id: men.id)
} label: {
Image(systemName: "plus")
.font(.title)
.foregroundColor(Color.onboardingColor)
}
.buttonStyle(PlainButtonStyle())
}.background(NavigationLink("", destination:
ItemMenuView(meniu: men)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
ToolbarButtons(numberOfProducts: menus.count)
}
}
).opacity(0)
)
}
}
} else {
EmptyView()
}
}
}
struct MeniuriView: View {
#EnvironmentObject var syncViewModel : SyncViewModel
var body: some View {
List {
ForEach(syncViewModel.menuType) { type in
SectionVieww(menuType: type)
}
}
.listStyle(PlainListStyle())
}
}
Put it conditionally, like
if let description = men.welcomeDescription {
Text(description)
.font(.caption)
.foregroundColor(.gray)
}
Related
I'm new to Swift at the moment and I'm having trouble appending to a to-do list. I am not receiving an error, so I don't know what's wrong. I hope this isn't too much code to go through, but I don't even know where the problem is.
There is a sheet modal that opens and closes fine. The only issue is that when I press the save button, the information I typed in doesn't add to the list.
I've add the ViewModel, NewTaskView(sheet), TaskView(customizes list), and a bit of code of the DetailView where the list should be.
import Foundation
import SwiftUI
class TaskViewModel : Identifiable , ObservableObject {
#Published var tasks : [Task] = [
Task(taskName: "Lab", taskDate: Date(), taskCompleted: false),
Task(taskName: "Assignment 4.02", taskDate: Date(), taskCompleted: false)
]
#Published var sortType : SortType = .alphabetical
#Published var isPresented = false
#Published var searched = ""
func addTask(task : Task){
tasks.append(task)
}
func removeTask(indexAt : IndexSet){
tasks.remove(atOffsets: indexAt)
}
func sort(){
switch sortType {
case .alphabetical :
tasks.sort(by: { $0.taskName < $1.taskName })
case .date :
tasks.sort(by: { $0.taskDate > $1.taskDate })
}
}
}
struct Task : Identifiable , Equatable {
var id : String = UUID().uuidString
let taskName : String
let taskDate : Date
var taskCompleted: Bool
}
enum SortType : String , Identifiable , CaseIterable {
var id : String { rawValue }
case alphabetical
case date
}
struct NewTaskView: View {
#Environment(\.presentationMode) var presentationMode
#ObservedObject var taskVM : TaskViewModel
#State var taskName = ""
#State var taskCompleted = Bool()
#State var taskDate = Date()
var body: some View {
NavigationView {
VStack(spacing: 14) {
Spacer()
TextField("Assignment Name",text: $taskName)
.padding()
.background(Color("tan"))
.cornerRadius(5)
.font(Font.custom(FontNameManager.Montserrat.semibold, size: 15))
.padding(.bottom, 20)
HStack{
Text("Due Date")
.font(Font.custom(FontNameManager.Montserrat.semibold, size: 15))
Image(systemName: "bell.badge")
.foregroundColor(.gray)
.frame(width: 30, height: 30, alignment: .leading)
VStack{
DatePicker("Select Date", selection: $taskDate, displayedComponents: .date)
.labelsHidden()
}
}
HStack{
Text("Mark as Completed")
.font(Font.custom(FontNameManager.Montserrat.semibold, size: 15))
Button(action : {
taskCompleted.toggle()
}){
if taskCompleted == true {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(Color("orange"))
.font(.title2)
}
else {
Image(systemName: "circle")
.foregroundColor(Color("lightorange"))
.font(.title2)
}
}
}
Spacer()
Button(action:{taskVM.addTask(task: .init(taskName: taskName, taskDate: taskDate, taskCompleted: taskCompleted))
presentationMode.wrappedValue.dismiss()},
label:{
Text("Save")
})
}.padding()
.navigationBarItems(trailing: Button(action: {
presentationMode.wrappedValue.dismiss()
}) {
HStack{
Image(systemName: "xmark")
.foregroundColor(Color("orange"))
}
})
}
}
}
struct NewTaskView_Previews: PreviewProvider {
static var previews: some View {
NewTaskView(taskVM: TaskViewModel())
}
}
struct TaskView: View {
var task : Task
#Environment(\.managedObjectContext) var moc
#State var currentDate: Date = Date()
#State var taskCompleted = false
func getDateFormatString(date:Date) -> String
{
var dateString = ""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM. dd"
dateString = dateFormatter.string(from: date)
return dateString
}
var body: some View {
HStack {
Button(action : {
self.taskCompleted.toggle()
try? self.moc.save()
}){
if self.taskCompleted {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(Color("orange"))
.font(.title2)
}
else {
Image(systemName: "circle")
.foregroundColor(Color("lightorange"))
.font(.title2)
}
}.padding()
VStack (alignment: .leading, spacing: 2){
Text("\(task.taskName)")
.font(Font.custom(FontNameManager.Montserrat.bold, size: 18))
.foregroundColor(Color("dark"))
.padding([.leading, .trailing], 1)
if self.taskCompleted {
Text("Completed")
.font(Font.custom(FontNameManager.Montserrat.bold, size: 12))
.foregroundColor(Color("burntorange"))
.frame(width: 95, height: 20)
.background(Color("lightorange"))
.cornerRadius(4)
}
else if currentDate > task.taskDate {
Text("Late")
.font(Font.custom(FontNameManager.Montserrat.semibold, size: 12))
.foregroundColor(.white)
.frame(width: 95, height: 18)
.background(Color("lightbrown"))
.cornerRadius(4)
}
else {
let diffs = Calendar.current.dateComponents([.day], from: currentDate, to: task.taskDate )
Text("\(diffs.day!) days left")
.font(Font.custom(FontNameManager.Montserrat.semibold, size: 12))
.foregroundColor(Color("burntorange"))
.frame(width: 95, height: 20)
.background(Color("lightorange"))
.cornerRadius(4)
}
}
Spacer()
Text(getDateFormatString(date: task.taskDate ))
.font(Font.custom(FontNameManager.Montserrat.medium, size: 12))
.padding()
}
.padding(10)
.cornerRadius(10)
.background(
RoundedRectangle(cornerRadius: 10 , style: .continuous)
.foregroundColor(.white))
}
}
struct TaskView_Previews: PreviewProvider {
static var previews: some View {
TaskView(task: Task(id: "", taskName: "Task Name", taskDate: Date(), taskCompleted: false))
}
}
struct DetailsView: View {
#Environment(\.managedObjectContext) var moc
#ObservedObject var developers : Developer
#ObservedObject var taskVM : TaskViewModel
#Environment(\.presentationMode) var presen
#Environment(\.editMode) var editButton
#State var taskCompleted = false
#State var show = false
#State var showSearch = false
#State var txt = ""
#State var currentDate: Date = Date()
#State var image : Data = .init(count: 0)
#State var indices : [Int] = []
func getDateFormatString(date:Date) -> String
{
var dateString = ""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM. dd"
dateString = dateFormatter.string(from: date)
return dateString
}
var body: some View {
NavigationView {
ZStack {
ZStack{
VStack{
Color("lightorange")
.clipShape(CustomCorners(corners: [.bottomLeft, .bottomRight], size: 70))
.ignoresSafeArea(.all, edges: .top)
.frame(width: 420, height: 175)
Spacer()
}
VStack{
HStack {
if !self.showSearch{
Button(action: {
withAnimation(.spring()){
self.presen.wrappedValue.dismiss()
}
}) {
Image(systemName: "chevron.left")
.font(.title2)
.foregroundColor(Color("dark"))
.padding(10)
}
}
Spacer(minLength: 0)
HStack {
if self.showSearch{
Image(systemName: "magnifyingglass")
.font(.title2)
.foregroundColor(Color("dark"))
.padding(.horizontal, 8)
TextField("Search", text: $taskVM.searched , onEditingChanged: { (isBegin) in
if isBegin {
showSearch = true
} else {
showSearch = false
}
})
Button(action: {
withAnimation{
self.showSearch.toggle()
}
}) {
Image(systemName: "xmark").foregroundColor(.black).padding(.horizontal, 8)
}
}
else {
Button(action: {
withAnimation {
self.showSearch.toggle()
}
}) {
Image(systemName: "magnifyingglass")
.font(.title2)
.foregroundColor(Color("dark"))
.padding(10)
}
}
}.padding(self.showSearch ? 10 : 0)
.background(Color("lightorange"))
.cornerRadius(20)
}
ZStack{
RoundedRectangle(cornerRadius: 25)
.foregroundColor(Color("tan"))
.frame(width: 335, height: 130)
HStack {
VStack (alignment: .leading){
// Image(uiImage: UIImage(data: developers.imageD ?? self.image)!)
// .resizable()
// .frame(width: 70, height: 70)
// .clipShape(RoundedRectangle(cornerRadius: 20))
Text("\(developers.username ?? "")")
.font(Font.custom(FontNameManager.Montserrat.bold, size: 24))
.foregroundColor(Color("dark"))
Text("\(developers.descriptions ?? "")")
.font(Font.custom(FontNameManager.Montserrat.semibold, size: 18))
.foregroundColor(.gray)
}
.padding([.leading, .trailing], 70)
.padding(.bottom, 80)
Spacer()
}
}
HStack{
Text("Assignments")
.font(Font.custom(FontNameManager.Montserrat.bold, size: 20))
Spacer(minLength: 0)
EditButton()
}
.padding([.leading, .trailing], 20)
Spacer()
List {
ForEach (taskVM.tasks.filter {
self.taskVM.searched.isEmpty ? true : $0.taskName.localizedCapitalized.contains(self.taskVM.searched)} ){ task in
TaskView(task: task)
.listRowSeparator(.hidden)
}
.onDelete(perform: {
taskVM.removeTask(indexAt: $0)
})
}
.listStyle(InsetListStyle())
}
}
VStack {
Spacer()
HStack {
Spacer()
ExpandableFAB(taskVM: TaskViewModel(), show: $show)
}
}
}.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
}
struct DetailsView_Previews: PreviewProvider {
static let persistenceController = PersistenceController.shared
static var developers: Developer = {
let context = persistenceController.container.viewContext
let developers = Developer(context: context)
developers.username = "Math"
developers.descriptions = "Calculus"
return developers
}()
static var previews: some View {
DetailsView(developers: developers, taskVM: TaskViewModel()).environment(\.managedObjectContext, persistenceController.container.viewContext)
}
}
struct ExpandableFAB: View {
#Environment(\.managedObjectContext) var moc
#ObservedObject var taskVM : TaskViewModel
#Binding var show: Bool
var body: some View{
VStack(spacing: 20){
if self.show{
Button(action: {
taskVM.isPresented.toggle()
}) {
Image(systemName: "list.bullet.rectangle.portrait").resizable().frame(width: 25, height: 25).padding()
}
.foregroundColor(.white)
.background(Color("orange"))
.clipShape(Circle())
Button(action: {
self.show.toggle()
}) {
Image(systemName: "doc.badge.plus").resizable().frame(width: 25, height: 25).padding()
}.foregroundColor(.white)
.background(Color("orange"))
.clipShape(Circle())
}
Button(action: {
self.show.toggle()
}) {
Image(systemName: "plus").resizable().frame(width: 25, height: 25).padding()
}.foregroundColor(.white)
.background(Color("orange"))
.clipShape(RoundedRectangle(cornerRadius: 20))
.padding()
.rotationEffect(.init(degrees: self.show ? 180 : 0))
}.fullScreenCover(isPresented: $taskVM.isPresented, content: {
NewTaskView(taskVM: taskVM)
})
}
}
#burnsi I don't think I have that anywhere. Where should there be one?
Of course you have one and you need one:
ExpandableFAB(taskVM: TaskViewModel(), show: $show)
This line is causing the issue.
You are somehow injecting a TaskViewModel in your DetailsView (You are not showing where), but not using it. Try:
ExpandableFAB(taskVM: taskVM, show: $show)
And the place you create your ViewModel ('TaskViewModel()') should have a #StateObject wrapper.
Explanation:
As you add something to your ViewModel the views depending on the ViewModel get rebuild. So your TaskViewModel ends up beeing recreated and you still have your 2 initial values in your array.
This view hold a list of pdf names which when tapped open webviews of pdf links.
The view has a search bar above the list which when tapped causes the scrollview to disappear.
struct AllPdfListView: View {
#Environment(\.presentationMode) var mode: Binding<PresentationMode>
#ObservedObject var pdfsFetcher = PDFsFetcher()
#State var searchString = ""
#State var backButtonHidden: Bool = false
#State private var width: CGFloat?
var body: some View {
GeometryReader { geo in
VStack(alignment: .leading, spacing: 1) {
HStack(alignment: .center) {
Image(systemName: "chevron.left")
Text("All PDFs")
.font(.largeTitle)
Spacer()
}
.padding(.leading)
.frame(width: geo.size.width, height: geo.size.height / 10, alignment: .leading)
.background(Color(uiColor: UIColor.systemGray4))
.onTapGesture {
self.mode.wrappedValue.dismiss()
}
HStack(alignment: .center) {
Image(systemName: "magnifyingglass")
.padding([.leading, .top, .bottom])
TextField ("Search All Documents", text: $searchString)
.textFieldStyle(PlainTextFieldStyle())
.autocapitalization(.none)
Image(systemName: "slider.horizontal.3")
.padding(.trailing)
}
.overlay(RoundedRectangle(cornerRadius: 10).stroke(.black, lineWidth: 1))
.padding([.leading, .top, .bottom])
.frame(width: geo.size.width / 1.05 )
ScrollView {
ForEach($searchString.wrappedValue == "" ? pdfsFetcher.pdfs :
pdfsFetcher.pdfs.filter({ pdf in
pdf.internalName.contains($searchString.wrappedValue.lowercased())
})
, id: \._id) { pdf in
if let parsedString = pdf.file?.split(separator: "-") {
let request = URLRequest(url: URL(string: "https://mylink/\(parsedString[1]).pdf")!)
NavigationLink(destination: WebView(request: request)
.navigationBarBackButtonHidden(backButtonHidden)
.navigationBarHidden(backButtonHidden)
.onTapGesture(perform: {
backButtonHidden.toggle()
})) {
HStack(alignment: .center) {
Image(systemName: "doc")
.padding()
.frame(width: width, alignment: .leading)
.lineLimit(1)
.alignmentGuide(.leading, computeValue: { dimension in
self.width = max(self.width ?? 0, dimension.width)
return dimension[.leading]
})
Text(pdf.internalName)
.padding()
.multilineTextAlignment(.leading)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}
.padding(.leading)
}
}
}
.navigationBarHidden(true)
}
.accentColor(Color.black)
.onAppear{
pdfsFetcher.pdfs == [] ? pdfsFetcher.fetchPDFs() : nil
}
}
}
}
}
Pdf list and Searchbar.
The same view on Searchbar focus.
I would like the search string to filter the list of pdfs while maintaining the visibility of the list.
I was able to fix this by making my #ObservableObject an #EnvironmentObject in my App :
#main
struct MyApp: App {
#ObservedObject var pdfsFetcher = PDFsFetcher()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(pdfsFetcher)
}
}
}
struct AllPdfListView: View {
#EnvironmentObject var pdfsFetcher: PDFsFetcher
}
I am trying to make an application where the user can see a list of foods and recipes and make changes etc. In the DetailView for each food, there is an EditView where the values can be changed. I am trying to use a double binding on the value by using #State to define the value and $food.name for example to make the changes happen.
When I click 'Done' and exit this view back to the DetailView, the changes are not made at all, leaving me confused?
Any help on this problem would be greatly appreciated, thank you :)
My EditView.swift:
import SwiftUI
struct EditView: View {
#State var food: Food
var body: some View {
List {
Section(header: Text("Name")) {
TextField("Name", text: $food.name)
}
Section(header: Text("Image")) {
TextField("Image", text: $food.image)
}
Section(header: Text("Desc")) {
TextField("Desc", text: $food.desc)
}
Section(header: Text("Story")) {
TextField("Story", text: $food.story)
}
}.listStyle(InsetGroupedListStyle())
}
}
struct EditView_Previews: PreviewProvider {
static var previews: some View {
EditView(food: cottonCandy)
}
}
My FoodDetail.swift:
import SwiftUI
struct FoodDetail: View {
#State var food: Food
#State private var isPresented = false
var body: some View {
VStack {
Image(food.image)
.resizable()
.frame(width: 300.0,height:300.0)
.aspectRatio(contentMode: .fill)
.shadow(radius: 6)
.padding(.bottom)
ScrollView {
VStack(alignment: .leading) {
Text(food.name)
.font(.largeTitle)
.fontWeight(.bold)
.padding(.leading)
.multilineTextAlignment(.leading)
Text(food.desc)
.italic()
.fontWeight(.ultraLight)
.padding(.horizontal)
.multilineTextAlignment(.leading)
Text(food.story)
.padding(.horizontal)
.padding(.top)
Text("Ingredients")
.bold()
.padding(.horizontal)
.padding(.vertical)
ForEach(food.ingredients, id: \.self) { ingredient in
Text(ingredient)
Divider()
}.padding(.horizontal)
Text("Recipe")
.bold()
.padding(.horizontal)
.padding(.vertical)
ForEach(food.recipe, id: \.self) { step in
Text(step)
Divider()
}.padding(.horizontal)
}.frame(maxWidth: .infinity)
}.frame(minWidth: 0,
maxWidth: .infinity,
maxHeight: .infinity,
alignment: .center
)
}
.navigationBarItems(trailing: Button("Edit") {
isPresented = true
})
.fullScreenCover(isPresented: $isPresented) {
NavigationView {
EditView(food: food)
.navigationTitle(food.name)
.navigationBarItems(leading: Button("Cancel") {
isPresented = false
}, trailing: Button("Done") {
isPresented = false
})
}
}
}
}
struct FoodDetail_Previews: PreviewProvider {
static var previews: some View {
Group {
FoodDetail(food: cottonCandy)
}
}
}
Inside EditView, you want to have a Binding. Replace
#State var food: Food
with
#Binding var food: Food
... then, you'll need to pass it in:
.fullScreenCover(isPresented: $isPresented) {
NavigationView {
EditView(food: $food) /// make sure to have dollar sign
.navigationTitle(food.name)
.navigationBarItems(leading: Button("Cancel") {
isPresented = false
}, trailing: Button("Done") {
isPresented = false
})
}
}
I'm trying to pass FetchResult Data from one screen to another, through a Navigation Link in a ScrollView.
When I try to call the passed data in the DetailView screen, I get the following error:
Instance member "" cannoth be used on type "SavedPoem"
Code below - Saved Poem List
import SwiftUI
struct SavedPoemList: View {
#Environment(\.managedObjectContext) var moc
#FetchRequest(entity: SavedPoem.entity(), sortDescriptors: []) var savedpoems : FetchedResults<SavedPoem>
var body: some View {
VStack (alignment: .leading, spacing: 0) {
HStack{
Text("Your Saved Poems")
.font(.title)
.fontWeight(.black)
.foregroundColor(.black)
Spacer()
}.padding(.bottom)
.padding(.trailing)
.padding(.leading)
ScrollView {
ForEach(savedpoems, id:\.title) {SavedPoem in
NavigationLink (destination: DetailViewSaved()){
ZStack {
Rectangle()
.fill(Color.white)
.frame(width: UIScreen.screenWidth - 40, height: 70)
.cornerRadius(5)
.padding([.horizontal], 20)
// .shadow(color: .gray, radius: 10)
HStack {
VStack (alignment: .leading){
Text("\(SavedPoem.title ?? "")")
.font(.headline)
.foregroundColor(.black)
.lineLimit(1)
.padding(.bottom, 3)
Text("\(SavedPoem.author ?? "")")
.font(.subheadline)
.foregroundColor(.secondary)
}
.padding(.trailing)
Spacer()
}
.padding()
}.padding(.bottom,10)
}
}.onDelete(perform: self.remove)
}
.navigationTitle("My Saved Poems")
.navigationBarHidden(true)
.edgesIgnoringSafeArea(.top)
.padding(.bottom, 30)
}
.padding(.horizontal, 30)
.edgesIgnoringSafeArea(.bottom)
}
func remove(at offsets : IndexSet) {
for index in offsets {
let delete = savedpoems[index]
self.moc.delete(delete)
}
try? self.moc.save()
}
}
and Code for the Detail View
import SwiftUI
struct DetailViewSaved: View {
#ObservedObject var fetch = FetchPoem()
#Environment(\.managedObjectContext) var moc
#FetchRequest(entity: SavedPoem.entity(), sortDescriptors: []) var savedpoems : FetchedResults<SavedPoem>
#State private var saved : Bool = false
var currentDate = Text(Date().addingTimeInterval(600), style: .date)
var body: some View {
VStack {
HStack{
// NavigationLink( destination: HomeView())
// {
//
// Image(systemName: "arrow.backward")
// .font(.system(size: 25, weight: .heavy))
// .foregroundColor(.black)
// }
Spacer(minLength: 0)
Button(action:
{
// self.moc.delete(delete)
try? self.moc.save()
}) {
Image(systemName: saved ? "bookmark.fill": "bookmark")
.font(.system(size: 25, weight: .heavy))
.foregroundColor(.black)
}
}
ScrollView {
VStack {
HStack{
VStack (alignment: .leading) {
Text("Today's Poem, \(currentDate)")
.font(.subheadline)
.foregroundColor(Color.gray)
.padding(.bottom, 20)
.padding(.top, 10)
Text("\(SavedPoem.title ?? "")")
// .font(.largeTitle)
// .fontWeight(.heavy)
// .foregroundColor(.black)
// .padding(.bottom, 20)
// .lineSpacing(0)
// Text("BY "+poem.author.uppercased())
Text("BY \(SavedPoem.author ?? "")")
// .font(.subheadline)
// .foregroundColor(Color.gray)
// .padding(.bottom, 20)
HStack {
Text("\(SavedPoem.lines ?? "")")
// .font(.body)
// .foregroundColor(.black)
// .padding(.bottom)
// .lineSpacing(5)
//
Spacer()
}
Spacer()
}
.padding()
}
}
}
}
}
}
Am I missing anything? How can I resolve this issue, and pass the data from the Fetchedresults in the list view to the detailed screen?
Thanks in advance.
EDITED CODE FOR REPLY
SavedPoemList:
import SwiftUI
struct SavedPoemList: View {
#Environment(\.managedObjectContext) var moc
#FetchRequest(entity: SavedPoem.entity(), sortDescriptors: []) var savedpoems : FetchedResults<SavedPoem>
var body: some View {
VStack (alignment: .leading, spacing: 0) {
HStack{
Text("Your Saved Poems")
.font(.title)
.fontWeight(.black)
.foregroundColor(.black)
Spacer()
Text("Edit")
.font(.subheadline)
.fontWeight(.black)
.foregroundColor(.gray)
}.padding(.bottom)
.padding(.trailing)
.padding(.leading)
ScrollView {
ForEach(savedpoems, id:\.title) {SavedPoem in
NavigationLink (destination: DetailViewSaved(savedPoem: SavedPoem)){
ZStack {
Rectangle()
.fill(Color.white)
.frame(width: UIScreen.screenWidth - 40, height: 70)
.cornerRadius(5)
.padding([.horizontal], 20)
// .shadow(color: .gray, radius: 10)
HStack {
VStack (alignment: .leading){
Text("\(SavedPoem.title ?? "")")
.font(.headline)
.foregroundColor(.black)
.lineLimit(1)
.padding(.bottom, 3)
Text("\(SavedPoem.author ?? "")")
.font(.subheadline)
.foregroundColor(.secondary)
}
.padding(.trailing)
Spacer()
}
.padding()
}.padding(.bottom,10)
}
}.onDelete(perform: self.remove)
}
.navigationTitle("My Saved Poems")
.navigationBarHidden(true)
.edgesIgnoringSafeArea(.top)
.padding(.bottom, 30)
}
.padding(.horizontal, 30)
.edgesIgnoringSafeArea(.bottom)
}
func remove(at offsets : IndexSet) {
for index in offsets {
let delete = savedpoems[index]
self.moc.delete(delete)
}
try? self.moc.save()
}
}
DetailView
import SwiftUI
struct DetailViewSaved: View {
#ObservedObject var fetch = FetchPoem()
#Environment(\.managedObjectContext) var moc
#FetchRequest(entity: SavedPoem.entity(), sortDescriptors: []) var savedpoems : FetchedResults<SavedPoem>
#State private var saved : Bool = false
var savedPoem : SavedPoem
var currentDate = Text(Date().addingTimeInterval(600), style: .date)
var body: some View {
VStack {
HStack{
// NavigationLink( destination: HomeView())
// {
//
// Image(systemName: "arrow.backward")
// .font(.system(size: 25, weight: .heavy))
// .foregroundColor(.black)
// }
Spacer(minLength: 0)
Button(action:
{
// self.moc.delete(delete)
try? self.moc.save()
}) {
Image(systemName: saved ? "bookmark.fill": "bookmark")
.font(.system(size: 25, weight: .heavy))
.foregroundColor(.black)
}
}
ScrollView {
VStack {
HStack{
VStack (alignment: .leading) {
// Text("Today's Poem, \(currentDate)")
// .font(.subheadline)
// .foregroundColor(Color.gray)
// .padding(.bottom, 20)
// .padding(.top, 10)
Text("\(savedPoem.title ?? "")")
// .font(.largeTitle)
// .fontWeight(.heavy)
// .foregroundColor(.black)
// .padding(.bottom, 20)
// .lineSpacing(0)
// Text("BY "+poem.author.uppercased())
// Text("BY \(SavedPoem.author ?? "")")
// .font(.subheadline)
// .foregroundColor(Color.gray)
// .padding(.bottom, 20)
// HStack {
// Text("\(SavedPoem.lines ?? "")")
// .font(.body)
// .foregroundColor(.black)
// .padding(.bottom)
// .lineSpacing(5)
//
Spacer()
}
Spacer()
}
.padding()
}
}
}
}
}
}
struct DetailViewSaved_Previews: PreviewProvider {
static var previews: some View {
DetailViewSaved(savedPoem: SavedPoem)
}
}
I made an example with your case :
SavedPoemList : Pass an item from your array to your Detail View like that :
NavigationLink (destination: DetailViewSaved(savedPoem: SavedPoem)){
VStack{
Text("Your row view")
}
}
and to receive it in your Detail View :
struct DetailViewSaved: View {
var savedPoem : SavedPoem
var body: some View {
Text("Your view")
}
}
In my code I get this error and I cannot figure out how to resolve it. The error is in the Trailing block of code
struct Map: View {
#ObservedObject public var dataManager = DataManager.shared
#Binding public var seqId: String
// rz- to pass seqId to second view
// #State public var seqId2: String = ""
var body: some View {
ZStack {
VStack {
Text("Results").foregroundColor(Color.white).onAppear{self.dataManager.downloadSeqData(seqId: self.seqId)} .onAppear(perform: playSound)/*rz want to add this sound func to contentview somehow, otherwise it will constantly play sound when page loads */ .edgesIgnoringSafeArea(.all)
//rz- if strand is linear draw line
if dataManager.dataSet?.INSDSeq.topology == "linear" {
Rectangle()
.fill(Color.black)
.frame(width: 500, height: 20)
}
//rz- if strand is circular draw o
if dataManager.dataSet?.INSDSeq.topology == "circular" {
Circle()
.stroke(Color.black, style: StrokeStyle(lineWidth: 20, lineCap: .round, lineJoin: .round))
.frame(width: 500, height: 500)
}
if dataManager.dataSet?.INSDSeq.topology != "circular" && dataManager.dataSet?.INSDSeq.topology != "linear"{
Text("Data Unavailable, try a new accession number.")
}
}
.navigationBarItems(
//rz - added home and genbank view to navigation bars
leading:
NavigationLink(destination: ContentView()) {
Text("New Query")
.font(.title)
.foregroundColor(Color.black)
},
trailing:
NavigationLink(destination: Screen(seqId: self.$seqId)) {
Text("GenBank View")
.font(.title)
.foregroundColor(Color.black)
Error is in $seqId
NavigationLink(destination: Screen(seqId: self.$seqId)) {
Here is the Screen view
import SwiftUI
struct Screen: View {
#ObservedObject public var dataManager = DataManager.shared
#State private var seqId: String = ""
var body: some View {
VStack {
TextField("Enter Accession Number", text: $seqId)
.padding()
Button("Search")
{
dataManager.downloadSeqData(seqId: seqId)
}
ScrollView {
VStack(alignment: .leading) {
Text(dataManager.dataSet?.INSDSeq.locus ?? "")
.padding()
Text(dataManager.dataSet?.INSDSeq.organism ?? "").padding()
Text(dataManager.dataSet?.INSDSeq.source ?? "").padding()
Text(dataManager.dataSet?.INSDSeq.taxonomy ?? "").padding()
Text(dataManager.dataSet?.INSDSeq.topology ?? "").padding()
Text(dataManager.dataSet?.INSDSeq.length == nil ? "" : "\(dataManager.dataSet!.INSDSeq.length)") .padding()
Text(dataManager.dataSet?.INSDSeq.strandedness ?? "").padding()
Text(dataManager.dataSet?.INSDSeq.moltype ?? "").padding()
Text(dataManager.dataSet?.INSDSeq.sequence ?? "").padding()
}
.cornerRadius(10)
VStack(alignment: .leading, spacing: 10) {
ForEach(dataManager.featureList, id:\.self) { feature in
VStack (alignment: .leading){
VStack (alignment: .leading) {
Text(feature.INSDFeature_key).bold()
Text(feature.INSDFeature_location)
}.padding()
IntervalSection(feature: feature)
QualsSection(feature: feature)
}
.cornerRadius(10)
}
}
.cornerRadius(20)
}
.padding(.horizontal)
}
}
}
struct IntervalSection: View {
var feature: INSDFeature
var body: some View {
VStack (alignment: .leading){
ForEach(0..<feature.INSDFeature_intervals.count, id: \.self) { i in
ForEach(0..<feature.INSDFeature_intervals[i].INSDInterval.count, id: \.self) { j in
if let from = feature.INSDFeature_intervals[i].INSDInterval[j].INSDInterval_from {
VStack (alignment: .leading){
Text("\(from)").bold()
Text("\(feature.INSDFeature_intervals[i].INSDInterval[j].INSDInterval_to ?? -1)")
}
.padding()
.cornerRadius(10)
}
}
}
}
}
}
struct QualsSection: View{
var feature: INSDFeature
var body: some View {
VStack (alignment: .leading){
ForEach(0..<feature.INSDFeature_quals.count , id: \.self) { i in
ForEach(0..<feature.INSDFeature_quals[i].INSDQualifier.count , id: \.self) { j in
VStack (alignment: .leading){
Text(feature.INSDFeature_quals[i].INSDQualifier[j].INSDQualifier_name).bold()
Text(feature.INSDFeature_quals[i].INSDQualifier[j].INSDQualifier_value)
}
.padding()
.cornerRadius(10)
}
}
}
}
}
In SwiftUI you should use Binding instead of State in cases, where the data is coming from another view. Furthermore both attributes of Screen are private, therefore they can't be accessed in this case set from outside of the struct itself.
I would suggest to make seqID in Screen public like you did it with dataManager and change it to State