I am working to add Spotlight indexing for my app entities as discussed in WWDC24's video "What's New in App Intents".
That video goes over the IndexedEntity protocol and the integration with Spotlight via CSSearchableItemAttributeSet.
What I'm seeing though does not match the video. In the video, the presenter goes through the sort of progressive approach you can take to getting this data into Spotlight starting with the basics and then expanding to include more support depending on how much the developer wants to do.
What I'm seeing is that if you conform to IndexedEntity, your entities will appear in Spotlight using the name derived from
public var displayRepresentation: DisplayRepresentation
So, that works. Name appears... BUT the next part of the video goes into how to expand your implementation with more metadata for Spotlight via CSSearchableItemAttributeSet. The issue I'm seeing is that once that's implemented, the items disappear from Spotlight, almost like that implementation is overriding the base implementation in a way that no longer functions.
My expectation is that an item with custom attributes would use them in Spotlight as appropriate, not disappear from search, i.e. what's shown in the video should work.
I've got a sample project here:
https://hanchor.s3.amazonaws.com/misc/IndexingTest.zip
To reproduce with the sample:
Build and run. Indexing is setup in the init() method so it will just run.
Go to Spotlight and search for 'Huntersblau', a string included in the content set. At this point you should see a result - good!
Stop the app and go back and uncomment the var attributeSet: CSSearchableItemAttributeSet implementation in IndexingTestApp.swift. This will provide custom attributes to Spotlight.
Repeat steps 1 and 2 - you'll see now, it no longer appears in the search results - when CSSearchableItemAttributeSet is implemented, the item drops out of Spotlight.
Post
Replies
Boosts
Views
Activity
I have an app with fairly typical requirements - I need to insert some data (in my case from the network but could be anything) and I want to do it in the background to keep the UI responsive.
I'm using SwiftData.
I've created a ModelActor that does the importing and using the debugger I can confirm that the data is indeed being inserted.
On the UI side, I'm using @Query and a SwiftUI List to display the data but what I am seeing is that @Query is not updating as the data is being inserted. I have to quit and re-launch the app in order for the data to appear, almost like the context running the UI isn't communicating with the context in the ModelActor.
I've included a barebones sample project. To reproduce the issue, tap the 'Background Insert' button. You'll see logs that show items being inserted but the UI is not showing any data.
I've tested on the just released iOS 18b3 seed (22A5307f).
The sample project is here:
https://hanchor.s3.amazonaws.com/misc/SwiftDataBackgroundV2.zip
I am working on adding indexing to my App Entities via IndexedEntity. I already, separately index my content via Spotlight.
Watching 'What's New in App Intents', this is covered well but I have a question.
Do I need to implement both CSSearchableItem's associateAppEntity AND also a custom implementation of attributeSet in my IndexedEntity conformance? It seems duplicative but I can't tell from the video if you're supposed to do both or just one or the other.
I'm using Swift Data for an app that requires iOS 18.
All of my models conform to a protocol that guarantees they have a 'serverID' String variable.
I wrote a function that would allow me to pass in a serverID String and have it fetch the model object that matched. Because I am lazy and don't like writing the same functions over and over, I used a Self reference so that all of my conforming models get this static function.
Imagine my model is called "WhatsNew". Here's some code defining the protocol and the fetching function.
protocol RemotelyFetchable: PersistentModel {
var serverID: String { get }
}
extension WhatsNew: RemotelyFetchable {}
extension RemotelyFetchable {
static func fetchOne(withServerID identifier: String, inContext modelContext: ModelContext) -> Self? {
var fetchDescriptor = FetchDescriptor<Self>()
fetchDescriptor.predicate = #Predicate<Self> { $0.serverID == identifier }
do {
let allModels = try modelContext.fetch(fetchDescriptor)
return allModels.first
} catch {
return nil
}
}
}
Worked great! Or so I thought...
I built this and happily ran a debug build in the Simulator and on devices for months while developing the initial version but when I went to go do a release build for TestFlight, that build reliably crashed on every device with a message like this:
SwiftData/DataUtilities.swift:65: Fatal error: Couldn't find \WhatsNew. on WhatsNew with fields [SwiftData.Schema.PropertyMetadata(name: "serverID", keypath: \WhatsNew., defaultValue: nil, metadata: Optional(Attribute - name: , options: [unique], valueType: Any, defaultValue: nil, hashModifier: nil)), SwiftData.Schema.PropertyMetadata(name: "title", keypath: \WhatsNew., defaultValue: nil, metadata: nil), SwiftData.Schema.PropertyMetadata(name: "bulletPoints", keypath: \WhatsNew.)>, defaultValue: nil, metadata: nil), SwiftData.Schema.PropertyMetadata(name: "dateDescription", keypath: \WhatsNew., defaultValue: nil, metadata: nil), SwiftData.Schema.PropertyMetadata(name: "readAt", keypath: \WhatsNew.)>, defaultValue: nil, metadata: nil)]
It seems (cannot confirm) that something in the release build optimization process is stripping out some metadata / something about these models that makes this predicate crash.
Tested on iOS 18.0 and 18.1 beta.
How can I resolve this? I have two dozen types that conform to this protocol. I could manually specialize this function for every type myself but... ugh.
I'm seeing a lot of these in my logs:
PersistentIdentifier PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-swiftdata://Course/BC9CF99A-DE6A-46F1-A18D-8034255A56D8), implementation: SwiftData.PersistentIdentifierImplementation) was remapped to a temporary identifier during save: PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata:///Course/t58C849CD-D895-4773-BF53-3F63CF48935B210), implementation: SwiftData.PersistentIdentifierImplementation). This is a fatal logic error in DefaultStore
... though everything seems to work.
Does anyone know what this means in this context? Anything I can do to not have this appear?
I am trying to use the ModelContainer's "delete" function to delete all instances of a model but I'm getting an error related to my relationships:
Constraint trigger violation: Batch delete failed due to mandatory OTO nullify inverse on LeagueSeasonRanking/golfer
I do have a relationship on Golfer, a toMany relationship to LeagueSeasonRanking which is marked with a cascade delete rule... I would expect that to take care of things and cascade along but it seems to not work. Is that a bug?
I'm trying CoreSpotlight on the 18b1 seed on iOS and after submitting my query, I'm getting multiple errors about what looks like missing models:
[Model loading] model loading failed with err -1000 for model path /Users/hunter/Library/Developer/CoreSimulator/Devices/0AF4F46E-5510-4458-B61C-F8A153155809/data/Containers/Data/Application/1D8580C0-AC80-4949-9FDA-31DB463BDA5C/Library/Spotlight/Resources_V3/Default/models/spotlight_l2.mlmodelc and directives path /Users/hunter/Library/Developer/CoreSimulator/Devices/0AF4F46E-5510-4458-B61C-F8A153155809/data/Containers/Data/Application/1D8580C0-AC80-4949-9FDA-31DB463BDA5C/Library/Spotlight/Resources_V3/Default/directives/directives_l2.mdplist
I am calling CSUserQuery.prepare() but that doesn't seem to make a difference.
Is there more to this than what is on this page? https://developer.apple.com/documentation/corespotlight/building-a-search-interface-for-your-app?changes=latest_minor
I'm trying to use SwiftData for a new app after ~20 years of Core Data (and EOF before that). So while I'm new to SwiftData, I'm not new to Apple persistence frameworks.
I've got a pretty typical workflow - need to load some JSON from the network, convert that into model objects.
I've created an actor using the @ModelActor macro and I'm using that to do the network fetch and insert. I can set breakpoints in this code and see that it does indeed run and it's running on a non-main queue. That all seems fine.
The problem is that my @Query powered variable in my SwiftUI user interface does not get updated when this data is loaded and saved as I would expect it to.
I'm passing in the container to the actor using modelContext.container from the same modelContext that is powering the view / in the environment. My understanding was that like Core Data before it, the SwiftData framework was listening for the relevant notifications passed by the container/context, processing those and updating the UI but I can only see my data if I quit and relaunch the app.
This seems like it should be a very common use case but I've not found much online. Not sure if that means I'm just doing something fundamentally wrong or what.
Tested on both iOS 18 and 17 with the same results.
Anyone else doing this successfully? What could I be doing wrong?
I've got an iOS framework that I've had around for ages. It's a mixture of Objective-C and Swift.
Since installing Xcode 12, I'm now getting a bunch of warnings of the type:
'Double-quoted include in framework header, expected angle-bracketed instead'
If I go to the various source files and say change:
#import "Place.h"
to
#import <VegasKit/Place.h>
then I get an error saying it can't find the file. If I try this:
#import <Place.h>
then I get an error telling me to go back to double-quotes, i.e. undo the change.
Any idea what I can do to get this all setup correctly? Thanks.
Hi,
New in iOS 17 and the aligned releases is a modifier "toolbarTitleDisplayMode". What does this do exactly?
https://developer.apple.com/documentation/SwiftUI/View/toolbarTitleDisplayMode(_:)
I've experimenting with it a bunch and can't ever see it do really anything so I'm sure I'm using it wrong. What is this for?
So, using UIStackView, I've noticed that some UILabels seem to want to truncate instead of wrap to a new line... Anyone else noticed this? The label's number of lines is set to 0.There's a stack view with two labels in it. The stack view is setup to be horizontally and vertically centered in its superview with at least 10 points from the trailing and leading margins. I'd expect the labels to wrap to a new line, not truncate.Any thoughts?
Is there a problem with an app having more than one widget extension?
I previously had two 'Today View' extensions that I'm replacing but after installing the app on device with two widget extensions, I'm only seeing the second one in the widget picker.
I see that there's WidgetBundle but my two widgets have very different datasets so the timeline stuff won't mesh.
I'm using the new multiplatform target option in Xcode 14 to add an iPad target to an existing macOS app.
The macOS app uses the Sparkle framework to update itself. Sparkle is a macOS-only framework.
I added the iPad target and specified the Sparkle framework should only apply to the macOS build but when trying to build the app, Xcode complains that the Sparkle framework doesn’t exist for iOS (true but should not be relevant).
Xcode is trying to build/include Sparkle even though it’s marked to not include for iOS builds.
Has anyone had any success with this?
Hi,I've got my CloudKit records with created and modifed setup to be sortable and queryable but I'm having a hard time constructing a CloudKit.js query that will use those values.This: var query = {
recordType: "MyRecord",
sortBy: [{
fieldName: 'created'
}]
};This doesn't work, I get this error:Unknown field 'CKFieldName{_name='created'}I also tried 'createdDate', 'modified', 'modificationDate' and all give the same error. What's the magic?
Hi,
With iOS 15 we can now update the nsPredicate and nsSortDescriptors properties on a @FetchRequest which is great.
What I'm wondering though is the correct way to apply/re-apply user data stored in @State and/or @SceneStorage for predicates when a view is init'd.
Something like @SceneStorage isn't available in the init method but I find that onAppear isn't called in some circumstances.
For example, let's say I have a picker that drives the NSPredicate and the user picks a non-default value. If the app goes into the background and then back to the foreground and that same view is visible, it looks like SwiftUI re-runs the init for the view but does not re-run the onAppear modifier, leaving my UI in an inconsistent state.
What's the right way to handle this? Feels like I must be fighting the framework / there must be a better way.