Post not yet marked as solved
I think we have to keep using modifyRecordsCompletionBlock because modifyRecordsResultBlock doesn't error on server record changed, it erroneously reports success. As of Xcode 14b1 iOS 16b1. See this post for more info.
Post not yet marked as solved
Use one session, according to Use Background Sessions Efficiently
I noticed if you init a session with a config with the same identifier you will actually get the previous instance.
I assume you have to set a taskDescription on the task to be able to identify it in .backgroundTask() on the Scene, where presumably you have to retrieve all the completed tasks from the session and deal with the results.
The problem is ForEach with id: \.self for a dynamic array of value types is a major mistake unfortunately made by many developers, anyone know why? The documentation states that id needs to be "The key path to the provided data’s identifier." E.g. id: \.uniqueIdentifier, or preferably conform your model struct to Identifiable and implement either let id = UUID() or var id: String { return a calculated id from other vars }
Post not yet marked as solved
The ForEach View cannot not work with indicies for dynamic data, it requires identifiers which is why we supply it with an array of Identifiable data.
This is so that it can calculate inserts, moves and deletions which obviously is impossible with an array of indicies which will in the case of moving 5 items around the indices will still be 0-4.
Post not yet marked as solved
You could try this workaround:
var cancelable: AGSCancelable?
let onCancel = { cancelable?.cancel() }
return try await withTaskCancellationHandler {
onCancel()
} operation: {
Post not yet marked as solved
In SwiftUI we don't use view model objects. The View structs (or custom @State structs) hold the data that SwiftUI uses to diff and update the screen. View models are a UIKit pattern don't use it in SwiftUI, if you do then you'll add an unnecessary level of indirection and slow SwiftUI down and lose a lot of the magic behaviour.
Post not yet marked as solved
isDetailLink(false) on the NavigationLink will fix this problem
Post not yet marked as solved
To avoid this do:
struct InsideView: View {
let value: Int
// …
}
@Binding is for when we want write access to the state.
Post not yet marked as solved
There is a mistake. You need to move your NavigationView into Tab1. Also remove the ZStack.
struct Tab1: View {
@State var shownextPage = false
var body: some View {
NavigationView{
NavigationLink( destination: SecondView(), isActive: $shownextPage) {
Text("Next Page")
}
}
}
}
Post not yet marked as solved
In the code posted, the id: \.self is a programming mistake, try
ForEach(1..<100) {
Post not yet marked as solved
Hi I'm not talking about purging all the history, only the history that is no longer needed because the NSCoreDataCoreSpotlightDelegate has already moved past it. As explained in the link I included (included again below), we have to purge the unneeded history otherwise we are wasting disk space.
Purge History
Because persistent history tracking transactions take up space on disk, determine a clean-up strategy to remove them when they > are no longer needed. Before pruning history, a single gatekeeper should ensure that your app and its clients have consumed the history they need.
From Consuming Relevant Store Changes
There is info on how to do this in the docs here: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html#//apple_ref/doc/uid/10000172i-SW6-SW15
See the note that says:
Note: If you want to allow the helper process to call methods on an object in your application, you must set the exportedInterface and exportedObject properties before calling resume. These properties are described further in the next section.
XPC is bidirectional. Just use setExportedInterface and setExportedObject in your client. Then in the server when you call a method on the remoteObjectProxy you will receive the method call in the exported object in the client.
FYI this is how apps that use CoreLocation receive location updates from the locationd daemon. Use Hopper on the CoreLocation framework and take a look at _CLLocationManagerRoutineProxy createConnection for more detail.
`/* @class _CLLocationManagerRoutineProxy */
-(void)createConnection {
rbx = self;
rdi = self->_connection;
if (rdi != 0x0) {
[rdi release];
*(rbx + 0x18) = 0x0;
}
rax = [NSXPCConnection alloc];
rax = [rax initWithMachServiceName:@"com.apple.locationd.routine" options:0x1000];
*(rbx + 0x18) = rax;
if (rax != 0x0) {
[*(rbx + 0x18) setExportedInterface:[NSXPCInterface interfaceWithProtocol:@protocol(CLLocationManagerRoutineClientInterface)]];
[*(rbx + 0x18) setExportedObject:rbx];
r14 = [*(rbx + 0x18) exportedInterface];
r13 = objc_opt_class(@class(NSArray));
objc_opt_class(@class(CLLocation));
[r14 setClasses:[NSSet setWithObjects:r13] forSelector:@selector(didUpdateLocations:) argumentIndex:0x0 ofReply:0x0];
rdx = [NSXPCInterface interfaceWithProtocol:@protocol(CLLocationManagerRoutineServerInterface)];
[*(rbx + 0x18) setRemoteObjectInterface:rdx];
r14 = [*(rbx + 0x18) serviceName];
rdi = *(rbx + 0x18);
var_78 = *__NSConcreteStackBlock;
*(&var_78 + 0x8) = 0xffffffffc2000000;
*(&var_78 + 0x10) = sub_911b;
*(&var_78 + 0x18) = 0x71d40;
*(&var_78 + 0x20) = r14;
[rdi setInterruptionHandler:rdx];
rdi = *(rbx + 0x18);
var_50 = *__NSConcreteStackBlock;
*(&var_50 + 0x8) = 0xffffffffc2000000;
*(&var_50 + 0x10) = sub_9133;
*(&var_50 + 0x18) = 0x71d40;
*(&var_50 + 0x20) = r14;
[rdi setInvalidationHandler:&var_50];
[*(rbx + 0x18) resume];
}
if ([rbx updating] != 0x0) {
[[[rbx connection] remoteObjectProxy] startUpdatingLocation];
}
return;
}
`
Just wanted to share that I noticed a bug in the above old code sample, the second append was done on the wrong variable, here it is fixed and updated:
guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: group) else { return }
var cachesURL = url.appendingPathComponent("Library", isDirectory: true)
cachesURL = cachesURL.appendingPathComponent("Caches", isDirectory: false)
Right now I'm struggling to get a disk URLCache to write to the group container, it fails with:
2021-05-24 18:46:55.879431+0100 URLCacheTestApp[95367:2519466] [logging-persist] cannot open file at line 44499 of [02c344acea]
2021-05-24 18:46:55.879495+0100 URLCacheTestApp[95367:2519466] [logging-persist] os_unix.c:44500: (0) open(/Users/me/Library/Group%20Containers/group.com.myco.MyApp/Library/Caches/Cache.db) - Undefined error: 0
2021-05-24 18:46:55.879567+0100 URLCacheTestApp[95367:2519466] NetworkStorageDB:_openDBReadConnections: failed to open read connection to DB @ /Users/me/Library/Group%20Containers/group.com.myco.MyApp/Library/Caches/Cache.db. Error=14. Cause=unable to open database file
Post not yet marked as solved
Apple's Scrumdinger sample - https://developer.apple.com/tutorials/app-dev-training/getting-started-with-scrumdinger uses a function to generate a binding. In your case it would be like this:
struct Todo: Identifiable {
let id = UUID()
var title: String
var isDone = false
}
class TodoStore: ObservableObject {
@Published var todos: [Todo] = [.init(title:"Test")]
}
struct ListRow: View {
@Binding var todo: Todo
var body: some View {
Button(action: {
self.todo.isDone.toggle()
}) {
Text("\(todo.title) \(todo.isDone.description)")
}
}
}
struct ContentView: View {
@StateObject var todoStore = TodoStore()
var body: some View {
List(todoStore.todos) { todo in
ListRow(todo: binding(for: todo))
}
}
// from Scrumdinger sample app
private func binding(for todo: Todo) - BindingTodo {
guard let scrumIndex = todoStore.todos.firstIndex(where: { $0.id == todo.id }) else {
fatalError("Can't find scrum in array")
}
return $todoStore.todos[scrumIndex]
}
}