When running a Mac Catalyst app that uses DocumentGroup, the app fails to display the document content. The document picker works as expected, but creating a new document or opening an existing one results in an empty window. This issue occurs regardless of whether “Optimize for Mac” or “Scale iPad” is selected.
Steps to Reproduce:
1. Download the sample project provided by Apple for building a document-based app in SwiftUI.
2. Delete the macOS version of the project.
3. Add a Mac Catalyst version of the app.
4. In the Mac Catalyst settings, select “Optimize for Mac” (the bug also appears if it is “Scale iPad”).
5. Run the project on macOS.
Expected Result:
The app should correctly display the content of the document when creating or opening it.
Actual Result:
The app opens an empty window when a new document is created or an existing one is opened.
Impact:
We have received multiple 1-star reviews, and our retention has dropped by two-thirds due to this issue.
Environment: Xcode 16.1; macOS 15.1 & 15.2 (on 15.0 it works fine)
Has anyone experienced the same issue? I filed multiple reports so far.
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Posts under SwiftUI tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
It only seems to happen in the real app I am working on and not within any of the test apps I make.
Its lasted a few Xcode versions. Don't know if this is widespread to the point of having a name?
On iOS you can create a new Lock Screen that contains a bunch of emoji, and they'll get put on the screen in a repeating pattern, like this:
When you have two or more emoji they're placed in alternating patterns, like this:
How do I write something like that? I need to handle up to three emoji, and I need the canvas as large as the device's screen, and it needs to be saved as an image. Thanks!
(I've already written an emojiToImage() extension on String, but it just plonks one massive emoji in the middle of an image, so I'm doing something wrong there.)
Ok… I'm baffled here… this is very strange.
Here is a SwiftUI app:
import SwiftUI
@main struct StepperDemoApp: App {
func onIncrement() {
print(#function)
}
func onDecrement() {
print(#function)
}
var body: some Scene {
WindowGroup {
Stepper {
Text("Stepper")
} onIncrement: {
self.onIncrement()
} onDecrement: {
self.onDecrement()
}
}
}
}
When I run in the app in macOS (Xcode 16.0 (16A242) and macOS 14.6.1 (23G93)), I see some weird behavior from these buttons. My experiment is tapping + + + - - -. Here is what I see printed:
onIncrement()
onIncrement()
onIncrement()
onIncrement()
onDecrement()
What I expected was:
onIncrement()
onIncrement()
onIncrement()
onDecrement()
onDecrement()
onDecrement()
Why is an extra onIncrement being called? And why is one onDecrement dropping on the floor?
Deploying the app to iPhone Simulator does not repro this behavior (I see the six "correct" logs from iPhone Simulator).
The following is my playground code. Any of the apple audio units show the plugin view, however anything else (i.e. kontakt, spitfire, etc.) does not. It does not error, just where the visual is expected is blank.
import AppKit
import PlaygroundSupport
import AudioToolbox
import AVFoundation
import CoreAudioKit
let manager = AVAudioUnitComponentManager.shared()
let description = AudioComponentDescription(componentType: kAudioUnitType_MusicDevice,
componentSubType: 0,
componentManufacturer: 0,
componentFlags: 0,
componentFlagsMask: 0)
var deviceComponents = manager.components(matching: description)
var names = deviceComponents.map{$0.name}
let pluginName: String = "AUSampler" // This works
//let pluginName: String = "Kontakt" // This does not
var plugin = deviceComponents.filter{$0.name.contains(pluginName)}.first!
print("Plugin name: \(plugin.name)")
var customViewController:NSViewController?
AVAudioUnit.instantiate(with: plugin.audioComponentDescription, options: []){avAudioUnit, error in
var ilip = avAudioUnit!.auAudioUnit.isLoadedInProcess
print("Loaded in process: \(ilip)")
guard error == nil else {
print("Error: \(error!.localizedDescription)")
return
}
print("AudioUnit successfully created.")
let audioUnit = avAudioUnit!.auAudioUnit
audioUnit.requestViewController{ vc in
if let viewCtrl = vc {
customViewController = vc
var b = vc?.view.bounds
PlaygroundPage.current.liveView = vc
print("Successfully added view controller.")
}else{
print("Failed to load controller.")
}
}
}
I am trying add Sign in with Apple but when I attempt to capability in my app nothing happens in the list
does apple not able to provide this feature yet in Vision OS or is there any bug or may be ami missing something which does not seems?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let message = self.parent.viewModel.messages[indexPath.row]
// var cell: RCBaseMessageCell? = tableView.dequeueReusableCell(withIdentifier: String( message.type.rawValue)) as? RCBaseMessageCell
var cell = tableView.dequeueReusableCell(withIdentifier: "cell")
if #available(iOS 16.0, *) {
cell?.contentConfiguration = UIHostingConfiguration {
Text("123").onTapGesture {
print("123")
}
}
return cell
}
on ios 18.1 onTapGesture sometimes will not callback ,but ios 17 16 is ok,how can i fix it
Keep ScrollView position when adding items on the top using onAppear / onScrollTargeVisibilityChange
Related Post: Keep ScrollView position when adding items on the top
I was trying to implement a message view using ScrollView + LazyVStack. This view requires pagination so I used onScrollTargeVisibilityChange modifier to detect if the first item appears on screen and a new page needs to be loaded. I learnt from the above post that scrollPositon modifier can help keep the scroll position. I tested the method mentioned in that post -- use a button to add new items to the top -- and it worked.
However, when use onScrollTargeVisibilityChange modifier to add items, the view automatically scrolls to the top and cause the following loop:
first item in the list appears on screen --> load and insert more items to the top --> scroll view scrolls to top --> first item appears --> load more data --> scroll to top --> first item ... --> more data... --> top ...
Until it generates the error ScrollTargetVisibilityChange tried to update multiple times per frame.
Here is the simplified code.
struct Item: Identifiable {
var id: UUID = .init()
var content: String
}
struct ScrollViewTest: View {
@State private var items: [Item] = (0...30).map {Item(content:"\($0)")}.reversed()
@State private var itemID: Item.ID?
@State private var page: Int = 0
var body: some View {
ScrollView {
LazyVStack {
ForEach(items) {item in
Text(item.content)
.frame(height: 30)
}
}
.scrollTargetLayout()
}
.scrollPosition(id: $itemID)
.defaultScrollAnchor(.bottom)
.onScrollTargetVisibilityChange(idType: Item.ID.self) { onScreenItemIDs in
if onScreenItemIDs.first == items.first?.id {
page += 1
let newItems = (page*30+1 ... (page+1)*30).map {Item(content:"\($0)")}
items.insert(contentsOf: newItems.reversed(), at: 0)
}
}
.toolbar {
Button("Add") {
page += 1
let newItems = (page*30+1 ... (page+1)*30).map {Item(content:"\($0)")}
items.insert(contentsOf: newItems.reversed(), at: 0)
}
}
}
}
I want to load data while scrolling without the need of pressing any buttons. How can I solve this problem?
Is there a way to implement controls for background audio using ActivityKit like in the Apple Music application? I didn't found anything in your documentation about handling actions like this except deep links, but they're not suitable for this use case
Getting this error:
'Task' is only available in macOS 10.15 or newerSourceKit
LoggerForPreviews.swift(130, 9): Add 'if #available' version check
LoggerForPreviews.swift(129, 24): Add @available attribute to enclosing static method
LoggerForPreviews.swift(5, 20): Add @available attribute to enclosing actor
Does it have something to do with developing in VSCode?
import Foundation
import SwiftUI
// Logger: A concise, globally accessible logging utility for SwiftUI previews
public final actor PreviewLogger: Sendable {
// LogLevel: Defines severity levels for logging
public enum LogLevel: Int, Sendable, CaseIterable {
// Define cases based on LOG_LEVEL_MAP
case trace, debug, verbose, info, notice, warning, error, critical, fatal
// Computed property to get order based on case declaration
private var order: Int {
switch self {
case .trace: return 0
case .debug: return 1
case .verbose: return 2
case .info: return 3
case .notice: return 4
case .warning: return 5
case .error: return 6
case .critical: return 7
case .fatal: return 8
}
}
public var description: String {
// Use capitalized raw value for description
return String(describing: self).uppercased()
}
// Static function to compare log levels
static func >= (lhs: LogLevel, rhs: LogLevel) -> Bool {
return lhs.order >= rhs.order
}
}
// Shared instance for global access
public static let shared = PreviewLogger()
// Current log level
public var logLevelThreshold: LogLevel = .info
private init() {}
// Configure the logger's log level
public func configure(logLevelThreshold: LogLevel) {
self.logLevelThreshold = logLevelThreshold
}
// Helper function to center text within a given width
private func centered(_ text: String, in separator: String) -> String {
let totalLength = separator.count
let textLength = text.count
if textLength >= totalLength {
return text
}
let padding = (totalLength - textLength) / 2
let padString = String(repeating: " ", count: padding)
return padString + text
}
// Main logging function
public func log(
_ message: String,
level: LogLevel = .info,
file: String = #file,
function: String = #function,
line: Int = #line,
callerFile: String? = nil,
callerFunction: String? = nil,
callerLine: Int? = nil
) {
#if DEBUG
guard ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" else {
return
}
guard level >= logLevelThreshold else { return }
let fileName = (file as NSString).lastPathComponent
let cleanFunction = function.replacingOccurrences(of: "(_:file:function:line:)", with: "")
let levelIcon: String
switch level {
case .trace: levelIcon = "🔍"
case .debug: levelIcon = "🛠️"
case .verbose: levelIcon = "📝"
case .info: levelIcon = "ℹ️"
case .notice: levelIcon = "📢"
case .warning: levelIcon = "⚠️"
case .error: levelIcon = "❌"
case .critical: levelIcon = "🚨"
case .fatal: levelIcon = "💀"
}
let header = "[\(levelIcon) \(level.description)]"
let separator =
"· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·"
let finalSeparator =
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
let centeredHeader = centered(header, in: separator)
var output = """
\n\(separator)
\(centeredHeader)
"""
let locationInfo = "📍 \(fileName):\(line) ➜ \(cleanFunction)"
let centeredLocation = centered(locationInfo, in: separator)
output += "\n\(centeredLocation)"
if let callerFile = callerFile,
let callerLine = callerLine
{
let callerFileName = (callerFile as NSString).lastPathComponent
let callerInfo = "📱 Called from: \(callerFileName):\(callerLine)"
let centeredCallerInfo = centered(callerInfo, in: separator)
output += "\n\(centeredCallerInfo)"
}
output += """
\n\(separator)\n\(message)\n\(finalSeparator)
"""
print(output)
#endif
}
// Static Methods
public static func configure(logLevelThreshold: LogLevel) {
Task {
await shared.configure(logLevelThreshold: logLevelThreshold)
}
}
public static func log(
_ message: String,
level: LogLevel = .info,
file: String = #file,
function: String = #function,
line: Int = #line,
callerFile: String? = nil,
callerFunction: String? = nil,
callerLine: Int? = nil
) {
Task {
await shared.log(
message,
level: level,
file: file,
function: function,
line: line,
callerFile: callerFile,
callerFunction: callerFunction,
callerLine: callerLine
)
}
}
}
Hey everyone,
TL;DR
How do I enable a draggable TableView to drop Audio Files into Apple Music / Rekordbox / Finder?
Intro / skip me
I've been dabbling into Swift / SwiftUI for a few weeks now, after roughly a decade of web development.
So far I've been able to piece together many things, but this time I'm stuck for hours with no success using Forums / ChatGPT / Perplexity / Trial and Error.
The struggle
Sometimes the target doesn't accept the dropping at all
sometimes the file data is failed to be read
when the drop succeeds, then only as a stream in apple music
My lack of understanding / where exactly I'm stuck
I think the right way is to use UTType.fileUrl but this is not accepted by other applications.
I don't understand low-level aspects well enough to do things right.
The code
I'm just going to dump everything here, it includes failed / commented out attempts and might give you an Idea of what I'm trying to achieve.
//
// Tracks.swift
// Tuna Family
//
// Created by Jan Wirth on 12/12/24.
//
import SwiftySandboxFileAccess
import Files
import SwiftUI
import TunaApi
struct LegacyTracks: View {
@State var tracks: TunaApi.LoadTracksQuery.Data?
func fetchData() {
print("fetching data")
Network.shared.apollo.fetch(query: TunaApi.LoadTracksQuery()) { result in
switch result {
case .success(let graphQLResult):
self.tracks = graphQLResult.data
case .failure(let error):
print("Failure! Error: \(error)")
}
}
}
@State private var selection = Set<String>()
var body: some View {
Text("Tracks").onAppear{
fetchData()
}
if let tracks = tracks?.track {
Table(of: LoadTracksQuery.Data.Track.self, selection: $selection) {
TableColumn("Title", value: \.title)
} rows : {
ForEach(tracks) { track in
TableRow(track)
.draggable(track)
// .draggable((try? File(path: track.dropped_source?.path ?? "").url) ?? test_audio.url) // This causes a compile-time error
// .draggable(test_audio.url)
// .draggable(DraggableTrack(url: test_audio.url))
// .itemProvider {
// let provider = NSItemProvider()
// if let path = self.dropped_source?.path {
// if let f = try? File(path: path) {
// print("Transferring", f.url)
//
//
// }
// }
//
// provider.register(track)
// return provider
// } // This does not
}
}
.contextMenu(forSelectionType: String.self) { items in
// ...
Button("yoooo") {}
} primaryAction: { items in
print(items)
// This is executed when the row is double clicked
}
} else {
Text("Loading")
}
// }
}
}
//extension Files.File: Transferable {
// public static var transferRepresentation: some TransferRepresentation {
// FileRepresentation(exportedContentType: .audio) { url in
// SentTransferredFile( self.)
// }
// }
//}
struct DraggableTrack: Transferable {
var url: URL
public static var transferRepresentation: some TransferRepresentation {
FileRepresentation (exportedContentType: .fileURL) { item in
SentTransferredFile(test_audio.url, allowAccessingOriginalFile: true)
}
// FileRepresentation(contentType: .init(filenameExtension: "m4a")) {
// print("file", $0)
// print("Transferring fallback", test_audio.url)
// return SentTransferredFile(test_audio.url, allowAccessingOriginalFile: true)
// }
// importing: { received in
// // let copy = try Self.(source: received.file)
// return Self.init(url: received.file)
// }
// ProxyRepresentation(exporting: \.url.absoluteString)
}
}
extension LoadTracksQuery.Data.Track: @retroactive Identifiable {
}
import UniformTypeIdentifiers
extension LoadTracksQuery.Data.Track: @retroactive Transferable {
// static func getKind() -> UTType {
// var kind: UTType = UTType.item
// if let path = self.dropped_source?.path {
// if let f = try? File(path: path) {
// print("Transferring", f.url)
// if (f.extension == "m4a") {
// kind = UTType.mpeg4Audio
// }
// if (f.extension == "mp3") {
// kind = UTType.mp3
// }
// if (f.extension == "flac") {
// kind = UTType.flac
// }
// if (f.extension == "wav") {
// kind = UTType.wav
// }
//
// }
// }
// return kind
// }
public static var transferRepresentation: some TransferRepresentation {
ProxyRepresentation {
$0.dropped_source?.path ?? ""
}
FileRepresentation(exportedContentType: .fileURL) { <#Transferable#> in
SentTransferredFile(<#T##file: URL##URL#>, allowAccessingOriginalFile: <#T##Bool#>)
}
// FileRepresentation(contentType: .fileURL) {
// print("file", $0)
// if let path = $0.dropped_source?.path {
// if let f = try? File(path: path) {
// print("Transferring", f.url)
// return SentTransferredFile(f.url, allowAccessingOriginalFile: true)
// }
// }
// print("Transferring fallback", test_audio.url)
// return SentTransferredFile(test_audio.url, allowAccessingOriginalFile: true)
// }
// importing: { received in
// // let copy = try Self.(source: received.file)
// return Self.init(_fieldData: received.file)
// }
// ProxyRepresentation(exporting: \.title)
}
}
On an iPad or iPhone running iPadOS / iOS 18.2 (built with Xcode 16.2), run the WritingApp sample code from https://developer.apple.com/documentation/SwiftUI/Building-a-document-based-app-with-SwiftUI from WWDC24
Then add the following struct to the project:
struct NavigationBarToolbar: ToolbarContent {
var body: some ToolbarContent {
ToolbarItem(placement: .secondaryAction) {
Button("Button 1", systemImage: "1.circle") { }
}
ToolbarItem(placement: .secondaryAction) {
Button("Button 2", systemImage: "2.circle") { }
}
ToolbarItem(placement: .secondaryAction) {
Button("Button 3", systemImage: "3.circle") { }
}
ToolbarItem(placement: .secondaryAction) {
Button("Button 4", systemImage: "4.circle") { }
}
ToolbarItem(placement: .secondaryAction) {
Button("Button 5", systemImage: "5.circle") { }
}
}
}
Comment out the original toolbar in the sample project and replace with:
.toolbar(content: NavigationBarToolbar.init)
Run the project and open or create a document
Click on the TitleMenu and choose Rename, in order to rename the file
Type in a new name and press Enter.
Notice how the items of the toolbar disappear
——
This issue has been submitted as feedback with number FB16100225
This issue is linked to the following feedbacks:
FB14855728
FB14855668
FB14849205
FB12343963
FB15164292
Hi! I was trying to add an animation to my SwiftUI view with UIKit, but after the animation runs there's a delay before the view will accept touch interactions. I thought it was because of the frame size of the view controller, but even after fixing that I still get the delay. Could anyone point me to where I might be going wrong, or if maybe using a UIKit modifier for the animation just doesn't work?
Any help would be greatly appreciated!
UIView:
class BounceView: UIView {
required init() {
super.init(frame: .zero)
}
func bounceAnimation() {
guard let piece = self.subviews.first else { return }
UIView.animate(withDuration: 0.7, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0) {
piece.frame.origin.x += 10
}
}
func bounceBack() {
guard let piece = self.subviews.first else { return }
UIView.animate(withDuration: 0.7, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0) {
piece.frame.origin.x -= 10
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
UIView controller:
class BounceViewController: UIViewController {
init(controller: UIViewController) {
super.init(nibName: nil, bundle: nil)
view = BounceView()
addChild(controller)
controller.view.translatesAutoresizingMaskIntoConstraints = false
controller.view.backgroundColor = .clear
view.addSubview(controller.view)
controller.didMove(toParent: self)
}
// adjusts view to match bounds of child
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let subviewFrame = self.view.subviews.first?.bounds ?? .zero
view.frame = subviewFrame
print(subviewFrame)
self.updateViewConstraints()
}
func update(animated: Bool) {
let bounceView = view as? BounceView
if animated {
bounceView?.bounceAnimation()
} else {
bounceView?.bounceBack()
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
SwiftUI wrapper:
struct BounceUIViewController: UIViewControllerRepresentable {
private var controller: UIViewController
@Binding var animated: Bool
init(controller: UIViewController, animated: Binding<Bool>) {
self.controller = controller
self._animated = animated
}
func makeUIViewController(context: Context) -> BounceViewController {
BounceViewController(controller: controller)
}
func updateUIViewController(_ uiViewController: BounceViewController, context: Context) {
uiViewController.update(animated: animated)
}
}
View extension:
extension View {
func bounce(animated: Binding<Bool>) -> some View {
modifier(Bounce(animated: animated))
}
}
struct Bounce: ViewModifier {
@Binding var animated: Bool
init(animated: Binding<Bool>) {
self._animated = animated
}
func body(content: Content) -> some View {
BounceUIViewController(controller: content.uiViewController, animated: $animated)
}
}
It looks like Xcode 16 has changed this behavior so I'm not sure if this is a bug or not.
When a SwiftUI Button wraps a UIButton, the button doesn't work on iOS 18.0+
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Button(action: {
print("Not called on iOS 18")
}) {
WrapperButton()
.frame(width: 200, height: 50)
}
}
}
}
struct WrapperButton: UIViewRepresentable {
func makeUIView(context: Context) -> some UIView {
let button = UIButton(type: .system)
button.setTitle("OK", for: .normal)
return button
}
func updateUIView(_ uiView: UIViewType, context: Context) {}
}
This occurs with the app build with Xcode 16 and running on iOS 18
but it was worked with Xcode 15 builds and running on iOS 18
The WatchOS Control Center has an Edit/Done button at the bottom, and in its edit mode, elements can be moved around and added/removed.
Yet, the SwiftUI List doesn't have an edit mode on WatchOS.
My question is: is the edit functionality in Control Center a custom thing, or is that present in some SwiftUI component that I've missed?
I'm making an app using SwiftUI and trying to use the TextEditor view. However when I run it, and I try entering text into the TextEditor, the characters don't appear, they do however appear in the terminal that i used to run the app. The same problem exists with the TextField view.
I usually run it using swift run but have also tried swift build and running the produced executable as well as using release mode.
Minimal example:
import SwiftUI
@main
struct Example: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State var text: String = ""
var body: some View {
TextEditor(text: $text)
}
}
I've encountered a weird issue with the new Map for iOS 17. In my list, which includes a MapView among other elements, I've observed that with the new initializer, the top and bottom bars are persistently displayed. They don't hide and only appear when scrolling, as they should. This problem doesn't occur with the old, now-deprecated initializer. To illustrate this, I have two screenshots: one with the map enabled and the other with the map disabled, demonstrating the issue.
Here is also my new Map code:
struct MapListRowView: View {
@Binding internal var location: LocationModel
@State internal var user: Bool = true
private var position: CLLocationCoordinate2D { .init(latitude: location.latitude, longitude: location.longitude) }
private var isPad: Bool { UIDevice.current.userInterfaceIdiom == .pad ? true : false }
var body: some View {
Map(bounds: .init(minimumDistance: 1250)) {
if user { UserAnnotation() }
Annotation("", coordinate: position) {
ZStack {
Circle().fill().foregroundColor(.white).padding(1)
Image(systemName: "mappin.circle.fill")
.resizable()
.foregroundColor(.indigo)
}.frame(width: 20, height: 20).opacity(user ? .zero : 1.0)
}
}
.frame(height: isPad ? 200 : 100)
.cornerRadius(8)
.listRowInsets(.init(top: -5, leading: .zero, bottom: -5, trailing: .zero))
.padding(.vertical, 5)
.disabled(true)
}
}
Dear Experts,
I have been looking at thr SimpleWatchConnectivity sample code:
https://developer.apple.com/documentation/watchconnectivity/transferring-data-with-watch-connectivity
There are a couple of things in there that look out of date. Firstly, it uses a WKApplicationDelegate to receive the background tasks. I believe this can probably be entirely removed, and replaced with .backgroundTask(.watchConnectivity) { ... } on the App. Is that true? What do I need something inside the { ... } there?
Secondly, it is using NSNotificationCenter to send received data from the WCSessionDelegate to the SwiftUI view hierarchy. Is there a better way to do that? I have spent a while trying to work out how a WCSessionDelegate class can connect to a binding to a SwiftUI @State property, and cause the UI to update in response to received data, but I haven't made it work.
Are there any newer examples of how to do this? I'm currently only trying to send some simple applicationContext state from the phone to the watch and have some views update to show the latest values.
Thanks, Phil.
Hi,
I am trying to read in which section in a list the user is currently located and want to scroll him to a specific section. Therefore I would like to use the new .scrollPosition modifier. Best would be the ability to implement the same snapping effect from ScrollView.
So I used this snippet:
struct Item: Identifiable{
var id: Int
static func getMany() -> [Item] {
var items = [Item]()
for i in 0..<100 {
items.append(Item(id: i))
}
return items
}
}
struct ContentView: View {
@State var items = Item.getMany()
@State var scrolledID: Item.ID?
var body: some View {
NavigationStack {
List {
ForEach(items) { item in
ItemView(item: item)
}
}
.scrollTargetLayout()
.scrollPosition(id: $scrolledID)
.navigationTitle("Hello, \(scrolledID ?? 0)")
}
}
}
struct ItemView: View {
var item: Item
var body: some View {
Text("Hello world, \(item)")
}
}
Doesn't work.
So I tried to place the modifiers in different places in the code to attack several different parts of the list as the "scrollTargetLayout" - but this doesn't change anything here.
Isn't the List View just the Form inside a ScrollView?! This doesn't work either. If I place the Form OR List inside a ScrollView, the contents of the list aren't displayed anymore. This seems logical, because the list is a LazyVStack rendering without a height, as it doesn't know its final height.
Can we fix this somehow?
I made a ImagePicker which worked pretty well. But when app get bigger it stops. Does not react to change isPresented value. As far I know I changed nothing around this part of an App. Also same thing happened in different place, another kind of picker.
print ("HELL'o") never prints. Silence.
struct ImagePicker: View {
@Binding var imageSource: ImageSource
@State var showFileImporter: Bool = false
@EnvironmentObject var manager: Manager
var body: some View {
VStack {
....
Button(action: {
print("before", showFileImporter)
showFileImporter = true
print("after", showFileImporter)
},
label: { Text("open Image") })
.buttonStyle(.borderless)
.controlSize(.mini)
}.fileImporter(isPresented: $showFileImporter,
allowedContentTypes: [.png, .jpeg, .tiff],
onCompletion: { result in
print ("HELL'o") // Never prints
switch result {
case let .success(url):
guard let _ = try? Data(contentsOf: url) else { return }
....
case let .failure(error):
print(error)
}
})
}
}
Does anybody have an idea what happened?
I suspect some settings in completely different palce or bug or computer does not like me.