You can use the isActive parameter of NavigationLink to bind a property and trigger the push changing the property value to true:
struct ContentView: View {
@State private var isActive = false
var body: some View {
NavigationView {
VStack {
Button("Present") {
isActive = true
}
NavigationLink(destination: Color.red, isActive: $isActive) { }
}
}
}
}
I'm using a Button action to change the value but you can do it in the error handling for example.
Post
Replies
Boosts
Views
Activity
You can also use the @UIApplicationDelegateAdaptor property wrapper if you prefer the UIKit way.
@main
struct SampleApp: App {
@UIApplicationDelegateAdaptor var delegate: AppDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
print(#function)
return true
}
}
The problem is the fact that in your code you end up with repeated identifiers and I believe that LazyVStack requires the ids to be unique. I managed to make it work using a UUID as an identifier:
struct ContentView: View {
var body: some View {
ScrollView {
LazyVStack{
ForEach(0...2, id: \.self) { section in
Section {
ForEach(0..<2) { item in
Text("Section: \(section), Item: \(item)")
.id(UUID())
}
}
}
}
}
}
}
When a sample code is appearing in the video there is a button available in the upper left corner to copy the code to clipboard.
You can achieve this using the .fullScreenCover modifier as in the following example:
import SwiftUI
struct ContentView: View {
@State private var isPresented = false
var body: some View {
Button("Present") {
isPresented.toggle()
}
.fullScreenCover(isPresented: $isPresented) {
ModalView()
}
}
}
struct ModalView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
Button("Dismiss") {
presentationMode.wrappedValue.dismiss()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red)
.foregroundColor(Color.white)
.edgesIgnoringSafeArea(.all)
}
}
I've noticed this too and I believe it’s because Label is made to be used in specific places, like in a tab item.
You can get the position by using GeometryReader to read the scrollView content frame, pass the value using PreferenceKey and observe it:
struct ContentView: View {
var body: some View {
ScrollView {
ZStack {
LazyVStack {
ForEach(0...100, id: \.self) { index in
Text("Row \(index)")
}
}
GeometryReader { proxy in
let offset = proxy.frame(in: .named("scroll")).minY
Color.clear.preference(key: ScrollViewOffsetPreferenceKey.self, value: offset)
}
}
}
.coordinateSpace(name: "scroll")
.onPreferenceChange(ScrollViewOffsetPreferenceKey.self) { value in
print(value)
}
}
}
The .frame(in: .named("scroll")) is required to get the frame relative to the ScrollView and obtain a 0 offset when at the top, without the height of the safe area. If you try using .frame(in: .global) you will get a non-zero value when the scroll view is at the top (20 or 44, depends on the device).
ScrollViewReader actually provides a ScrollViewProxy with a function scrollTo(_ id:, anchor:) that you can use to scroll to the position of a View related to a given id:
struct ContentView: View {
@State private var position = 0
var body: some View {
VStack {
HStack {
Button("Top") { position = 0 }
Button("Middle") { position = 500 }
Button("Bottom") { position = 1000 }
}
ScrollView {
ScrollViewReader { proxy in
LazyVStack {
ForEach(0...1000, id: \.self) { index in
Text("Row \(index)")
}
}
.onChange(of: position) { value in
withAnimation {
proxy.scrollTo(value, anchor: .center)
}
}
}
}
}
}
}