Hello, I am trying to use app groups to share preferences between an app and its QuickLook extension (both sandboxed), but I can't understand why it's not working.
For testing, I created an empty macOS app project and added a QuickLook Extension, then on both the targets' entitlement files I added the app group domain in the form "teamid.test". Last but not least, in the Info.plist file of the QL extension i added some UTIs to have the QL extension called when previewing.
In the QL extension's PreviewViewController.swift file I try to save a value like this:
func preparePreviewOfFile(at url: URL, completionHandler handler: @escaping (Error?) -> Void) {
let defaults=UserDefaults(suiteName: "teamid.***")
defaults?.set(1, forKey: "test")
handler(nil)
}
If I try to run the app and preview a file though, I get this message in the Console:
Couldn't write values for keys ( test ) in CFPrefsPlistSource<0x7fb63681cce0> (Domain: teamid.***, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: Yes): setting preferences outside an application's container requires user-preference-write or file-write-data sandbox access
And the value is not saved. The only way to make this work is to add a temporary exception in the extension target, like this:
<array>
<string>/Library/Group Containers/teamid.***/</string>
</array>
</plist>
What bugs me is that if I try to save a value from the app instead, it works.
Are app groups not supported for QuickLook extensions?
Thank you,
Michele
Post
Replies
Boosts
Views
Activity
Hello, I am stuck with the following problem.
I have a view where i fetch a some data (SetlistsView) and present it
in a List. The add and move functions work flawlessly and the list is
updated as soon as I execute one of these. This is the code for that
view:
struct SetlistsView: View {
@Environment(\.managedObjectContext) private var managedObjectContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Setlist.id, ascending: true)],
animation: .default
)
private var setlists : FetchedResults<Setlist>
var body: some View {
NavigationView {
List {
ForEach(setlists, id: \.self) { setlist in
SetlistRowView(setlist: setlist)
}
.onMove(perform: move)
}
.toolbar {
ToolbarItem {
Button(action: add) {
Label("Add Item", systemImage: "plus")
}
}
}
}
}
func add() {
let newSet = Setlist(context: managedObjectContext)
newSet.id = fetchMaxId() + 1
PersistenceController.shared.save()
}
func move(from oldIndex: IndexSet, to newIndex: Int) {
var revisedItems: [Setlist] = setlists.map{$0}
revisedItems.move(fromOffsets: oldIndex, toOffset: newIndex)
for reverseIndex in stride(from: revisedItems.count-1, through: 0, by: -1) {
revisedItems[reverseIndex].id = Int64(reverseIndex)
}
PersistenceController.shared.save()
}
private func fetchMaxId() -> Int64 {
return (setlists.max(by: { a, b in a.id < b.id}))?.id ?? -1
}
}
For each element in the list I instantiate a SetListRowView to which I pass the setlist element. This is the code for that view:
struct SetlistRowView: View {
// Needs to be observed or edits made in SetlistView
// (like changing name or list order) won't update this view
@ObservedObject var setlist : Setlist
var body: some View {
NavigationLink {
SongsView(setlist: setlist)
} label: {
Text(String(setlist.id))
}
}
}
This acts as a middleman in which I use a NavigationLink to pass the
selected setlist to the SongsView, for which this is the code:
struct SongsView: View {
@Environment(\.managedObjectContext) private var managedObjectContext
@ObservedObject var setlist : Setlist
@State private var songs : [Song]
init(setlist: Setlist) {
self.setlist = setlist
let allObjects = setlist.songs?.allObjects as! [Song]
self.songs = allObjects.sorted(by: {$0.id < $1.id})
}
var body: some View {
List {
ForEach(songs, id: \.self) { song in
Text(String(song.id))
}
.onMove(perform: move)
}
.toolbar {
ToolbarItem {
Button(action: add) {
Label("Add Item", systemImage: "plus")
}
}
}
}
func add() {
let newSong = Song(context: managedObjectContext)
newSong.id = fetchMaxId() + 1
newSong.setlist = setlist
PersistenceController.shared.save()
}
func move(from oldIndex: IndexSet, to newIndex: Int) {
var revisedItems: [Song] = songs.map{$0}
revisedItems.move(fromOffsets: oldIndex, toOffset: newIndex)
for reverseIndex in stride(from: revisedItems.count-1, through: 0, by: -1) {
revisedItems[reverseIndex].id = Int64(reverseIndex)
}
PersistenceController.shared.save()
}
private func fetchMaxId() -> Int64 {
return (songs.max(by: { a, b in a.id < b.id}))?.id ?? -1
}
}
And here's my problem. In the SongsView I the move and add functions
don't work as they should. The add function actually inserts a new item
but the view doesn't get refreshed, I have to get back into the
SetlistsView and enter the SongsView again. The move function doesn't
reassign the id property.
I don't get why these functions work in the SetlistsView but not in the SongsView. I tried changing the songs var as such
@FetchRequest private var songs : FetchedResults<Song>
init(setlist: Setlist) {
self.setlist = setlist
let predicate = NSPredicate(format: "setlist == %@", setlist)
let sortDescriptors = [NSSortDescriptor(keyPath: \Song.id, ascending: true)]
self._songs = FetchRequest(sortDescriptors: sortDescriptors, predicate: predicate)
}
And this seems to work better, as the add function works, but if I
add a name property to the Song object (in the CoreData database) I can
see that, when the move action ends, the songs are put back into their
original order and not actually swapped.
Why the behaviour is different in the two views and how can I fix it? Thank you
I am trying to retrieve the ellipsoidal altitude from a CLLocation but it seems like an invalid value is always returned, no matter the vertical accuracy (which according to the documentation should just be > 0) I first encountered this problem while developing a tool to retrieve workouts from healthkit, but i tried this code in a playground and i still get zero.
import CoreLocation
var location = CLLocation(coordinate: CLLocationCoordinate2D(latitude: 46.071067, longitude: 13.234579), altitude: 113, horizontalAccuracy: CLLocationAccuracy(floatLiteral: 1.0), verticalAccuracy: CLLocationAccuracy(floatLiteral: 1.0), timestamp: Date())
print(location.ellipsoidalAltitude)
Am I doing something wrong or is this a bug?