NSManagedObjectContextObjectsDidChangeNotification not always called instantly - macos

I have an Mac Application using a NSPersistentDocument. I want to get notified when Objects are deleted to save this information using Core Data. So I'm listening for NSManagedObjectContextObjectsDidChangeNotification. Often it is called instantly when objects are deleted, but sometimes it is only called after the persistent document is saved with all deleted objects not being notified before. Because I want to let the user directly export all existing objects (and not the deleted anymore) what to I have to do to become notified instantly to save the delete information or do I have to use it in another way?

NSManagedObjectContextObjectsDidChangeNotification is no longer issued as frequently or quickly on 10.7 as on 10.6. You can force Core Data to issue the notification (assuming there are changes) by calling -[NSManagedObjectContext processPendingChanges].

Related

How to make a Finder Sync Extension change badges in response to outside events

I have a Finder Sync Extension that will display a badge on a file based on the state of a local database. It's straightforward enough to query this database in the requestBadgeIdentifierForURL function, but what if I want the badge to change for a Finder item that's already visible if the state of that database has changed (which can be via a notification through any variety of mechanisms). The documentation (https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html) would seem to imply this is possible with this statement:
You might also want to track these URLs, in order to update their
badges whenever their state changes.
The only ways I can imagine this would be possible (and most seem wrong) would be:
call setBadgeIdentifier:forURL from another application that is aware of the change
Launch a thread in the init function of my extension which listens for notifications and calls setBadgeIdentifier:forURL when it receives them
Call some OS API that prompts Finder that the extension should be triggered via requestBadgeIdentifierForURL.
Only the last one seems feasible, and could be managed via the extension informing the outside resource what needs refreshing via the beginObservingDirectoryAtURL/endObservingDirectoryAtURL callbacks, but i don't know what mechanism could do this.

Easy Core Data migration during early development, when Data Loss is expected and acceptable

When a Core Data app is in early development, its Managed Object Model is often in constant flux. For each build, new Managed Objects and properties are added or deleted from the model.
When the Managed Object Model changes, the app will crash on next run with the error:
The model used to open the store is incompatible with the one used to create the store
The common advice in this situation is to delete the app from your device/simulator and re-run.
This works fine for developers using Xcode, but is annoying for non-technical stakeholders involved in the release process. It would be much preferable to not explain to the CEO or QA team that they must delete the app before installing that update from TestFlight. Or to field crashing bugs caused by this issue.
Once the models have been finalized a bit, we'll implement a real Core Data migration strategy.
In this dev phase, data loss is acceptable and expected.
This method will be removed before the app is released.
What's the easiest, lightweight, removable, debug way to "migrate" changes to the Managed Object Model between releases? This will likely be equivalent to "delete the app and re-run", but without needing to manually delete the app.
This should handle any and all changes to the Core Data stack, including adding and deleting Managed Objects and Properties.
In this scenario, I would check compatibility against the current model and then delete the SQLite database if a migration would have been required.
Consider using (in Objective-C)
// error, sourceStoreURL, theManagedObjectModel are valid
NSDictionary *storeMetadata=[NSPersistentStoreCoordinator metadataForPersistentStoreOfType: NSSQLiteStoreType
URL: sourceStoreURL error: &error];
BOOL storeIsCurrent=[theManagedObjectModel isConfiguration: nil
compatibleWithStoreMetadata: storeMetadata];
if (!storeIsCurrent)
{
// Alert user
// Delete on-disk store via sourceStoreURL
// (including -wal and -shm files if journaling enabled)
}
You can change the store URL when you change the model.
You can also do model versioning even for early development and then delete them all before you ship. This can also help your team learn the ins and outs of model versioning.

How to add information to Glimpse after EndRequest?

I'm the maintainer of the Miniprofiler Glimpse plugin and with the latest Miniprofiler versions I'm not able to push data to Glimpse because the Profiler is not yet populated (in previous versions it was) when the GetData() method of the tab is called.
Right now what I do is wrap the Miniprofiler Storage and when the Save() method is called, all the needed information is there but it's too late and I don't know how to send it to the tab.
So, what is the best approach (if possible) to add this information to a tab when it's ready in Miniprofiler?
Unfortunately EndRequest is currently the last moment you can subscribe on to return the necessary data. That is the moment when Glimpse will finalize its monitoring for the given request and the moment it will persist that information to the persistence store.
Although in v1 it is possible to add data after the EndRequest but only when using the default in memory store. So you could return your wrapper, which will be empty at that moment, and it will be stored in memory, allowing you to change the wrapped content afterwards.
But the above will not work for other persistence stores. We might also change this in v2 to make it deterministic, independent of the persistence store being used.
Maybe you could have your wrapper ask MiniProfiler to calculate the results at that moment, so they can be stored, even though those results might not be 100% complete?

Marking a view as "busy" in Cocoa

I'm writing a Cocoa app, and I need to indicate to the user that a view is invalid and can't respond until a background job is completed.
Longer version:
A view in my app contains some data fetched from a server. When the app determines that the data is invalid, it fetches fresh information and displays it. Usually the update happens too quickly to see, but if server or network problems cause the background job to take more than a second or two, I need to make sure the user
Cannot interact with the view until the job is finished;
Can tell that the view is awaiting an update; and
Can continue to interact with other parts of the application until the job is finished.
1) is important because any operation initiated with the stale data will fail, and if the network or the server is slow, I don't want the user to waste his time with futile attempts to interact with that part of the application. (It's fine if the user can still see the data. That could conceivably be helpful, actually, but it isn't crucial.)
What is the standard way to do this in Cocoa? For what it's worth, in the Eclipse framework I think I used the showBusy method on ViewPart.
If there isn't a standard way, does anyone have any suggestions for tackling it? I haven't been using OS X very long, so I'm not even sure how an app is supposed to look and behave in this situtaion. (The screenshots on this page looking promising, but it's iOS, not OS X: http://cocoawithlove.com/2009/04/showing-message-over-iphone-keyboard.html)
Right now I'm working on replacing the whole view with an NSProgressIndicator and restoring the view after the task finishes, but removing the view means my app could end up in a funky state if something goes wrong. Also, I'd like to be able to factor this functionality out into its own class or category(?) since I will have this issue with several different view classes in my application. Ideally I'd like to end up with something as simple as Eclipse's view.showBusy(true)/view.showBusy(false).
Any and all help would be appreciated.
Thanks!
Why not just draw another view on top of the busy view? You could either have it display an image that means busy, or draw it as semitransparent, so it shades out the before-update version of the busy view.

MACOSX - When calling -finishSyncing on an ISyncSessionDriver the app makes repeated calls to the delegate

I'm using Sync Services in my application. I'm using the normal way of getting the contacts from the address book (using sync services).
I want to prematurely end a sync session if the user decides to do that, therefore, when the user presses the "cancel" button, I make a call to [driver finishSyncing]
Attached to the ISyncSessionDriver is a delegate which deals with delegate methods typical of a sync session. One of those methods is - (BOOL)sessionDriver:(ISyncSessionDriver *)sender willFinishSessionAndReturnError:(NSError **)outError
The problem is that when calling finishSyncing, the sessionDriver:willFinishSessionAndReturnError: gets repeatedly called, not just once, but hunderds of times. Eventually it will throw an error.
So, how could I fix this, or what better debugging can I do to figure out what the problem is?
Thanks
Use instead - (void)cancelSyncing.
Make sure to release the receiver soon afterward because you cannot continue using a canceled session.

Resources