#ios #objective-c #sqlite #core-data #core
#iOS #objective-c #sqlite #core-данные #Ядро
Вопрос:
Это код, который я использую для создания постоянного контейнера для основного стека данных.
Я хочу обработать случай сбоя, когда persistentContainer не равен нулю и уже загружен в общий класс экземпляра CoredataHandler.
Файл CoredataHandler.h
@property (strong, nonatomic) NSPersistentContainer *persistentContainer;
@property (nonatomic) BOOL isStoreLoaded;
Файл CoredataHandler.m
@implementation CoredataHandler
(CoredataHandler *) sharedInstance
{
static CoredataHandler *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(amp;onceToken, ^{
shared = [[self alloc] init];
});
return shared;
}
- (id)init {
if (self = [super init]) {
_persistentContainer = self.persistentContainer;
}
return self;
}
@synthesize persistentContainer = _persistentContainer;
- (NSPersistentContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
@synchronized (self) {
NSURL * storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
storeURL = [storeURL URLByAppendingPathComponent:@"MyDataBase"];
if (_persistentContainer == nil) {
NSPersistentContainer *container = [[NSPersistentContainer alloc] initWithName:@"MyDataBase"];
NSPersistentStoreDescription * persistentStoreDescription = [[NSPersistentStoreDescription alloc] initWithURL:storeURL];
persistentStoreDescription.shouldMigrateStoreAutomatically = YES;
[persistentStoreDescription setOption:NSFileProtectionComplete forKey:NSPersistentStoreFileProtectionKey];
persistentStoreDescription.shouldInferMappingModelAutomatically = YES;
container.persistentStoreDescriptions = @[persistentStoreDescription];
[container loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
//abort();
self->_isStoreLoaded = NO;
}
self->_isStoreLoaded = YES;
return;
}];
if (self.isStoreLoaded) {
_persistentContainer = container;
}
} else {
if (![self persistentStoreExistsWithStoreURL:storeURL]) {
_persistentContainer = nil;
}
}
}
return _persistentContainer;
}
Я попытался, проверив, существует ли хранилище в пути
-(BOOL)persistentStoreExistsWithStoreURL:(NSURL *)url {
if (url amp;amp;
url.isFileURL amp;amp;
[NSFileManager.defaultManager fileExistsAtPath:url.path]) {
return YES;
}
return NO;
}
-(NSBatchUpdateResult *)executeRequestForNSBatchUpdateResult:(NSBatchUpdateRequest *)updateRequest {
NSBatchUpdateResult *batchUpdateResult = nil;
if (!self.persistentContainer) {
return nil;
}
if (self.persistentContainer.viewContext) {
batchUpdateResult = (NSBatchUpdateResult *)[self.persistentContainer.viewContext executeRequest:updateRequest error:nil];
}
return batchUpdateResu<
}
@end
-(void)markItmesInCategory:(NSNumber*)categoryId {
NSBatchUpdateRequest *req= [[NSBatchUpdateRequest alloc] initWithEntityName:@"Items_table"];
req.predicate = [NSPredicate predicateWithFormat:@"categoryId=%d",[channelKey intValue]];
req.propertiesToUpdate = @{
@"status" : @(1)
};
req.resultType = NSUpdatedObjectsCountResultType;
CoredataHandler * dbHandler = [CoredataHandler sharedInstance];
NSError * fetchError = nil;
NSBatchUpdateResult *batchUpdateResult = (NSBatchUpdateResult *)[dbHandler executeRequestForNSBatchUpdateResult:req];
if (batchUpdateResult) {
NSLog(@"updated rows", batchUpdateResult.result);
}
}
Как справиться со случаем, если его уже загруженный объект находится в общем классе экземпляра и если хранилище имеет некоторые проблемы с разрешениями при доступе
Пример: постоянное хранилище недоступно из-за разрешений или защиты данных, когда устройство заблокировано.
Комментарии:
1. Когда и где в вашем коде вы хотите это проверить?
CoredataHandler
инициализируется только один раз при обращении к нему, поэтому, когда может возникнуть «случай сбоя, когда persistentContainer не равен нулю и уже загружен в общий класс экземпляра CoredataHandler»?2. Я хотел проверить в CoredataHandler при доступе к методу persistentContainer в другой части, доступно ли основное хранилище данных или нет, чтобы я мог справиться, если хранилище недоступно, когда телефон заблокирован в случае NSFileProtectionComplete