I have an app which uses SwiftData and CloudKit all works fine and well. Now I wanted to implement a feature which lets the user know that there are data incoming from the cloud and they have to wait a little bit for the data to show up. Furthermore my app needs to do some data sanitation when it starts up. This sanitation should only be done after the CloudKit updates are processed.
So is there a way that my app can know when CloudKit is doing updates and when it is finished? I was looking for some kind of notification but couldn’t find any info on that.
I don’t need to know which data are updated or process the data. I just want to get notified when a sync starts and when it has ended. Actually it would suffice to know when a sync is finished.
Post
Replies
Boosts
Views
Activity
I want to recreate an user experience like in the settings app in tvOS. Therefore I have a HStack with some content on the left side and a List of NavigationLinks on the right side.
However a focused link in the list gets clipped on the left side. I tried paddings and spacers and what not, but nothing helped. Is this is a bug or am I missing something?
Here is some example code to show the problem:
struct ContentView: View {
var body: some View {
NavigationStack {
HStack(spacing: 20) {
VStack(alignment: .center) {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
List {
ForEach(SomeViewEnum.allCases) { someView in
NavigationLink(someView.rawValue, value: someView)
}
}
.navigationDestination(for: SomeViewEnum.self) { someView in
Text(someView.rawValue)
}
}
}
}
}
And a screenshot to show the problem:
I have a multiplatform app where I support iOS, macOS and tvOS. There is one target which supports it all. In my assets catalog I have the AppIcon entry which holds the app icon for iOS and macOS. This works as expected. However the tvOS app icon is ignored. I added an "tvOS App Icon & Top Shelf Image" asset to my asset catalog and filled it with my icons for tvOS.
Then I added it in the target’s general settings App Icon entry under App Icons and Launch Screen like shown in the screenshot.
What am I missing? What needs to be done to make this work?
I am building a tvOS app which divides the screen into two parts horizontally. Both sides have buttons. I want a certain button on the right side to have focus. To achieve that I am marking the enclosing HStack with .focusScope() and then use .prefersDefaultFocus(in:) on the button which should have focus.
This works fine, even if I add another focus scope inside (see source code). But as soon as I wrap the HStack in a NavigationView it falls apart. The scope is not set as intended, instead the left view always gets the focus.
Am I missing something? Is this intended? I’m a little lost right now.
I am targeting tvOS 16.4 and using Xcode 14.3.1.
Fun fact: The simulator view inside Xcode displays the view correctly. The simulator and an actual device are not.
Here is an example to showcase that:
struct ContentView: View {
@Namespace private var mainNamespace
@Namespace private var rightNamespace
var body: some View {
// NavigationView {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
HStack {
VStack {
Button("left") {}
}
VStack {
Button("right 1") {}
Button("right 2") {}
.prefersDefaultFocus(in: rightNamespace)
}
.focusScope(rightNamespace)
.prefersDefaultFocus(in: mainNamespace)
}
.focusScope(mainNamespace)
.padding(.top, 50)
}
.padding()
// }
}
}
I have an app which uses SwiftUI and Mac Catalyst. When running on a Mac I want to provide a preferences menu entry with the usual keyboard shortcut Command + ,. An implementation via the Settings bundle is out of question since my preferences are too complex for this.
Here is a reduced example of my implementation:
import SwiftUI
@main
struct PreferencesMenuTestApp: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: UIResponder, UIApplicationDelegate {
override func buildMenu(with builder: UIMenuBuilder) {
let preferencesCommand = UIKeyCommand(title: "Preferences…",
action: #selector(showPreferences),
input: ",",
modifierFlags: .command)
// let preferencesCommand = UIAction(title: "Preferences…") { action in
// debugPrint("show preferences")
// }
let menu = UIMenu(title: "Preferences…",
options: .displayInline,
children: [preferencesCommand])
builder.insertSibling(menu, afterMenu: .about)
}
@objc
func showPreferences() {
debugPrint("show preferences")
}
}
The problem is that the menu entry is disabled. Obviously the provided selector is not recognised. When I mark the AppDelegate with @main, then the menu entry is enabled. Of course then the app's window is empty.
When I switch to the UIAction implementation (the out commented code) it works fine. But since one cannot provide a keyboard shortcut for UIActions this is not a good solution.
What am I missing? How would one implement a preferences menu entry that actually works?
I am using Xcode 15 and working on a localised app. I use the new String Catalogs feature which works great for my app. In my app I created some local package like Apple has done it in the Backyard Birds example. However the translations I did in the package's String Catalog won’t be used in the app. What am I doing wrong?
For my app I use a struct for my CoreData persistence controller like so:
struct PersistenceController {
static var shared = PersistenceController()
// more code omitted for brevity
}
As a development asset I made an extension to the PersistenceController to provide a special instance for previews with some sample data.
extension PersistenceController {
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
// create some sample data
return result
}()
}
Now I want to use the special preview instance with the new #Preview macro in Xcode beta 2. The deployment target for the app is set to iOS 17.
#Preview {
var context = PersistenceController.preview.container.viewContext
return SpanList()
.preferredColorScheme(.light)
.environment(\.managedObjectContext, context)
}
But the preview fails to build due to the following error:
Type 'PersistenceController' has no member 'preview'.
My experiments show that everything I add to the PersistenceController via an extension is not available in the preview macro. This is no matter where I place the extension. Even when it’s placed in the same file as the PersistenceController itself.
Am I missing something or is this intended behaviour?
I’ve got this simple view and it doesn’t work as expected. When clicking the button a new Eventis created and the flag used as binding for a sheet is set to true. This should show the sheet and give the sheet access to the Event. Instead I get the error message Fatal error: Unexpectedly found nil while unwrapping an Optional value.
I can’t see the problem. As far as I see this the tmpEvent variable should have a valid value once the sheet is presented.
import SwiftUI
struct TestView: View {
@Environment(\.managedObjectContext) private var viewContext
@State private var showingSheet = false
@State private var tmpEvent: Event?
var body: some View {
VStack {
Button(action: showSheet) {
Label("Add event", systemImage: "plus.circle")
}
}
.sheet(isPresented: $showingSheet) {
Text("event title: \(tmpEvent!.descriptionString)"). // Fatal error occurs here
}
}
private func showSheet() {
tmpEvent = Event(context: viewContext)
showingSheet = true
}
}
Any ideas why this isn’t working?
In my app I’ve got a list view and a view for displaying the rows in the list. When I delete an item from that list the app crashes in the row view stating an illegal access.
I don’t understand why the row view is rendered again for the deleted item.
The list view:
import Foundation
import SwiftUI
struct SpanList: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [ NSSortDescriptor(keyPath: \Span.startDate,
ascending: true) ],
predicate: NSPredicate(format: "isArchived != YES"),
animation: .default)
private var activeSpans: FetchedResults<Span>
var body: some View {
NavigationView {
VStack {
List {
Section(header: ActiveSectionHeader()) {
ForEach(activeSpans, id: \.id) { item in
NavigationLink(destination: getConfiguredEditView(span: item)) {
SpanRow(span: item)
}
.buttonStyle(PlainButtonStyle())
.listRowBackground(item.color.opacity(0.5))
}
.onDelete(perform: deleteItems)
}
}
.listStyle(GroupedListStyle())
}
}
}
private func getConfiguredEditView(span: Span) -> some View {
EditSpan(span: span)
.navigationTitle("Edit Span")
.navigationBarTitleDisplayMode(.inline)
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
// Necessary due to a bug in the framework. Without this the app crashes
// with a bug stating multiple access from different threads is not
// allowed.
viewContext.perform {
offsets.map {
activeSpans[$0]
}.forEach(viewContext.delete)
PersistenceController.shared.save()
}
}
}
}
The row view:
import SwiftUI
import CoreData
struct SpanRow: View {
@ObservedObject var span: Span
var body: some View {
HStack(alignment: .center) {
VStack(alignment: .leading) {
HStack {
if span.showOnStartPage && !span.isArchived {
Image(systemName: "paperclip")
}
Text(span.descriptionString)
.font(.headline)
.fontWeight(.bold)
}
Spacer()
HStack {
// It crashes here
Text("\(span.startDate, formatter: dateFormatter)")
Text("–")
if span.usesEndDate {
Text("\(span.endDate, formatter: dateFormatter)")
} else {
Image(systemName: "infinity")
}
}
}
Spacer()
if let daysSinceStart = span.daysSinceStart {
VStack {
Text("\(daysSinceStart)")
.font(.largeTitle)
.fontWeight(.semibold)
Text("days")
}
}
}
.padding(.vertical, 5)
}
private let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
return formatter
}()
}
What am I missing?