I have a subclass of UIDocument called Song that I use for storing users' content locally. The main reason I'm using UIDocument is for the autosaving feature.
I have an issue where after autosaving a document, -[Song revertToContentsOfURL:]
is called. This causes the document to load from disk again. The data is up-to-date, but other properties get reset as my app thinks that I am opening a new document. I could use a flag to check if the document is already open and not reset the relevant properties, but I would rather prevent revertToContentsOfURL:
from being called in the first place.
Note: this doesn't always happen. It seems that when a new document is created on the first launch of the app, it will call revertToContentsOfURL:
after each autosave, but on subsequent runs the autosave performs as expected. This could just be a coincidence though.
Here is the relevant code:
Song.h
typedef NS_OPTIONS(NSUInteger, ChangeFlag) {
ChangeFlagNone = 0,
ChangeFlagPaths = 1 << 0,
ChangeFlagInstruments = 1 << 1,
ChangeFlagColors = 1 << 2,
ChangeFlagProperites = 1 << 3,
ChangeFlagMixer = 1 << 4,
ChangeFlagTools = 1 << 5,
ChangeFlagScreenshot = 1 << 6,
ChangeFlagAll = ~ChangeFlagNone
};
@interface Song : UIDocument
@property (nonatomic) ChangeFlag changes;
- (void)addChange:(ChangeFlag)change;
- (void)removeChange:(ChangeFlag)change;
@end
Song.m
#import "Song.h"
@implementation Song
- (void)addChange:(ChangeFlag)change {
self.changes |= change;
}
- (void)removeChange:(ChangeFlag)change {
self.changes &= ~change;
}
- (void)setChanges:(ChangeFlag)changes
{
_changes = changes;
dispatch_async(dispatch_get_main_queue(), ^{
if (_changes == ChangeFlagNone) {
[self updateChangeCount:UIDocumentChangeCleared];
} else {
[self updateChangeCount:UIDocumentChangeDone];
}
});
}
- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
// populate various app properties
// -[Song addChange:] will be called multiple times
// ...
// clear changes (called directly instead of through setChange to avoid async)
_changes = ChangeFlagNone;
[self updateChangeCount:UIDocumentChangeCleared];
return YES;
}
- (id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
NSFileWrapper *rootDirectory = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
// store current changes value before clearing
ChangeFlag changes = _changes;
// clear changes (called directly instead of through setChange to avoid async)
_changes = ChangeFlagNone;
[self updateChangeCount:UIDocumentChangeCleared];
// update various file wrappers in rootDirectory, based on flags in `changes` variable
// ...
return self.rootDirectory;
}
@end