The Build for Previews builds all my targets including the test targets. Is there a way to configure the relevant targets? I do not see an option in the schema editor, and disabling Find Implicit Dependencies has no effect either.
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Post
Replies
Boosts
Views
Activity
Is there a way to use NSPathControl or something equivalent in SwiftUI on Mac?
I'm trying to understand how to use .focusedSceneValue on macOS.
Given a very basic app which displays Thing-s, and have a menu for editing the things. When I run the app, nothing is selected at first and the menu is disabled. When selecting e.g. the Thing Alfa in the sidebar. the menu becomes enabled as expected. When I select another Thing, the menu is also updated as expected.
However, if I switch focus to another application, e.g. the Finder, and then switch back to my app, the menu is now disabled, even though a Thing is selected in the sidebar.
If I open another window within my app and select e.g. Gamma in the sidebar of that window the menu is updated as expected. But, when switching back to the first window the menu is disabled, although a Thing is selected.
What am I doing wrong? Xcode 13.1 and macOS Monterey 12.0.1.
See the code below (the code can also be found here: https://github.com/danwaltin/FocusedSceneValueTest)
struct Thing: Identifiable, Hashable {
let id: Int
let name: String
static func things() -> [Thing] {
return [
Thing(id: 1, name: "Alfa"),
Thing(id: 2, name: "Beta"),
Thing(id: 3, name: "Gamma")
]
}
}
@main
struct FocusedSceneValueTestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.commands {
ThingCommands()
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
List(Thing.things()) { thing in
NavigationLink(
destination: DetailView(thing: thing),
label: {Text(thing.name)}
)
}
Text("Nothing selected")
}
}
}
struct DetailView: View {
let thing: Thing
var body: some View {
Text(thing.name)
.focusedSceneValue(\.selectedThing, thing)
.navigationTitle(thing.name)
}
}
struct ThingCommands: Commands {
@FocusedValue(\.selectedThing) private var thing
var body: some Commands {
CommandMenu("Things") {
Button("Edit \(thingName)") {
print("*** Editing \(thingName)")
}
.disabled(thing == nil)
.keyboardShortcut("e")
}
}
private var thingName: String {
guard let thing = thing else {
return ""
}
return thing.name
}
}
struct SelectedThingKey : FocusedValueKey {
typealias Value = Thing
}
extension FocusedValues {
var selectedThing: Thing? {
get {self[SelectedThingKey.self]}
set {self[SelectedThingKey.self] = newValue}
}
}
So I am banging my head, I realized my stand along Watch App had a STUPID long name of "App Name - WatchKit App" so I went into my Target and changed the Display Name to "App Name" removing WatchKit App. Well now my app won't validate when uploading to the Appstore. I get the message - Invalid Info.plist key. The key
WKExtensionDelegateClassName in bundle App Name.app/Watch/App Name WatchKit App.app is invalid.
My Info.plist has the value of
<key>WKExtensionDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).ExtensionDelegate</string>
I have confirmed that I have @WKExtensionDelegateAdaptor(ExtensionDelegate.self) var delegate in my @main for the SwiftUI App. And when I print a few values in my app launch I get the following confirmations:
Super Init - ExtensionDelegate
Contentview
applicationDidFinishLaunching for watchOS
Super Init - ExtensionDelegate
Optional(My_App_Extension.Setup)
Optional(My_App_Extension.Statistics)
Optional(My_App_Extension.Other)
applicationDidBecomeActive for watchOS
update complication
I create three classes at launch and print this in the log with print(ExtensionDelegate.shared.Setup as Any) , etc. The other lines are just confirming where I am at app startup.
This is a WatchOS8 application and I am running Xcode version Version 13.1 (13A1030d).
Hi,
I'm currently developing a SwiftUI based app with Core Data and CloudKit sync with the NSPersistentCloudKitContainer.
I found different solutions how to toggle CloudKit sync of the Core Data during runtime. The basic idea of these solutions is the following.
instantiate a new NSPersistentCloudKitContainer
set storeDescription.cloudKitContainerOptions = nil
load persistence store
Some solutions recommend to restart the app manually to avoid exactly my problem.
Issues
So far so good. How can I distribute the new viewContext through my app during runtime. In the main App I distributed the viewContext during startup via @Environment(\.managedObjectContext) and it seems not be updated automatically after a reinitialization of NSPersistentCloudKitContainer.
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistence.container.viewContext)
}
}
After deactivating the CloudKit sync I receive the following error when I try to add a new entity.
[error] warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'TestEntity' so +entity is unable to disambiguate.
Any ideas?
Regards
Sven
I'm working on an app targeting iOS 15+ using SwiftUI.
The app has several Views that load data from an API in their onAppear() method. While the loading operation is in progress, these views show a loading overlay via .fullScreenCover().
While most of the time this works as expected, I've discovered that if the API operation completes before the overlay's .onAppear() has fired, the overlay gets stuck on screen, i.e. does not dismiss. This bug occurs both in the simulator and on device.
This is a simplified version of my implementation:
struct MyDataView: View {
@EnvironmentObject var store:Store
var Content: some View {
// ...
}
@ViewBuilder
var body: some View {
let showLoadingOverlay = Binding(
get: {
store.state.loading
},
set: { _ in }
)
Content
.onAppear {
store.dispatch(LoadData)
}
.fullScreenCover(isPresented: showLoadingOverlay) {
LoadingOverlay()
}
}
}
Log messages tell me that my store is updating correctly, i.e. the booleans all operate as expected. Adding log output to the binding's getter always prints the correct value. Adding a breakpoint to the binding's getter makes the problem disappear.
I've found that the chronology of events that lead to this bug is:
MyDataView.onAppear()
LoadData
Binding: true
Overlay starts animating in
LoadData finishes
Binding: false
Overlay fires it's onAppear
I.e. whenever loading finishes before the fullScreenCover's onAppear is fired, the overlay get's stuck on screen. As long as loading takes at least as long as it takes the overlay to appear, the bug does not occur.
It appears to be a race condition between the .fullScreenCover appearing and the binding changing to false.
I've found that the bug can be avoided if loading is triggered in the overlay's .onAppear(). However, I would like to avoid this workaround because the overlay is not supposed to carry out data loading tasks.
Hi,
I want to activate/deactivate the CloudKit Sync during App runtime in a user settings view. Basically this works fine. Every time I toggle between the NSPersistentContainer and the NSPersistentCloudKitContainer, I increase the persistence.persistenceContainerReloaded attribute and the whole view hierarchy will be reloaded. Thus all changes are passed through the whole app.
During the reload phase I have to load a new persistence store by container.loadPersistentStores(...). Unfortunately, I cannot remove the old persistence store before loading the new one. The app crashes immediately, because the store and viewContext is still in use. Therefore, I just create a new one and trigger the reload. Afterwards every view is using the new viewContext. But somewhere in the background there is still the old persistence store with CloudKit Sync active and pushes every local change to the cloud. Changes on the cloud from other devices are not received anymore.
Does someone has any idea, how to correctly unload a PersistentStore (replace NSPersistentCloudKitContainer by NSPersistentContainer) in a SwiftUI based app?
@main
struct TargetShooterApp: App {
@StateObject var persistence: Persistence = Persistence.shared
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistence.container.viewContext)
.id(persistence.persistenceContainerReloaded)
}
}
}
Hey,
I know you can write @AppStorage("username") var username: String = "Anonymous" to access a Value, stored In the User Defaults, and you can also overwrite him by changing the value of username.
I was wondering if there is any workaround to use @AppStorage with Arrays.
Because I don't find anything, but I have a lot of situations where I would use it.
Thanks!
Max
How to get upload progress when using:
let (data, urlResponse) = try await urlSession.upload(
for: urlRequest,
from: bodyData,
delegate: nil // Something I need here maybe?
)
I have tried using:
func urlSession(
_ session: URLSession,
task: URLSessionTask,
didSendBodyData bytesSent: Int64,
totalBytesSent: Int64,
totalBytesExpectedToSend: Int64) {
print("fractionCompleted : \(Float(totalBytesSent) / Float(totalBytesExpectedToSend))")
}
Within the same class but it never fires.
I specifically want the async / await capability on the upload.
I couldn't get the session.uploadTask to work with the await prefix.
Don’t over-engineering! No suggested architecture for SwiftUI, just MVC without the C.
On SwiftUI you get extra (or wrong) work and complexity for no benefits. Don’t fight the system.
Are there good examples of integrating SwiftUI, Coredata and Cloudkit working nicely together?
I have a simple SwiftUI application with CoreData and two views. One view displays all "Place" objects. You can create new places and you can show the details for the place.
Inside the second view you can add "PlaceItem"s to a place.
The problem is that, once a new "PlaceItem" is added to the viewContext, the @NSFetchRequest seems to forget about its additional predicates, which I set in onAppear. Then every place item is shown inside the details view. Once I update the predicate manually (the refresh button), only the items from the selected place are visible again.
Any idea how this can be fixed? Here's the code for my two views:
struct PlaceView: View {
@FetchRequest(sortDescriptors: []) private var places: FetchedResults<Place>
@Environment(\.managedObjectContext) private var viewContext
var body: some View {
NavigationView {
List(places) { place in
NavigationLink {
PlaceItemsView(place: place)
} label: {
Text(place.name ?? "")
}
}
}
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
let place = Place(context: viewContext)
place.name = NSUUID().uuidString
try! viewContext.save()
} label: {
Label("Add", systemImage: "plus")
}
}
}
.navigationTitle("Places")
}
}
struct PlaceItemsView: View {
@ObservedObject var place: Place
@FetchRequest(sortDescriptors: []) private var items: FetchedResults<PlaceItem>
@Environment(\.managedObjectContext) private var viewContext
func updatePredicate() {
items.nsPredicate = NSPredicate(format: "place == %@", place)
}
var body: some View {
NavigationView {
List(items) { item in
Text(item.name ?? "");
}
}
.onAppear(perform: updatePredicate)
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
let item = PlaceItem(context: viewContext)
item.place = place
item.name = NSUUID().uuidString
try! viewContext.save()
} label: {
Label("Add", systemImage: "plus")
}
}
ToolbarItem(placement: .navigationBarLeading) {
Button(action: updatePredicate) {
Label("Refresh", systemImage: "arrow.clockwise")
}
}
}
.navigationTitle(place.name ?? "")
}
}
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
var body: some View {
NavigationView {
PlaceView()
}
}
}
Thanks!
Hi,
I thought this should be quite easy and maybe I only have tomatoes on my eyes, but I cannot find out how to call an action when the user clicks the red button or use CMD-W to close the Preferences window (= Settings Scene).
I use Core Data. In the Preferences, many data structures, which define my system, are changed.
I learned, that you shouldn't save too often to avoid performance problems, so now I want to save the Core Data context when the user closes the Preferences window.
I tried .onDisappear, onChange of focus etc. but this didn't work.
How can I define an action?
Any hints are welcome :-)
Hi,
I've implemented the FamilyActivityPicker and I also noticed that it is the same picker that we get when we go to Setttings > Screen Time > App Limits > Add Limit.
When you tap on a given row, it will present all apps that are in that category. If you press the check mark on Category then on the Category row will be updated by showing the checkmark as selected and a "All" text to the right side, and on the app rows from that category the check marks will also be marked as selected.
This behavior is not consistent when I implement the FamilyActivityPicker. If I go through the same process the app rows won't be shown as selected.
Any suggestions on how to make this work? I'm attaching screen shots to illustrate my point.
Settings App
My FamilyActivityPicker Implementation
Is there a way to optimize a List in SwiftUI?
There is a problem with selection not working properly when the List has many rows.
If you scroll to multi-select and up, some rows in the middle are not selected.
I have an issue where selecting an unselected row deselects nearby rows.
Is there any way for selection to work reliably even for a List of many rows?
I would like to find a solution that is stable even when multiple lines are selected, like mail and note, which are the default apps in ios.
ps. I am using CoreData.
@State var selectedItem = Set<MyEntity>()
List(selection: $selectItem){
ForEach(items, id: \.self){ item in
ContactsRow(contactsData: item)
}
}
.environment(\.editMode, $editMode)
In the recent WWDC 2022, FreeForm app was introduced and in that app in the tool picker there was a Fill Tool.
I want to put that fill tool (or any similar filling tool) in my xcode app that I am building. But when I use pencilkit PKToolPicker, there is not Fill Tool.
So how to get this fill tool in my app.
Any leads would be helpful. Thanks.
Overview
I am bit confused regarding drag and drop on SwiftUI
I think there are 2 approaches but I am stuck with both approaches
WWDC22
When using the new draggable, dropDestination, Transferable API, only single items are draggable. Multiple items in a list are not draggable. I have filed a feedback FB10128110
WWDC21
I have faced a couple of issues for drag and drop introduced in WWDC21 (onDrag, onDrop, itemIdentifier), the Feedback ids are FB9854301, FB9854569, FB9855245, FB9855532, FB9855567, FB9855575. It contains sample projects, would really appreciate if someone could have a look it.
Note: All feedbacks include a sample project with detail steps and some even have screenshots and videos
Questions:
If my approach is wrong or if I am missing something?
Unfortunately I didn't manage to get a SwiftUI lab session (got cancelled), so please help me with these issues.
After updating to NavigationStack with nested navigation links (with navigation links in a navigation destination), I see a lot of warnings in Xcode 14 beta:
Update NavigationAuthority bound path tried to update multiple times per frame.
Update NavigationAuthority possible destinations tried to update multiple times per frame.
The app often freezes when navigated with a NavigationLink. Do others see these problems?
The Problem
In our brand new SwiftUI project (Multiplatform app for iPhone, iPad and Mac) we are using a ScrollView with both .horizontal and .vertical axes enabled. In the end it all looks like a spreadsheet.
Inside of ScrollView we are using LazyVStack with pinnedViews: [.sectionHeaders, .sectionFooters]. All Footer, Header and the content cells are wrapped into a LazyHStack each. The lazy stacks are needed due to performance reasones when rows and columns are growing.
And this exactly seems to be the problem. ScrollView produces a real layout mess when scrolling in both axes at the same time.
Tested Remedies
I tried several workarounds with no success.
We built our own lazy loading horizontal stack view which shows only the cells whose indexes are in the visible frame of the scrollview, and which sets dynamic calculated leading and trailing padding.
I tried the Introspect for SwiftUI packacke to set usesPredominantAxisScrolling for macOS and isDirectionalLockEnabled for iOS. None of this works as expected.
I also tried a workaround to manually lock one axis when the other one is scrolling. This works fine on iOS but it doesn't on macOS due to extreme poor performance (I think it's caused by the missing NSScrollViewDelegate and scroll events are being propagated via NotificationCenter).
Example Screen Recordings
To give you a better idea of what I mean, I have screenshots for both iOS and macOS.
Example Code
And this is the sample code used for the screenshots. So you can just create a new Multiplatform project and paste the code below in the ContentView.swift file. That's all.
import SwiftUI
let numberOfColums: Int = 150
let numberOfRows: Int = 350
struct ContentView: View {
var items: [[Item]] = {
var items: [[Item]] = [[]]
for rowIndex in 0..<numberOfRows {
var row: [Item] = []
for columnIndex in 0..<numberOfColums {
row.append(Item(column: columnIndex, row: rowIndex))
}
items.append(row)
}
return items
}()
var body: some View {
Group {
ScrollView([.horizontal, .vertical]) {
LazyVStack(alignment: .leading, spacing: 1, pinnedViews: [.sectionHeaders, .sectionFooters]) {
Section(header: Header()) {
ForEach(0..<items.count, id: \.self) { rowIndex in
let row = items[rowIndex]
LazyHStack(spacing: 1) {
ForEach(0..<row.count, id: \.self) { columnIndex in
Text("\(columnIndex):\(rowIndex)")
.frame(width: 100)
.padding()
.background(Color.gray.opacity(0.2))
}
}
}
}
}
}
.edgesIgnoringSafeArea([.top])
}
.padding(.top, 1)
}
}
struct Header: View {
var body: some View {
LazyHStack(spacing: 1) {
ForEach(0..<numberOfColums, id: \.self) { idx in
Text("Col \(idx)")
.frame(width: 100)
.padding()
.background(Color.gray)
}
Spacer()
}
}
}
struct Item: Hashable {
let id: String = UUID().uuidString
var column: Int
var row: Int
}
Can You Help?
Okay, long story short...
Does anybody knows a real working solution for this issue?
Is it a known SwiftUI ScrollView bug?
If there were a way to lock one scrolling direction while the other is scrolled, then I could deal with that. But at the moment, unfortunately, it is not usable for us.
So any solution is highly appreciated! Ideally an Apple engineer can help. 😃
NOTE: Unfortunately Apple does not allow URLs to anywhere. I also have two screen recordings for both iOS and macOS. So, if you would like to watch them, please contact me.
I am currently running Xcode Version 14.0 beta (14A5228q) creating a Multiplatform app. I wanted to include a LaunchScreen so added a Launch Screen Storyboard to my project. To the the app to see it I went under Target for my app, General, and under App Icons and Launch Screen I set the Launch Screen File to my storyboard.
This works perfectly when I run the app on iOS; however, when I run it on macOS I get an error:Launch Screen.storyboard error build: iOS storyboards do not support target device type "Mac".
I see there's no way to differentiate between macOS and iOS with the file and there's only one target. Does anyone know a way to make the storyboard only launch when running the iOS app (and iPadOS) and not be seen when running macOS?
Thanks