Can someone please shed some light? I have an app that uses Core Data and CloudKit, up until the last version, I was able to sync data between devices but now after I added two new Entities for some reason it stopped syncing between devices.
Here is how I did the change:
Created a new Core Data container.
Added the new Entities and their Attributes
Tested the new Entities locally to be able to send the new schema to CloudKit.
Went to CloudKit and made sure that the new Entities and Attributes were reflected on the Developent database.
Deploy Schema Cahnges.
Went to the Production database to make sure the new schema was deployed; and it was, both databases look the same.
Testing:
Tested in the simulator and with a real device and everything syncs, even the new Entities.
If I download the app from the App Store on two different devices they do NOT sync.
Based on the procedure I'm describing above, is there any important step I may have missed when doing the migration?
I'm not sure if this is related to the syncing issue but after testing a few times, I no longer can turn the iCloud on, I get the following message when I try to turn iCloud Sync On.
CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate resetAfterError:andKeepContainer:]: <NSCloudKitMirroringDelegate: 0x282c488c0> - resetting internal state after error: Error Domain=NSCocoaErrorDomain Code=134410 "CloudKit setup failed because there is another instance of this persistent store actively syncing with CloudKit in this process." UserInfo={NSURL=file:///var/mobile/Containers/Data/Application/73F19BC7-4538-4098-85C7-484B36192CF3/Library/Application%20Support/CoreDataContainer.sqlite, NSLocalizedFailureReason=CloudKit setup failed because there is another instance of this persistent store actively syncing with CloudKit in this process., NSUnderlyingException=Illegal attempt to register a second handler for activity identifier com.apple.coredata.cloudkit.activity.setup.8D4C04F6-8040-445A-9447-E5646484521}
Any idea of what could be wrong and preventing the devices from syncing? Any idea or suggestion is welcome.
Thanks
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Post
Replies
Boosts
Views
Activity
I have a view which shows some data based on a complex calculation. Let's say I need to parse some input string and transform it in some way.
private func someComplexCalculation(_ input: String) -> String {
// ...
}
The most naive approach would be to perform this in the view's body:
struct MyView: View {
let input: String
var body: some View {
Text(someComplexCalculation(input))
}
}
But of course, we want to keep body nice and fast because SwiftUI may call it very often. The text to be displayed will be constant for a particular view, in a particular place in the hierarchy (barring some major events such as locale changes, which can basically change the entire UI anyway).
So the next idea would be to hoist the calculation out of body in to the view's initialiser:
struct MyView: View {
let value: String
init(_ value: String) {
self.value = someComplexCalculation(value)
}
var body: some View {
Text(value)
}
}
Except that this view's initialiser will be called in the body of its parent, so this isn't really much of a win at all.
So the next idea is that we need to associate the cached data with the underlying view itself somehow. From what we are told about SwiftUI, that's what @State does.
struct MyView: View {
@State var value: String
init(_ value: String) {
self._value = State(initialValue: someComplexCalculation(value))
}
var body: some View {
Text(value)
}
}
Except... apparently this is not recommended because SwiftUI won't honour the value set in the initialiser.
That's kind of okay for my purposes - the contents won't change, and every view with the same identity (place in the hierarchy) will be provided the same input. The real problem emerges when we look at the documentation for @State. Its initialiser takes a value directly, so we're still going to perform this expensive calculation every time; we'll just discard the value immediately afterwards and take one which the framework memoised.
Which brings me on to my final approach - @StateObject. Unlike @State, its initialiser takes an autoclosure, so we won't recompute the value every time. But it should still be stored in a way that is bound to the underlying view, thereby giving me a place to stash memoised values.
struct MyView: View {
final class Cache {
var transformed: String
init(input: String) {
self.transformed = someComplexCalculation(value)
}
}
@StateObject var cache: Cache
init(_ value: String) {
self._cache = StateObject(wrappedValue: Cache(input: value))
}
var body: some View {
Text(cache.transformed)
}
}
I haven't been able to find much in the way of others online using @StateObject for this purpose, so I'd like to ask - is there some other solution I'm overlooking? Is this considered a misuse of @StateObject for some reason? The documentation for the StateObject initialiser says:
Initialize using external data
If the initial state of a state object depends on external data, you can call this initializer directly. However, use caution when doing this, because SwiftUI only initializes the object once during the lifetime of the view — even if you call the state object initializer more than once — which might result in unexpected behavior.
Which seems fine. This seems like exactly what I want.
I have a performance issue with a Mac SwiftUI app. Using instruments I see hangs reported. When I zero in on a hang I see that the time profiler reports most of the hang -- in one example 658 out of 687 ms -- being in 'static AppName.$main() [inlined]'.
I think that is saying my app is busy, but busy doing what?
The "hangs" are related to SwiftUI table processing. User experience is something like this: select an item, see the view changes based upon selection show up a second or two later. The duration of the hang increases with the number of items in the table. I'm testing with 100 ~ 1200 table entries.
Hi everyone
I am fighting with a weird problem
in my app I use swiftui and ai do not use tabs, but a hierarchy of view created by me that switch one to the other with a slide animation when I tap one of the elements
i don't use gesture, but only ontap.
The same app launched on two different iPhone has two different behaviours
on the iPhone 11 no problem, the animation is fluid and responsive, on the iPhone 10 I got some delay, and in the console I can read Gesture: System gesture gate timed out
I have searched but I have not found anything useful and more than this it is extremely difficult to find some info about this warning/error
How can I solve this?
on the iPhone 10 it seems like the animation got stuck for 1 seconds prior to be executed in the correct way
I've been working on an iOS project for the iPhone and would like to support running it on macOS computers with Apple Silicon. In the Targets / Supported Destinations we added "Mac (Designed for iPhone)" but experienced Thread 1: EXC_BAD_ACCESS crashes immediately when we tried to run it.
We've isolated it down to Stepper UI elements in our view. Starting a new project and just trying to present a single Stepper in the ContentView, we get the same crash.
Here is code that presents the issue:
// ContentView.swift
import SwiftUI
struct ContentView: View {
@State var someValue = 5
var body: some View {
VStack {
Stepper("Stepper", value: $someValue, in: 0...10)
}
}
}
When run from Xcode on an iOS device or the simulator, it runs fine.
Trying to run it on the Mac, it crashes here:
// Stepper_01App.swift
import SwiftUI
@main // <-- Thread 1: EXC_BAD_ACCESS (code=2, address=0x16a643f70)
struct Stepper_01App: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Xcode 14.3 (14E222b), MacOS Ventura 13.3.1 (a), Mac mini M2.
Target: Mac (Designed for iPhone)
We have verified that the same code crashes on all the Apple Silicon Macs we have access to. Searching the Internet and Apple Developer forums I dont find other reports, so I kind of feel there must be some level of either user error or system/project misconfiguration going on?
If any iOS app that used Steppers was just crashing when trying to run on a Mac, it seems like this would be a big deal.
If anyone has input or can point out what we need to do differently, it would be appreciated!
Animation is glitching when I tap on search bar
Below is the code
struct CustomTabBar: View {
@State var searchText = ""
var data = [1,2,3,4,5,6,7,8,9,10]
var body: some View {
NavigationStack {
ScrollView(.vertical) {
ForEach(data, id: \.self) { d in
box
}
}
.navigationTitle("Search")
.searchable(text: $searchText)
}
}
var box: some View {
Rectangle()
.frame(width: 75, height: 50)
.cornerRadius(10)
}
}
I am learning SwiftUI, I want to observe an AVPlayer status so I know when the videos is paused or not.
My current approach is more less like this:
I have VideosView that holds a list of a videos (in ZStack cards).
VideoViews has a VideosViewModel.
in VideosView i am calling in onAppear VideosViewModel.getItems...
struct ItemModel: Identifiable, Codable, Hashable, Equatable {
var id: String
var author: String // video owner
var url: URL? // url to the video
var player: AVPlayer? // AVPlayer created based on self.url...
mutating func setPlayer(_ avPlayer: AVPlayer) {
self.player = avPlayer
}
}
// vm
class FeedViewModel: ObservableObject {
@Published private(set) var items: [ItemModel] = []
func getItems() async {
do {
// fetch data from the API
let data = try await dataService.fetchFeeds()
// download and attach videos
downloadFeedVideos(data)
} catch {
// ....
}
}
private func downloadFeedVideos(_ feeds: [ItemModel]) {
for index in feeds.indices {
var item = feeds[index]
if let videoURL = item.url {
self.downloadQueue.queueDownloadIfFileNotExists(
videoURL,
DownloadOperation(
session: URLSession.shared,
downloadTaskURL: videoURL,
completionHandler: { [weak self] (localURL, response, error) in
guard let tempUrl = localURL else { return }
let saveResult = self?.fileManagerService.saveInTemp(tempUrl, fileName: videoURL.lastPathComponent)
switch saveResult {
case .success(let savedURL):
DispatchQueue.main.async {
// maybe this is a wrong place to have it?
item.setPlayer(AVPlayer(url: savedURL))
self?.items.append(item)
if self?.items.count ?? 0 > 1 {
// once first video is downloaded, use all device cores to fetch next videos
// all newest iOS devices has 6 cores
self?.downloadQueue.setMaxConcurrentOperationCount(.max)
}
}
case .none: break
case .failure(_):
EventTracking().track("Video download fail", [
"id": item.id,
"ulr": videoURL.absoluteString.decodeURL()
])
}
}), { fileCacheURL in
// file already downloaded
DispatchQueue.main.async {
item.setPlayer(AVPlayer(url: fileCacheURL))
self.items.append(item)
}
})
}
}
}
}
I found this article with some pseudo-code of how to track video playback state but I'm not sure how to implement it in my code....
https://developer.apple.com/documentation/avfoundation/media_playback/observing_playback_state
Hello and thanks for reading my post.
I have a SwiftUI view, the users should be able to click a button and take printout of that view. Clicking on the button should open the standard print sheet (select printer, pages, layout, etc.).
How can I implement such a functionality? I have been trying hard without any success. Please help.
It is an iPad app, using Xcode 14.3
I am using a LayzVStack embedded into a ScrollView. The list items are fetched from a core data store by using a @FetchResult or I tested it also with the new @Query command coming with SwiftData.
The list has one hundred items 1, 2, 3, ..., 100.
The user scrolled the ScrollView so that items 50, 51, ... 60 are visible on screen.
Now new data will be fetched from the server and updates the CoreData or SwiftData model. When I add new items to the end of the list (e.g 101, 102, 103, ...) then the ScrollView is keeping its position.
Opposite to this when I add new items to the top (0, -1, -2, -3, ...) then the ScrollView scrolls down.
Is there a way with the new SwiftData and SwiftUI ScrollView modifiers to update my list model without scrolling like with UIKit where you can query and set the scroll offset pixel wise?
Is .refreshable supposed to do anything on macOS? Works fine on iOS and iPadOS but it's not triggered on macOS. It's available since macOS 12 but the documentation doesn't mention anything about that.
https://developer.apple.com/documentation/swiftui/view/refreshable(action:)
The code for @State doesn't seem to work.
struct DonutListView: View {
var donutList: DonutList
@State private var donutToAdd: Donut?
var body: some View {
List(donutList.donuts) { DonutView(donut: $0) }
Button("Add Donut") { donutToAdd = Donut() }
.sheet(item: $donutToAdd) { // <-- would need a "donut in"
TextField("Name", text: $donutToAdd.name) // <-- donutToAdd is optional and I'm not sure how it would be unwrapped
Button("Save") {
donutList.donuts.append(donutToAdd)
donutToAdd = nil
}
Button("Cancel") { donutToAdd = nil }
}
}
}
Does anyone have a fix for this?
Thanks,
Dan!
Previously, it was recommended to use the @MainActor annotation for ObservableObject implementation.
@MainActor
final class MyModel: ObservableObject {
let session: URLSession
@Published var someText = ""
init(session: URLSession) {
self.session = session
}
}
We could use this as either a @StateObject or @ObservedObject:
struct MyView: View {
@StateObject let model = MyModel(session: .shared)
}
By moving to Observation, I need to the @Observable macro, remove the @Published property wrappers and Switch @StateObject to @State:
@MainActor
@Observable
final class MyModel {
let session: URLSession
var someText = ""
init(session: URLSession) {
self.session = session
}
}
But switching from @StateObject to @State triggers me an error due to a call to main-actor isolated initialiser in a synchronous nonisolated context.
This was not the case with @StateObject of @ObservedObject.
To suppress the warning I could :
mark the initializer as nonisolated but it is not actually what I want
Mark the View with @MainActor but this sounds odd
Both solutions does not sound nice to my eye.
Did I miss something here?
In the Apple Music app on iPad (horizontal size class == .regular), when a selection is made from the Split View sidebar, the detail switches to a separate UINavigationController for that selection, where we can push/pop views. If we make a different selection from the sidebar, we get another UINavigationController to manipulate. If we return to the first selection, the detail view is still showing the stack contents for that controller.
I am trying to get the same behavior from NavigationSplitView in SwiftUI, but the detail view will reset its presented controller to its root. I think this is because NavigationSplitView uses whatever NavigationStack it finds in the detail hierarchy to manage its contents, effectively erasing the per-view stack contents. I have tried various methods of saving and restoring the navigation path without any luck. Any ideas on how to approach this?
I have included a very simple example to show what I'm talking about.
import SwiftUI
struct ExampleView: View {
enum Selection: String, CaseIterable {
case letters
case numbers
}
@State private var selection: Selection?
var body: some View {
NavigationSplitView {
List(selection: $selection) {
ForEach(Selection.allCases, id: \.self) { selection in
NavigationLink(value: selection) {
Text(selection.rawValue.capitalized)
}
}
}
.navigationTitle("Sidebar")
} detail: {
switch selection {
case .letters:
self.lettersView
case .numbers:
self.numbersView
default:
Text("Make a selection")
}
}
}
var lettersView = LettersView()
var numbersView = NumbersView()
}
struct ExampleView_Previews: PreviewProvider {
static var previews: some View {
ExampleView()
}
}
// MARK: -
struct LettersView: View {
private let letters = ["a", "b", "c", "d", "e", "f"]
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
List {
ForEach(letters, id: \.self) { letter in
NavigationLink(value: letter) {
Text(letter.uppercased())
}
}
}
.navigationTitle("Letters")
.navigationDestination(for: String.self) { letter in
Text(letter.uppercased()).font(.largeTitle)
}
}
}
}
// MARK: -
struct NumbersView: View {
private let numbers = Array(0..<6)
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
List {
ForEach(numbers, id: \.self) { number in
NavigationLink(value: number) {
Text(String(number))
}
}
}
.navigationTitle("Numbers")
.navigationDestination(for: Int.self) { number in
Text(String(number)).font(.largeTitle)
}
}
}
}
So I am trying to move an old project from ios16 to ios17... wanted to play around with the new previews, and animations and first error I get is the above.
When I create a new project I can use the macro just fine.
What is more: when I add a new swiftUI file I get the same error with the #Preview macro.
I went through the project and target settings, making sure everything is set to ios17 and Swift5, but can't find any other settings. Cleared the build cache and rebuilt from scratch.
Hoping someone else ran onto the same problem and found a solution?
Without using #Preview
Using the new inline PhotosPicker style in iOS 17, it isn't made clear how to handle the cancel button's input, and i cannot seem to find an answer in the documentation.
PhotosPicker(
"Select picture",
selection: $selected,
selectionBehavior: .default,
photoLibrary: .shared()
)
.photosPickerStyle(.inline)
Does anybody have a solution or is this a bug that needs to be fixed?
Certainly, here's an explanation and the minimal code to reproduce the issue in English:
In SwiftUI, attempting to present a sheet or any other presentation view while a Menu view is open causes a conflict. This is because SwiftUI does not allow multiple presentation views to be open at the same time. Here's the simplest code to reproduce the issue:
import SwiftUI
struct ContentView: View {
@State var showSheet = false
var body: some View {
VStack {
Menu {
Button("Option 1") { }
Button("Option 2") { }
} label: {
Text("Open Menu")
}
Button(action: {
showSheet = true
}) {
Text("Open Sheet")
}
.sheet(isPresented: $showSheet) {
Text("Hello, Sheet!")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Is it possible to specify a default window size for a 2D window in visionOS? I know this is normally achieved by modifying the WindowGroup with .defaultSize(width:height:), but I get an error that this was not included in "xrOS". I am able to specify .defaultSize(width:height:depth:) for a volumetric window, but this doesn't have any effect when applied to a 2D one.
Hi all,
I am starting using the new amazing SwiftData and I really like it!
I have a question regarding how to pass the filter predicate from the parent view.
In my app I have a simple case where I have a package that contains multiple items.
When I package is selected a view is pushed with the list of items in that package.
The Items view has a query as following:
struct ScoreListView: View {
[.....]
@Query(filter: #Predicate<SWDItem> { item in
item.package?.id == selectedPackage.id
} ,sort: \.timestamp) var items: [SWDItem]
[.....]
var body: some View {
[...]
}
The problem is that selectedPackage is not "yet" available when defining the @Query and I have the classic error "Cannot use instance member 'selectedPackage' within property initializer; property initializers run before 'self' is available".
How can I structure the code to have the selected package available when the @Query is defined?
Thank you a lot
Hi. The binding in a ForEach or List view doesn't work anymore when using the @Observable macro to create the observable object. For example, the following are the modifications I introduced to the Apple's example called "Migrating from the Observable Object Protocol to the Observable Macro" https://developer.apple.com/documentation/swiftui/migrating-from-the-observable-object-protocol-to-the-observable-macro
struct LibraryView: View {
@Environment(Library.self) private var library
var body: some View {
List($library.books) { $book in
BookView(book: book)
}
}
}
All I did was to add the $ to turn the reference to library.books into a binding but I got the error "Cannot find '$library' in scope"
Is this a bug or the procedure to use binding in lists changed?
Thanks
Description
In Live Activities, we saw many beautiful animations that powered by .numericText() like Text(time, style: .timer), or even Text with .contentTransition(.numericText()) applied.
But it seems like in normal SwiftUI View, these beautiful animations are gone. Instead, we saw a blinking result or fade-in-out result.
Is that exactly right?
ScreenShots
In Live Activity:
In normal SwiftUI View: