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
Replies
Boosts
Views
Activity
You could try this workaround:
var cancelable: AGSCancelable?
let onCancel = { cancelable?.cancel() }
return try await withTaskCancellationHandler {
onCancel()
} operation: {
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.
isDetailLink(false) on the NavigationLink will fix this problem
To avoid this do:
struct InsideView: View {
let value: Int
// …
}
@Binding is for when we want write access to the state.
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")
}
}
}
}
In the code posted, the id: \.self is a programming mistake, try
ForEach(1..<100) {
Same here, on Intel using Xcode 13 beta 2 with iPhone 12 simulator. Killing the Spotlight processes works for a while until it comes back again (doing a drag down search brings it back). Hopefully beta 3 fixes it.
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
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]
}
}
import SwiftUI
import Firebase
struct ItemsView: View {
	 var itemName: String
	 var itemID: String
	 @ObservedObject var itemsGetter = ItemsGetter()
		// ....etc
.onAppear {
		itemsGetter.get(itemID:itemID)
}
		}
class ItemsGetter {
	 @Published var data = [items]()
	 func get(itemID:String) {
			let db = Firestore.firestore()
			db.collection("items").whreField("itemID", isEqualTo: itemID).addSnopshotListenser
Here is how to open a new window in SwiftUI on macOS.
In your ContentView create a button and open a URL for your app and another View e.g. Viewer to be shown in the window we will open:
struct ContentView: View {
		@Environment(\.openURL) var openURL
		var body: some View {
				VStack {
						Button("Open Viewer") {
								if let url = URL(string: "myappname://viewer") {
										 openURL(url)
								}
						}
						Text("Hello, world!")
				}
				.padding()
		}
}
struct Viewer: View {
		var body: some View {
				Text("Viewer")
		}
}
In your App add another WindowGroup for your viewer and set it to enable handling of external launch events (an internal event in our case).
@main
struct GroupDefaultsTestApp: App {
		var body: some Scene {
				WindowGroup {
						ContentView()
				}
				WindowGroup("Viewer") { // other scene
						Viewer()
				}
				.handlesExternalEvents(matching: Set(arrayLiteral: "*"))
		}
}
Now in Project->Info->URL Types type in myappname in the URL Schemes field (and the identifier field too) to register our app with the system.
Now run your app and click the button and it should open a new window!