I'm trying to setup my view so that there's (in order from top of display to bottom) a VStack with some content, followed by a List, followed by another VStack with a couple buttons where progressive blurs separate the list and the two VStack's content. Now, in the current version of my app when the user scrolls up or down, the list just cuts off. I'm having a very difficult time maintaining the entire view's vertical positioning while adding these blurs with ZStack. The code below is the current implementation with an attempted progressive blur. Right now, it's close, but the list is acting exactly how I don't want it - anchoring to the top of the display (its natural position) and causes the toolbar to blur when scrolled under (I can't disable toolbar without losing my toolbarItems either). Any help is appreciated.
NavigationStack {
VStack {
ZStack {
List(filteredItems) { item in
NavigationLink(destination: ItemDetailView(item: item)) {
HStack(spacing: 15) {
Image(systemName: item.icon)
VStack(alignment: .leading) {
Text(item.name)
Text("")
}
.multilineTextAlignment(.leading)
}
.padding(.vertical, 5)
}
}
.scrollIndicators(.hidden)
.scrollContentBackground(.hidden)
VStack(spacing: 5) {
if #available(iOS 18.0, *) {
Image(systemName: "plus.square.on.square.fill")
.resizable()
.scaledToFit()
.frame(maxHeight: 50)
.symbolEffect(.bounce.up, options: .nonRepeating)
} else {
Image(systemName: "plus.square.on.square.fill")
.resizable()
.scaledToFit()
.frame(maxHeight: 50)
}
Text("Items")
.font(.largeTitle.bold())
Text("Create, View, and Manage Your Items")
.font(.system(size: 12).weight(.bold))
.multilineTextAlignment(.center)
ScrollView(.horizontal) {
HStack(spacing: 20) {
filterButton(icon: "car.fill", color: .red, label: "Auto")
filterButton(icon: "cart.fill", color: .purple, label: "Shopping")
filterButton(icon: "laptopcomputer", color: .blue, label: "Tech")
filterButton(icon: "airplane", color: .orange, label: "Travel")
filterButton(icon: "gamecontroller.fill", color: .green, label: "Entertainment")
}
.padding(.leading, 25)
}
.scrollBounceBehavior(.basedOnSize)
.scrollIndicators(.hidden)
Spacer()
}
.padding(.top)
VStack {
Rectangle()
.fill(.thinMaterial)
.frame(height: 300)
.mask {
VStack(spacing: 0) {
LinearGradient(colors: [Color.black.opacity(0),
Color.black.opacity(0.383),
Color.black.opacity(0.707),
Color.black.opacity(0.924),
Color.black],
startPoint: .bottom,
endPoint: .top)
.frame(height: 400)
Rectangle()
}
}
Spacer()
}
.ignoresSafeArea()
VStack {
Spacer()
Rectangle()
.fill(.thinMaterial)
.frame(height: 200)
.mask {
VStack(spacing: 0) {
LinearGradient(colors: [Color.black.opacity(0),
Color.black.opacity(0.383),
Color.black.opacity(0.707),
Color.black.opacity(0.924),
Color.black],
startPoint: .top,
endPoint: .bottom)
.frame(height: 100)
Rectangle()
}
}
}
.ignoresSafeArea()
VStack(spacing: 12) {
Spacer()
Button {
showingAddItemView.toggle()
} label: {
HStack {
Image(systemName: "plus.circle")
Spacer()
.frame(width: 7)
Text("New Item")
.padding(.trailing, 3)
}
#if os(visionOS)
.padding(.vertical)
#endif
}
.padding(10)
#if os(iOS)
.background {
Capsule()
}
#endif
NavigationLink("Continue") {
}
}
.padding()
Post
Replies
Boosts
Views
Activity
I have implemented basic Sign in with Apple functionality to my app. When the app is launched, the user will be presented with a Continue with Apple view, where they can authenticate. Once signed in, they will return to a view that reads "Hello, [User's Name]". However, I cannot seem to figure out why the email and name return nil after authentication. For example, when authentication is successful, the HelloView simply reads "Hello, " with no name. I have it setup so that the users name and email are saved to AppStorage variables, and then inserted into a Profile class with SwiftData.
import AuthenticationServices
import SwiftData
import SwiftUI
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
@Environment(\.modelContext) var modelContext
@AppStorage("email") var email: String = ""
@AppStorage("firstName") var firstName: String = ""
@AppStorage("lastName") var lastName: String = ""
@AppStorage("userID") var userID: String = ""
@Query var userProfile: [Profile]
private var isSignedIn: Bool {
!userID.isEmpty
}
var body: some View {
VStack {
if !isSignedIn {
SignInView()
} else {
HomeView()
}
}
}
}
struct SignInView: View {
@Environment(\.colorScheme) var colorScheme
@Environment(\.modelContext) var modelContext
@AppStorage("email") var email: String = ""
@AppStorage("firstName") var firstName: String = ""
@AppStorage("lastName") var lastName: String = ""
@AppStorage("userID") var userID: String = ""
@Query var userProfile: [Profile]
var body: some View {
NavigationStack {
Spacer()
SignInWithAppleButton(.continue) { request in
request.requestedScopes = [.email, .fullName]
} onCompletion: { result in
switch result {
case .success(let auth):
switch auth.credential {
case let credential as ASAuthorizationAppleIDCredential:
// User ID
let userID = credential.user
// User Info
let email = credential.email
print(email!)
let firstName = credential.fullName?.givenName
print(firstName!)
let lastName = credential.fullName?.familyName
print(lastName!)
self.email = email ?? ""
self.userID = userID
self.firstName = firstName ?? ""
self.lastName = lastName ?? ""
createProfile()
default:
break
}
case .failure(let error):
print("Error signing in with Apple: \(error.localizedDescription)")
}
}
.signInWithAppleButtonStyle(colorScheme == .dark ? .white : .black)
.frame(height: 50)
.padding()
.cornerRadius(12)
.navigationTitle("[App Name]")
}
}
func createProfile() {
let newProfile = Profile(firstName: firstName, lastName: lastName, email: email, userID: userID)
modelContext.insert(newProfile)
}
}
This is how I have my HomeView setup:
import SwiftData
import SwiftUI
struct HomeView: View {
@Environment(\.modelContext) var modelContext
@Query var user: [Profile]
var body: some View {
ForEach(user) { user in
Text("Hello, \(user.firstName)")
}
}
}
#Preview {
HomeView()
}
And here's the Profile class:
import Foundation
import SwiftData
@Model
class Profile {
var firstName: String
var lastName: String
var email: String
var userID: String
init(firstName: String, lastName: String, email: String, userID: String) {
self.firstName = firstName
self.lastName = lastName
self.email = email
self.userID = userID
}
}
I'm fairly new to Swift, so I'm unsure as to what's going wrong with my code and how to fix it.
After switching to Swift 6, the view I have with requestReview throws: "Cannot form key path to main actor-isolated property 'requestReview'"
As I understand it, this is potentially due to the changes made to @MainActor. However, I am unsure how to go about fixing this error.