我按照上面贾斯汀的建议做了。在我的一个应用程序中运行良好两年,有大约 2 万用户。
@interface SharedUIManagedDocument ()
@property (nonatomic)BOOL preparingDocument;
@end
- (void)performWithDocument:(OnDocumentReady)onDocumentReady
{
void (^OnDocumentDidLoad)(BOOL) = ^(BOOL success) {
onDocumentReady(self.document);
self.preparingDocument = NO; // release in completion handler
};
if(!self.preparingDocument) {
self.preparingDocument = YES; // "lock", so no one else enter here
if(![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]]) {
[self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:OnDocumentDidLoad];
} else if (self.document.documentState == UIDocumentStateClosed) {
[self.document openWithCompletionHandler:OnDocumentDidLoad];
} else if (self.document.documentState == UIDocumentStateNormal) {
OnDocumentDidLoad(YES);
}
} else {
// try until document is ready (opened or created by some other call)
[self performSelector:@selector(performWithDocument:) withObject:onDocumentReady afterDelay:0.5];
}
}
斯威夫特(没有太多测试)
typealias OnDocumentReady = (UIManagedDocument) ->()
class SharedManagedDocument {
private let document: UIManagedDocument
private var preparingDocument: Bool
static let sharedDocument = SharedManagedDocument()
init() {
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let documentsDirectory: NSURL = urls.first as! NSURL
let databaseURL = documentsDirectory.URLByAppendingPathComponent(".database")
document = UIManagedDocument(fileURL: databaseURL)
let options = [NSMigratePersistentStoresAutomaticallyOption : true, NSInferMappingModelAutomaticallyOption : true]
document.persistentStoreOptions = options
preparingDocument = false
}
func performWithDocument(onDocumentReady: OnDocumentReady) {
let onDocumentDidLoad:(Bool) ->() = {
success in
onDocumentReady(self.document)
self.preparingDocument = false
}
if !preparingDocument {
preparingDocument = true
if !NSFileManager.defaultManager().fileExistsAtPath(document.fileURL.path!) {
println("Saving document for first time")
document.saveToURL(document.fileURL, forSaveOperation: .ForCreating, completionHandler: onDocumentDidLoad)
} else if document.documentState == .Closed {
println("Document closed, opening...")
document.openWithCompletionHandler(onDocumentDidLoad)
} else if document.documentState == .Normal {
println("Opening document...")
onDocumentDidLoad(true)
} else if document.documentState == .SavingError {
println("Document saving error")
} else if document.documentState == .EditingDisabled {
println("Document editing disabled")
}
} else {
// wait until document is ready (opened or created by some other call)
println("Delaying...")
delay(0.5, closure: {
self.performWithDocument(onDocumentReady)
})
}
}
private func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
}