2

我一直在开发一个应用程序,用户每天输入存储在核心数据中的数据(两个属性 anNSNumber和一个 as NSDate),我想通过允许用户从外部文件(如 csv 或任何其他支持的格式)导入数据来改进它通过单击按钮。关于如何有效地做到这一点的任何建议?

谢谢你。

编辑: 只需添加 csv 文件的屏幕截图以及 csv 解析器的输出作为 NSArray。基本上需要单独获取属性并在按钮单击时将它们存储在核心数据中。

- 输入文件为 csv:

在此处输入图像描述

- 示例 csv 解析器输出(NSarray):

在此处输入图像描述

4

3 回答 3

2

我最近需要实现类似的目标。

我项目团队的几个成员想把我们的应用原型拿出来展示给潜在客户,但想向每个客户展示不同的数据。我们通过允许我们的项目团队成员在与客户会面之前创建自己的测试数据来解决这个问题。

我通过创建一个示例 .csv 文件并将其分发给项目团队中的其他人来实现这一点。他们用自己的测试数据填充它,并使用 iTunes 文件共享将 .csv 测试数据文件放到设备上。

加载时,应用程序会扫描其 Documents 目录以查找测试数据文件。如果存在,它会解析 .csv 文件并保存到数据库中。

对于 CSV 解析,我使用了 Dave DeLong 的 CHCSVParser:https ://github.com/davedelong/CHCSVParser

在为您的应用程序设置 iTunes 文件共享方面提供了大量帮助。一个快速的谷歌发现这个教程(http://www.raywenderlich.com/1948/how-integrate-itunes-file-sharing-with-your-ios-app)应该可以帮助你,如果你需要它。

编辑 - 添加了有关在 Core Data 中存储 .csv 数据的帮助

您在原始帖子中声明您存储了一个 NSNumber 和 NSDate。以此为起点,您可能有一个 .csv 文件,格式如下:

+----------------+--------------+
+ NSNumberColumn | NSDateColumn |
+----------------+--------------+
+        1       |  2013-05-15  |
+        2       |  2013-06-15  |
+        3       |  2013-07-15  |
+----------------+--------------+

假设 CSV 解析器的输出是 NSArray 的 NSArray,您可以按如下方式创建 Core Data 对象:

我会为列号创建几个宏:

#define NSNumberColumn 0
#define NSDateColumn 1

然后遍历 .csv 文件中的行:

NSArray *rows = [NSArray arrayWithContentsOfCSVFile:pathToFile]; //CHCSVParser specific parsing method
for (NSArray *row in rows)
{
    NSString *numberString = [parsedCsvRow objectAtIndex:NSNumberColumn];
    NSString *dateString = [parsedCsvRow objectAtIndex:NSDateColumn];   

    NSNumber *number = // parse numberString to an NSNumber. Plenty of other posts on achieving this. 
    NSDate *date = // parse NSDate from dateString. Plenty of other posts on achieving this.

    NSManagedObjectContext *context = [self managedObjectContext];
    NSManagedObject *myCoreDataObject = [NSEntityDescription insertNewObjectForEntityForName:@"MyCoreDataObject" inManagedObjectContext:context];
    [myCoreDataObject setValue:number forKey:@"NSNumberColumn"];
    [myCoreDataObject setValue:date forKey:@"NSDateColumn"];
    NSError *error;
    if (![context save:&error]) {
        NSLog(@"%@", [error localizedDescription]);
    }
}

注意:为简洁起见,省略了输入验证和空值检查。我还冒昧地编造了您的 NSManagedObject 属性名称,这需要更新。上面的代码应该被分成更合适的类结构。

我现在不在 Mac 上,所以很遗憾我无法检查这是否有效。

希望有帮助。

于 2013-07-12T11:59:55.953 回答
0

尝试使用 plist 或 json,iOS 已经支持它们而不是 CSV。CSV 需要第三方解析器。使用 json 或 plist 你只需要遍历集合的元素来创建你的持久存储。如果您只有 CSV,您可以使用不同的免费工具进行中间转换,这些工具可以在 Internet 上免费找到,然后添加到您的捆绑包或发布到您的网站。

于 2013-07-12T11:21:36.650 回答
0

当您已经解析了 CSV 文件并且数据已准备好在 Objective-C 中使用时,您会执行以下操作。

  1. 为导入创建单独的上下文。您不知道数据有多大,因此您可能不想在导入时阻止现有上下文之一。

  2. 遍历解析数据中的条目并插入从每个条目配置的新托管对象。

  3. 每 200、500 或 1000 个条目(每个人都不同,您需要测试什么最适合您)保存上下文,并在需要时发布一个批次已导入的通知。

  4. 要保持低内存,请重置上下文并忘记您在此导入上下文中创建的所有对象。

  5. 循环结束后,不要忘记保存最后一次。

现在如何将数据带入另一个上下文,比如 UI 上下文?

这取决于您组织核心数据堆栈的方式。例如,导入上下文可以配置为 UI 上下文的子项。在这种情况下,每次保存到导入上下文后,更改将被推送到 UI 上下文(并且不要忘记保存 UI 上下文以进一步推送更改)。

但这不是最有效的方法,因为 UI 上下文是主线程上的上下文,它参与了导入,并且在阻塞它的 UI 线程上完成了额外的工作。我建议不要创建导入上下文,而是直接连接到持久存储协调器。在这种情况下,要对 UI 上下文进行更改,您需要mergeChangesFromContextDidSaveNotification:在每次保存后调用方法,或者您只需在每次保存后重新获取 UI 上下文并结束。后者在 UI 上下文上更容易,特别是在 NSFetchedResultsController 上,如果你使用它,因为它不需要一个一个地重放对更新对象的更改。

于 2013-07-12T12:20:39.550 回答