iOS:如何使用下载的CSV填充核心数据

时间:2013-07-12 10:50:59

标签: iphone ios objective-c core-data file-upload

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

谢谢。

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

- 输入文件为csv:

enter image description here

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

enter image description here

3 个答案:

答案 0 :(得分: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),它可以帮助你,如果你需要它。

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

您在原始帖子中说明您存储了NSNumber和NSDate。以此为出发点,您可能会使用以下格式的.csv文件:

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

假设CSV解析器的输出是NSArrays的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,所以不幸的是我无法检查这是否有效。

希望有所帮助。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

以下是您已经解析了CSV文件并准备在Objective-C中使用数据时所执行的操作。

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

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

  3. 每200,600或1000个条目(每个人都不同,您需要测试哪种方法最适合您)保存上下文,并在需要时发布批量导入的通知。< / p>

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

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

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

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

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