数据版本控制、迁移与表格视图管理
立即解锁
发布时间: 2025-08-13 02:46:29 阅读量: 4 订阅数: 10 

### 数据版本控制、迁移与表格视图管理
#### 1. 数据迁移操作
在数据迁移的最后一步,需要将自定义类设置为负责执行迁移的管理器。具体操作如下:
1. 在 `ShapesAppDelegate.m` 文件顶部添加 `MyMigrationManager.h` 的导入语句。
2. 再次编辑 `persistentStoreCoordinator` 方法,代码如下:
```objc
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory]
URLByAppendingPathComponent:@"Shapes.sqlite"];
NSURL *newStoreURL = [[self applicationDocumentsDirectory]
URLByAppendingPathComponent:@"Shapes-Temp.sqlite"];
NSError *error = nil;
NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator
metadataForPersistentStoreOfType:NSSQLiteStoreType URL:storeURL error:&error];
if(sourceMetadata != nil) {
}
NSManagedObjectModel *destinationModel = [self managedObjectModel];
BOOL pscCompatible = [destinationModel isConfiguration:nil
compatibleWithStoreMetadata:sourceMetadata];
if(!pscCompatible) {
NSLog(@"Migration is needed");
// Migration is needed
NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:nil
forStoreMetadata:sourceMetadata];
MyMigrationManager *migrationManager = [[MyMigrationManager alloc]
initWithSourceModel:sourceModel destinationModel:destinationModel];
NSMappingModel *mappingModel = [NSMappingModel
inferredMappingModelForSourceModel:sourceModel destinationModel:destinationModel
error:&error];
if(mappingModel == nil) {
NSLog(@"Could not find a mapping model");
abort();
}
if(![migrationManager migrateStoreFromURL:storeURL
type:NSSQLiteStoreType
options:nil
withMappingModel:mappingModel
toDestinationURL:newStoreURL
destinationType:NSSQLiteStoreType
destinationOptions:nil
error:&error]) {
// Deal with error
NSLog(@"Error migrating %@, %@", error, [error userInfo]);
abort();
}
// Replace the old store with the new one now that it's migrated
NSFileManager *fm = [NSFileManager defaultManager];
NSURL *backupURL = [[self applicationDocumentsDirectory]
URLByAppendingPathComponent:@"Shapes-old.sqlite"];
if(![fm moveItemAtURL:storeURL toURL:backupURL error:&error]) {
NSLog(@"Error backing up the store");
abort();
}
else if(![fm moveItemAtURL:newStoreURL toURL:storeURL error:&error]) {
NSLog(@"Error putting the new store in place");
abort();
}
else if(![fm removeItemAtURL:backupURL error:&error]) {
NSLog(@"Error getting rid of the old store");
}
}
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:destinationModel];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
```
需要注意的是,源存储和目标存储的 URL 必须不同,这样迁移才能正常运行。迁移成功后,需要使用 `NSFileManager` 类直接移动 SQLite 文件来清理旧的数据存储。最后运行应用程序执行自定义迁移,并使用 `sqlite3` 命令行验证数据存储是否包含正确的数据。
以下是数据迁移的流程图:
```mermaid
graph TD;
A[开始] --> B[检查源存储元数据];
B --> C{是否需要迁移};
C -- 是 --> D[创建迁移管理器];
C -- 否 --> E[直接初始化持久存储协调器];
D --> F[获取映射模型];
F --> G{映射模型是否存在};
G -- 是 --> H[执行迁移];
G -- 否 --> I[输出错误并终止];
H --> J[备份旧存储];
J --> K[替换旧存储为新存储];
K --> L[删除备份存储];
L --> E;
E --> M[返回持久存储协调器];
M --> N[结束];
```
#### 2. 理解 `NSFetchedResultsController`
`NSFetchedResultsController` 类将 Core Data 结果与表格视图相结合,它可以从持久存储中提取指定实体的托管对象,进行缓存以提高性能,并根据需要将数据提供给表格视图。创建 `NSFetchedResultsController` 需要以下四个参数:
| 参数 | 说明 |
| ---- | ---- |
| 提取请求(`NSFetchRequest` 实例) | 与之前使用的提取请求类似,但必须至少有一个排序描述符,以确保数据按可预测的顺序排列。 |
| 托管对象上下文 | 用于保存托管对象的正常上下文,通常使用应用程序的托管对象上下文。 |
| 节名称键路径 | 指定一个键路径,将提取请求实体的托管对象划分为表格视图的节。如果指定了该参数,提取请求必须按该值排序。 |
| 缓存名称 | 为 `NSFetchedResultsController` 用于缓存托管对象的缓存指定一个名称,从 iOS 4.0 开始,缓存名称必须唯一。 |
#### 3. `NSFetchedResultsController` 代理方法
`NSFetchedResultsController` 使用 `NSFetchedResultsControllerDelegate` 代理来实现关键方法,使表格视图和提取结果控制器协同工作。代理有以下四个处理表格数据更改的方法:
- `controllerWillChangeContent:`:当某些内容即将更改时调用,可在此处通知表格视图开始一系列更改。
- `controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:`:当托管对象更改(添加、删除、编辑或移动)时调用,根据更改类型更新表格行。
- `controller:didChangeSection:atIndex:forChangeType:`:当节更改(添加或删除)时调用,相应地插入或删除表格中的节。
- `controllerDidChangeContent:`:当更改完成时调用,通知表格视图更改已完成。
通过实现这些方法并将代理设置为视图控制器,可以更好地管理表格视图中的数据变化。
#### 4. 在 `League Manager` 中实现 `NSFetchedResultsController`
为了更好地理解 `NSFetchedResultsController` 的使用,下面将在 `League Manager` 应用程序中添加一个新的全球员视图。具体步骤如下:
1. **复制应用程序**:复制 `League Manager` 应用程序,并确保其能正常构建和运行。
2. **更改视图为标签栏视图**:打开 `League_ManagerAppDelegate.m` 文件,修改 `application:didFinishLaunchingWithOpt
0
0
复制全文
相关推荐









