Reputation: 1
I am new to iOS development and I have been working on a project using SwiftUI. I have a sheet where I can buy or sell some stocks. On successful transaction, I am supposed to show a green screen with success message. The problem is that my implementation just shows the green screen suddenly as opposed to it being animated/faded in. Here is what I mean: This is the way my app behaves and this is how I want it to behave.
Here is the code for the sheet:
//
// TradingSheetView.swift
// Stock Search
//
// Created by Kishan on 4/29/24.
//
import SwiftUI
import SimpleToast
struct TradingSheetView: View {
@EnvironmentObject var root: ToastViewModel
@StateObject var viewModel = TradingSheetViewModel()
@Binding var isTrading: Bool
@Binding var company: Company?
@Binding var portfolio: Portfolio?
@Binding var wallet: Wallet?
private var tradingQuantity: Int {
let tradingQuantityInt = Int(viewModel.tradingQuantity)
// if tradingQuantityInt == nil {
// root.showToast(saying: "Please enter a valid amount")
// }
return tradingQuantityInt ?? 0
}
private var tradingAmount: Double {
return (viewModel.quote?.c ?? 0) * Double(tradingQuantity)
}
var body: some View {
ZStack {
VStack {
HStack {
Spacer()
Button {
isTrading.toggle()
} label: {
Image(systemName: "xmark")
.foregroundStyle(Color(.label))
}
}
Text("Trade \(company?.name ?? "") shares")
.bold()
Spacer()
HStack {
TextField("0",
text: $viewModel.tradingQuantity)
.font(.system(size: 100, weight: .light))
.keyboardType(.numberPad)
Text(tradingQuantity > 1 ? "Shares" : "Share")
.font(.largeTitle)
.offset(y: 20)
}
HStack {
Spacer()
Text("x $\((viewModel.quote?.c ?? 0).getTwoPointsString())/share = $\(tradingAmount.getTwoPointsString())")
}
Spacer()
Text("$\((wallet?.amount ?? 0).getTwoPointsString()) available to buy \(company?.ticker ?? "")")
.font(.caption)
.foregroundStyle(.secondary)
.padding()
HStack(spacing: 20) {
Button {
Task {
if tradingAmount > (wallet?.amount ?? 0) {
root.showToast(saying: "Not enough money to buy")
return
}
if tradingQuantity <= 0 {
root.showToast(saying: "Cannot buy non-positive shares")
return
}
await viewModel.buy(tradingQuantity,
of: company?.ticker,
at: viewModel.quote?.c,
called: company?.name)
}
} label: {
PortfolioDetailsButton(title: "Buy")
}
Button {
Task {
if tradingQuantity > (portfolio?.quantity ?? 0) {
root.showToast(saying: "Not enough shares to sell")
return
}
if tradingQuantity <= 0 {
root.showToast(saying: "Cannot sell non-positive shares")
return
}
await viewModel.sell(tradingQuantity,
of: company?.ticker,
at: viewModel.quote?.c)
}
} label: {
PortfolioDetailsButton(title: "Sell")
}
}
}
.padding()
.onAppear() {
Task {
await viewModel.fetchCurrentQuote(for: company?.ticker ?? "")
}
}
if viewModel.transactionSuccess {
withAnimation(.easeInOut.speed(5)) {
ZStack {
Color.green.ignoresSafeArea()
VStack() {
Spacer()
Text("Congratulations!")
.bold()
.font(.largeTitle)
.foregroundStyle(.white)
Text(viewModel.transactionMessage)
.font(.callout)
.foregroundStyle(.white)
.padding(.vertical, 1)
Spacer()
Button {
isTrading.toggle()
} label: {
Text("Done")
.bold()
.frame(width: 350, height: 50)
.background(in: .capsule)
.foregroundStyle(.green)
}
}
.padding()
}
}
}
}
.simpleToast(isPresented: $root.isToastVisible,
options: root.toastOptions) {
ToastView(message: $root.toastMessage)
}
}
}
#Preview {
TradingSheetView(isTrading: .constant(true),
company: .constant(mockCompany),
portfolio: .constant(mockPortfolio),
wallet: .constant(mockWallet))
}
Edit:
As stated by @Sweeper below, I tried to replicate the view. I am not sure if it replicates it completely but here is the code:
//
// TestView.swift
// Stock Search
//
// Created by Kishan on 4/29/24.
//
import SwiftUI
struct TestView: View {
@State var success = false
var body: some View {
ZStack {
Button("Press here to perform transaction") {
Task {
await performTransaction()
}
}
if success {
ZStack {
Color.green.ignoresSafeArea()
VStack {
Text("Congratulations!")
.bold()
.font(.title)
.foregroundStyle(.white)
.padding(.vertical)
Button {
Task {
await performTransaction()
}
} label: {
Text("Done")
.bold()
.frame(width: 300, height: 50)
.background(in: .capsule)
.foregroundStyle(.green)
}
}
}
}
}
}
func performTransaction() async {
// Perform some transaction
success.toggle()
}
}
#Preview {
TestView()
}
I have tried using the .animation
modifier and withAnimation
as well, but it does not seem to work. Is there something that might be conflicting with how the animations are supposed to be performed?
Upvotes: 0
Views: 142
Reputation:
func performTransaction() async {
// Perform some transaction
withAnimation(.easeIn.speed(0.6)) {
success.toggle()
}
}
Read more about animation https://www.hackingwithswift.com/quick-start/swiftui, scroll down to Animation
Upvotes: 0