I'm creating a flashcard view for language education. The first iteration consisted of flipping cards to front and back. The second iteration consisted of an addition of a swipe-based interface. The third iteration was meant to combine the previous two; however I'm having animation visualization issues (i.e. the third flip animation doesn't look like the first iteration).
first and third iteration gif displaying issue
first iteration code:
struct CardBack : View {
let width : CGFloat
let height : CGFloat
let firLanguage: String
let wordClass: String
let accuracy: String
let definition: String
#Binding var degree : Double
var body: some View {
ZStack {
VStack {
HStack {
Text(wordClass)
.padding(10)
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.padding(.horizontal, 5)
.padding(.top, 5)
.font(.system(size: 15))
Text(firLanguage)
.padding(10)
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.padding(.trailing, 5)
.padding(.top, 5)
.font(.system(size: 15))
Text(accuracy)
.padding(10)
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.padding(.trailing, 5)
.padding(.top, 5)
.font(.system(size: 15))
Spacer()
Image(systemName: "command.circle.fill")
.font(.system(size: 29))
.padding(.horizontal, 5)
.padding(.top, 5)
.foregroundColor(Color.gray)
}
Spacer()
HStack {
Text("word analysis subview")
.padding(10)
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.padding(.horizontal, 5)
.padding(.bottom, 5)
.font(.system(size: 15))
Spacer()
}
}
.frame(width: 350, height: 190)
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 5)
VStack {
Spacer()
Text(definition)
.font(.title)
Spacer()
}
.frame(width: 350, height: 90)
.background(Color.white)
.cornerRadius(0)
.shadow(radius: 1)
}
.rotation3DEffect(Angle(degrees: degree), axis: (x: 1, y: 0, z: 0))
}
}
struct CardFront : View {
let width : CGFloat
let height : CGFloat
let secLanguage: String
let wordClass: String
let accuracy: String
let term: String
#Binding var degree : Double
var body: some View {
ZStack {
VStack {
HStack {
Text(wordClass)
.padding(10)
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.padding(.horizontal, 5)
.padding(.top, 5)
.font(.system(size: 15))
Text(secLanguage)
.padding(10)
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.padding(.trailing, 5)
.padding(.top, 5)
.font(.system(size: 15))
Text(accuracy)
.padding(10)
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.padding(.trailing, 5)
.padding(.top, 5)
.font(.system(size: 15))
Spacer()
Image(systemName: "command.circle.fill")
.font(.system(size: 29))
.padding(.horizontal, 5)
.padding(.top, 5)
.foregroundColor(Color.gray)
}
Spacer()
HStack {
Text("word analysis subview")
.padding(10)
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.padding(.horizontal, 5)
.padding(.bottom, 5)
.font(.system(size: 15))
Spacer()
}
}
.frame(width: 350, height: 190)
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 5)
VStack {
Spacer()
Text(term)
.font(.title)
Spacer()
}
.frame(width: 350, height: 90)
.background(Color.white)
.cornerRadius(0)
.shadow(radius: 1)
}
.rotation3DEffect(Angle(degrees: degree), axis: (x: 1, y: 0, z: 0))
}
}
struct CardFlipView: View {
//MARK: Variables
#State var backDegree = 0.0
#State var frontDegree = -90.0
#State var isFlipped = true
let width : CGFloat = 200
let height : CGFloat = 250
let durationAndDelay : CGFloat = 0.3
let firLanguage: String = "English"
let secLanguage: String = "Spanish"
let wordClass: String = "Verb"
let accuracy: String = "63%"
let term: String = "hablar"
let definition: String = "to talk"
//MARK: Flip Card Function
func flipCard () {
isFlipped = !isFlipped
if isFlipped {
withAnimation(.linear(duration: durationAndDelay)) {
backDegree = 90
}
withAnimation(.linear(duration: durationAndDelay).delay(durationAndDelay)){
frontDegree = 0
}
} else {
withAnimation(.linear(duration: durationAndDelay)) {
frontDegree = -90
}
withAnimation(.linear(duration: durationAndDelay).delay(durationAndDelay)){
backDegree = 0
}
}
}
//MARK: View Body
var body: some View {
ZStack {
CardBack(width: width, height: height, firLanguage: firLanguage, wordClass: wordClass, accuracy: accuracy, definition: definition, degree: $frontDegree)
CardFront(width: width, height: height, secLanguage: secLanguage, wordClass: wordClass, accuracy: accuracy, term: term, degree: $backDegree)
}.onTapGesture {
flipCard ()
}
}
}
third iteration code:
struct Word: Hashable, CustomStringConvertible {
var id: Int
let front: String
let back: String
let term: String
let definition: String
let accuracy: Int
let wordclass: String
var description: String {
return "\(term), id: \(id)"
}
}
struct ContentView3: View {
/// List of words
#State var words: [Word] = [
Word(id: 0, front: "Spanish", back: "English", term: "to speak", definition: "hablar", accuracy: 63, wordclass: "Verb"),
Word(id: 1, front: "Spanish", back: "English", term: "to eat", definition: "comer", accuracy: 63, wordclass: "Verb"),
//Word(id: 2, front: "Spanish", back: "English", term: "to think", definition: "pensar", accuracy: 63, wordclass: "Verb"),
//Word(id: 3, front: "Spanish", back: "English", term: "to live", definition: "vivir", accuracy: 63, wordclass: "Verb"),
//Word(id: 4, front: "Spanish", back: "English", term: "to write", definition: "escribir", accuracy: 63, wordclass: "Verb"),
]
/// Return the CardViews width for the given offset in the array
/// - Parameters:
/// - geometry: The geometry proxy of the parent
/// - id: The ID of the current user
private func getCardWidth(_ geometry: GeometryProxy, id: Int) -> CGFloat {
let offset: CGFloat = CGFloat(words.count - 1 - id) * 10
return geometry.size.width - offset
}
/// Return the CardViews frame offset for the given offset in the array
/// - Parameters:
/// - geometry: The geometry proxy of the parent
/// - id: The ID of the current user
private func getCardOffset(_ geometry: GeometryProxy, id: Int) -> CGFloat {
return CGFloat(words.count - 1 - id) * 10
}
private var maxID: Int {
return self.words.map { $0.id }.max() ?? 0
}
var body: some View {
VStack {
GeometryReader { geometry in
LinearGradient(gradient: Gradient(colors: [Color.init(#colorLiteral(red: 0.9686274529, green: 0.78039217, blue: 0.3450980484, alpha: 1)), Color.init(#colorLiteral(red: 1, green: 0.9882352941, blue: 0.862745098, alpha: 1))]), startPoint: .bottom, endPoint: .top)
.frame(width: geometry.size.width * 1.5, height: geometry.size.height)
.background(Color.yellow)
.clipShape(Circle())
.offset(x: -geometry.size.width / 4, y: -geometry.size.height / 6)
VStack(spacing: 24) {
Spacer()
ZStack {
ForEach(self.words, id: \.self) { word in
Group {
// Range Operator
if (self.maxID - 3)...self.maxID ~= word.id {
CardView(word: word, onRemove: { removedWord in
// Remove that user from our array
self.words.removeAll { $0.id == removedWord.id }
})
.animation(.spring())
.frame(width: self.getCardWidth(geometry, id: word.id), height: 400)
.offset(x: 0, y: self.getCardOffset(geometry, id: word.id))
}
}
}
}
Spacer()
}
}
}.padding()
}
}
//MARK: CardView
struct CardView: View {
#State private var translation: CGSize = .zero
#State private var swipeStatus: LikeDislike = .none
#State var backDegree = 0.0
#State var frontDegree = -90.0
#State var isFlipped = true
let durationAndDelay : CGFloat = 0.3
var word: Word
private var onRemove: (_ word: Word) -> Void
private var thresholdPercentage: CGFloat = 0.5 // when the user has draged 50% the width of the screen in either direction
private enum LikeDislike: Int {
case like, dislike, none
}
init(word: Word, onRemove: #escaping (_ word: Word) -> Void) {
self.word = word
self.onRemove = onRemove
}
private func getGesturePercentage(_ geometry: GeometryProxy, from gesture: DragGesture.Value) -> CGFloat {
gesture.translation.width / geometry.size.width
}
func flipCard () {
isFlipped = !isFlipped
if isFlipped {
withAnimation(.linear(duration: durationAndDelay)) {
backDegree = 90
}
withAnimation(.linear(duration: durationAndDelay).delay(durationAndDelay)){
frontDegree = 0
}
} else {
withAnimation(.linear(duration: durationAndDelay)) {
frontDegree = -90
}
withAnimation(.linear(duration: durationAndDelay).delay(durationAndDelay)){
backDegree = 0
}
}
}
var body: some View {
GeometryReader { geometry in
VStack(alignment: .leading) {
ZStack(alignment: self.swipeStatus == .like ? .topLeading : .topTrailing) {
if self.swipeStatus == .like {
Text("YES")
.font(.headline)
.padding()
.cornerRadius(10)
.foregroundColor(Color.green)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.green, lineWidth: 3.0)
).padding(24)
.rotationEffect(Angle.degrees(-45))
} else if self.swipeStatus == .dislike {
Text("NO")
.font(.headline)
.padding()
.cornerRadius(10)
.foregroundColor(Color.red)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.red, lineWidth: 3.0)
).padding(.top, 45)
.rotationEffect(Angle.degrees(45))
}
ZStack {
CardFront2(word: word, degree: $frontDegree)
CardBack2(word: word, degree: $backDegree)
}.onTapGesture {
flipCard ()
}
}
}
.animation(.interactiveSpring())
.offset(x: self.translation.width, y: 0)
.rotationEffect(.degrees(Double(self.translation.width / geometry.size.width) * 1), anchor: .bottom)
.gesture(
DragGesture()
.onChanged { value in
self.translation = value.translation
if (self.getGesturePercentage(geometry, from: value)) >= self.thresholdPercentage {
self.swipeStatus = .like
} else if self.getGesturePercentage(geometry, from: value) <= -self.thresholdPercentage {
self.swipeStatus = .dislike
} else {
self.swipeStatus = .none
}
}.onEnded { value in
// determine snap distance > 0.5 (half the width of the screen)
if abs(self.getGesturePercentage(geometry, from: value)) > self.thresholdPercentage {
self.onRemove(self.word)
} else {
self.translation = .zero
}
}
)
}
}
}
struct CardFront2 : View {
var word: Word
#Binding var degree : Double
var body: some View {
ZStack {
HStack {
VStack(alignment: .leading, spacing: 6) {
HStack {
Text("\(self.word.front)") ///add toggleability
.font(.subheadline)
.foregroundColor(.gray)
.padding(7)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))
.cornerRadius(10)
Text("\(self.word.wordclass)") ///add toggleability
.font(.subheadline)
.foregroundColor(.gray)
.padding(7)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))
.cornerRadius(10)
Text("\(self.word.accuracy)%") ///add toggleability
.font(.subheadline)
.foregroundColor(.gray)
.padding(7)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))
.cornerRadius(10)
Spacer()
Image(systemName: "info.circle")
.foregroundColor(.gray)
}.padding(.top, 15)
HStack {
Spacer()
Text("\(self.word.definition)")
.font(.title)
.bold()
Spacer()
}.padding(.vertical, 15)
}
Spacer()
}
.padding(.horizontal, 10)
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 5)
}
.rotation3DEffect(Angle(degrees: degree), axis: (x: 0, y: 1, z: 0))
}
}
struct CardBack2 : View {
var word: Word
#Binding var degree : Double
var body: some View {
ZStack {
HStack {
VStack(alignment: .leading, spacing: 6) {
HStack {
Text("\(self.word.back)") ///add toggleability
.font(.subheadline)
.foregroundColor(.gray)
.padding(7)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))
.cornerRadius(10)
Text("\(self.word.wordclass)") ///add toggleability
.font(.subheadline)
.foregroundColor(.gray)
.padding(7)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))
.cornerRadius(10)
Text("\(self.word.accuracy)%") ///add toggleability
.font(.subheadline)
.foregroundColor(.gray)
.padding(7)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))
.cornerRadius(10)
Spacer()
Image(systemName: "info.circle")
.foregroundColor(.gray)
}.padding(.top, 15)
HStack {
Spacer()
Text("\(self.word.term)")
.font(.title)
.bold()
Spacer()
}.padding(.vertical, 15)
}
Spacer()
}
.padding(.horizontal, 10)
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 5)
}
.rotation3DEffect(Angle(degrees: degree), axis: (x: 0, y: 1, z: 0))
}
}
I tried moving the .onTapGesture onto different parent views. I have really tried playing with all things animation for a few hours now, and I haven't been able to crack it. I want the card flip on iteration 3 to mirror that of iteration 1.
To update you guys on my complete fix.
At first I was clueless, then I identified the GeometryReader{} (GR) under CardView() as potentially the issue; however, it was actually the unnecessary VStack{} directly under the GR that it was reading from, instead of the ZStack{}. Outlined below.
GeometryReader { geometry in
VStack { // <-REMOVED
ZStack(alignment: self.swipeStatus == .yes ? .topLeading : .topTrailing) {
if self.swipeStatus == .yes {...} else if self.swipeStatus == .no {...}
ZStack {
CardFront2(word: word, degree: $frontDegree)
CardBack2(word: word, degree: $backDegree)
}.onTapGesture {
flipCard ()
}
}
After removing the above outlined code I was able to see more of the animation take place; however it still wasn't complete. I identified an animation in the ContentView() causing it. Outlined below.
ZStack {
ForEach(self.words, id: \.self) { word in
Group {
if (self.maxID - 3)...self.maxID ~= word.id {
CardView2(word: word, onRemove: { removedWord in
self.words.removeAll { $0.id == removedWord.id }
})
.animation(.spring()) // <-REMOVED
.frame(width: self.getCardWidth(geometry, id: word.id), height: 400)
.offset(x: 0, y: self.getCardOffset(geometry, id: word.id))
}
}
}
}
I'm quite self-taught, so I consistently need shoving in the right direction. Thank you both for your pointers!
hello i have an issue with my project on Xcode when I use navigation view, the window display not normally and appear on the right of the window already displayed,
here is the code.
NavigationLink(destination: Acceuil())
{
HStack{
Image("icone_connexion")
.font(.system(size: 15))
// .scaledToFill()
Text("se connecter")
.font(.system(size: 30))
}.cornerRadius(60)
.frame(width: 400, height: 60)
} .background(Capsule().fill(Color(red: 55/255, green: 66/255, blue: 114/255, opacity:1)))
.frame(width: 400, height: 60) //fin navigationlink
.buttonStyle(PlainButtonStyle())
I would like that the new window replace the older one:)
On macOS it is the standard behavior in NavigationView to show the views (parent view and destination view) next to each other: https://developer.apple.com/design/human-interface-guidelines/macos/windows-and-views/column-views/
If you don't want that you can do:
NavigationView {
...
}
.navigationViewStyle(.stack)
so I found this code
import SwiftUI
struct ContentView: View {
#State private var show = false
var body: some View {
VStack{
if !show {
RootView(show: $show)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
.transition(AnyTransition.move(edge: .leading)).animation(.default)
}
if show {
NextView(show: $show)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.green)
.transition(AnyTransition.move(edge: .trailing)).animation(.default)
}
}
}
}
struct RootView: View {
#Binding var show: Bool
var body: some View {
VStack{
Button("Next") { self.show = true }
Text("This is the first view")
}
}
}
it work grate for me so thanks you for your help
I am looking to make a quiz app using SwiftUI. I have now designed all of the views, but I am having trouble displaying the questions correctly.
I have a home view which for now just has a button that should display a questionView (has only one question) in order and one at a time.
I am using a ForEach to step through each question in a questions array and display a questionView with that specific question, but the problem is that the ForEach displays every question at the same time instead of waiting for the question to be submitted.
How can communicate with the ForEach (or any other function) to tell it when to start and stop showing questionViews.
struct Home: View {
#State var presentQuestionView: Bool = false
#StateObject var questionViewModel: QuestionViewModel = QuestionViewModel()
#State var isCompleted = false
var body: some View {
VStack {
Spacer()
Text("Guess Players")
.font(.title2)
.bold()
.onTapGesture {
presentQuestionView.toggle()
}
Spacer()
}
.sheet(isPresented: $presentQuestionView, content: {
ForEach(questionViewModel.questions.indices) { index in
QuestionView(question: questionViewModel.questions[index], presentQuestionView: $presentQuestionView, progressWidth: questionViewModel.progress(currentIndex: index) )
.offset(x: questionViewModel.currentQuestion().isCompleted ? 1000 : 0)
.rotationEffect(.init(degrees: questionViewModel.currentQuestion().isCompleted ? 1000 : 0))
}
})
}
}
when the button is clicked, I want the ForEach statement to present the QuestionView one at a time.
Here is my QuestionView
struct QuestionView: View {
#ObservedObject var question: Question
#Binding var presentQuestionView: Bool
var progressWidth: CGFloat
#State var isSubmitted = false
#State var buttonText = "Submit"
var body: some View {
VStack {
ZStack(alignment: Alignment(horizontal: .leading, vertical: .center), content: {
Capsule()
.fill(Color.gray.opacity(0.7))
.frame(height: 6)
Capsule()
.fill(Color.green)
.frame(width: progressWidth, height: 6)
})
Text("Guess The Player!")
.font(.system(size: 38))
.fontWeight(.heavy)
.foregroundColor(.purple)
.padding(.top)
Text("Career Averages: ")
.font(.title2)
.fontWeight(.heavy)
.foregroundColor(.black)
.padding(.top, 8)
Text("Points Per Game: \(question.answer.stats!.pointsPerGame)")
.font(.system(size: 20))
.fontWeight(.heavy)
.foregroundColor(.black)
.padding(.top, 5)
Text("Assists Per Game: \(question.answer.stats!.assistsPerGame)")
.font(.system(size: 20))
.fontWeight(.heavy)
.foregroundColor(.black)
.padding(.top, 5)
Text("Rebounds Per Game: \(question.answer.stats!.reboundsPerGame)")
.font(.system(size: 20))
.fontWeight(.heavy)
.foregroundColor(.black)
.padding(.top, 5)
Spacer(minLength: 0)
LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 20), count: 2), spacing: 25, content: {
Player_Cards(question: question, isSubmitted: $isSubmitted)
})
.padding()
Spacer(minLength: 0)
Button(action: {
if isSubmitted == false {
//update the score
if question.isCorrect() {
} else {
}
//update the view to show the correct answer
isSubmitted.toggle()
buttonText = "Next Question"
} else {
//Go into the next question
}
}, label: {
Text(buttonText)
.fontWeight(.heavy)
.foregroundColor(.white)
.padding(.vertical)
.frame(maxWidth: .infinity)
.background(Color.blue)
})
}
.background(Color.black.opacity(0.05).ignoresSafeArea())
}
}
This is what currently happens when I run this project
I am trying to load image from server in a slide show with SwiftUi but image is not loading in the slide show. please see my code below
import SwiftUI
import Combine
struct ImageCarouselView<Content: View>: View {
private var numberOfImages: Int
private var content: Content
#State private var currentIndex: Int = 0
private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
init(numberOfImages: Int, #ViewBuilder content: () -> Content) {
self.numberOfImages = numberOfImages
self.content = content()
}
var body: some View {
GeometryReader { geometry in
// 1
ZStack(alignment: .bottom) {
HStack(spacing: 0) {
self.content
}
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .leading)
.offset(x: CGFloat(self.currentIndex) * -geometry.size.width, y: 0)
.animation(.spring())
.onReceive(self.timer) { _ in
self.currentIndex = (self.currentIndex + 1) % (self.numberOfImages == 0 ? 1 : self.numberOfImages)
}
// 2
HStack(spacing: 3) {
// 3
ForEach(0..<self.numberOfImages, id: \.self) { index in
// 4
Circle()
.frame(width: index == self.currentIndex ? 10 : 8,
height: index == self.currentIndex ? 10 : 8)
.foregroundColor(index == self.currentIndex ? Color.blue : .white)
.overlay(Circle().stroke(Color.gray, lineWidth: 1))
.padding(.bottom, 8)
.animation(.spring())
}
}
}
}
}
}
and in my view
struct MainView: View {
#Binding var showMenu: Bool
#State var index = 0
var body: some View {
ScrollView {
//MainView(with:"https://govcard.net/banners/banner1.jpg")
GeometryReader { geometry in
ImageCarouselView(numberOfImages: 3) {
Image("image_carousel_1")
.resizable()
.scaledToFill()
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
Image("image_carousel_2")
.resizable()
.scaledToFill()
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
Image("image_carousel_3")
.resizable()
.scaledToFill()
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
}
}.frame(height: 200, alignment: .center)
}
i want to use url instead of asset image.
As far as I've seen the easiest way would be to add the Kingfisher Swift package to your project.import KingfisherSwiftUI to your swift file and use the KFImage(myUrl).
import KingfisherSwiftUI
struct MainView: View {
//...
KFImage(URL(string: "https://example.com/image.png")!)
}
Here are the steps to add the Kingfisher to your project:
Select File > Swift Packages > Add Package Dependency.
Enter https://github.com/onevcat/Kingfisher.git in the "Choose Package Repository" dialog.
In the next page, specify the version resolving rule as "Up to Next Major" with "5.14.0" as its earliest version.
I have a SwiftUI list/detail app with many data fields that are all the same except of
course for the data. I am trying to extract a view but cannot seem to get the
connections correct.
The data is in Core Data and the entity of note is Patient. I pass a patient record to
the detail view. Everything works when the code is repeated for each data field.
While I don't think the issue is with the custom modifier, for clarity I have included
the code for the custom modifier that adds a clear button. Strangely, I could not
find a built-in SwiftUI TextField clear button.
Here is the relevant code for an individual data element - this works:
var patient: Patient
#State private var updatedTitle: String = "No Title"
//title
VStack(alignment: .leading) {
Text("Person Title:")
.padding(.leading, 5)
.font(.headline)
HStack {
TextField("Enter a Title", text: $updatedTitle)
.frame(minWidth: 0, maxWidth: .infinity)
.padding(.trailing, -25)
.padding(.leading, 5)
.frame(height: 45)
.onAppear {
self.updatedTitle = self.patient.title ?? ""
}
Text("")
.frame(width: 35, height: 35)
.modifier(ClearButton(text: self.$updatedTitle))
.padding(.trailing, 15)
.padding(.leading, -20)
}
.background(Color("TextFieldBackground")).cornerRadius(8)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color.gray, lineWidth: 1)
)
.padding(.leading, 10)
.padding(.trailing, 10)
}.padding(10)
This is my attempt to extract a subview:
struct MyDataCell {
#Binding var tfData: String
var passedInLabel: String
var patient: Patient
var body: some View {
VStack(alignment: .leading) {
Text(passedInLabel)
.padding(.leading, 5)
.font(.headline)
HStack {
TextField("Enter a Title", text: $tfData)
.frame(minWidth: 0, maxWidth: .infinity)
.padding(.trailing, -25)
.padding(.leading, 5)
.frame(height: 45)
.onAppear {
self.tfData = self.patient.title ?? ""
}
Text("")
.frame(width: 35, height: 35)
.modifier(ClearButton(text: $tfData))
.padding(.trailing, 15)
.padding(.leading, -20)
}
.background(Color("TextFieldBackground")).cornerRadius(8)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color.gray, lineWidth: 1)
)
.padding(.leading, 10)
.padding(.trailing, 10)
}.padding(10)
}
}
This is the line of code I use to call the subview - the compiler instantly complains
with an error that has nothing to do with this line.
MyDataCell(tfData: $updatedTitle, passedInLabel: "Patient Title", patient: patient)
As mentioned, this is the code for the custom modifier:
struct ClearButton: ViewModifier {
#Binding var text: String
public func body(content: Content) -> some View {
HStack {
content
Button(action: {
self.text = ""
}) {
Image(systemName: "multiply.circle.fill")
.foregroundColor(.secondary)
}
}
}
}
Xcode Version 11.2 beta 2 (11B44) I have tried both the simulator and a device. Any
guidance would be appreciated.
MyDataCell needs to confirm to View - struct MyDataCell: View {
A property needs to be passed in that is the actual attribute for the Entity. In this case pass in the string of patient.title instead of passing the Entity, Patient. Then in .onAppear use that string.
Lastly, remember the max 10 item per view - break the list into groups.