Ios 将大量数据从coredata导出到json

Ios 将大量数据从coredata导出到json,ios,objective-c,json,core-data,export,Ios,Objective C,Json,Core Data,Export,我正在尝试将一些数据从核心数据导出到JSON。虽然记录数量不是特别大(大约5000-15000条记录),但我的数据模型很复杂,每个记录中都有大量数据,因此当我导出这些记录时,我超出了允许的内存,iOS会杀死我的应用程序 我目前采取的步骤是: 1。我有一个方法可以从cordata中提取所有数据,并将其存储在“NSDictionary”中。 2。然后,我使用“NSOutputStream”和“NSJSONSerialization”将其写入文件中 3。然后我压缩文件并通过电子邮件发送它 从最大内存的

我正在尝试将一些数据从核心数据导出到JSON。虽然记录数量不是特别大(大约5000-15000条记录),但我的数据模型很复杂,每个记录中都有大量数据,因此当我导出这些记录时,我超出了允许的内存,iOS会杀死我的应用程序

我目前采取的步骤是:

    1。我有一个方法可以从cordata中提取所有数据,并将其存储在“NSDictionary”中。
    2。然后,我使用“NSOutputStream”和“NSJSONSerialization”将其写入文件中
    3。然后我压缩文件并通过电子邮件发送它
从最大内存的角度来看,我非常确定步骤2和步骤3在流式传输数据时很好。但问题是,它在步骤1中被杀死,因为我正在有效地从CD中取出所有数据并将其放入内存,这样我就可以通过
NSOutputStream
将其传递到
NSJSONSerialization

有人知道如何不必将所有内容都拉入内存,但仍要写入一个树JSON文件吗

更新-更多详细信息
我的数据结构(为了澄清而简化)如下所示。 考虑到它不仅是一组扁平的记录,而且是一个具有关系的对象的层次结构,我不知道如何批量从核心数据中提取数据并将数据馈送到json拖缆,而不是全部在内存中构建json。我上面的第一步实际上是一组递归方法,这些方法从核心数据实体中提取数据并构建“NSDictionary”

Folder {
    Folder {
        Word {
            details type 1
            details type 2
        }
        Word {
            details type 1
            details type 2
        }
    }
    Folder {
        Word {
            details type 1
            details type 2
        }
        Word {
            details type 1
            details type 2
        }
    }
    Word {
        details type 1
        details type 2
    }
}

检查
NSFetchRequest
文档。您将看到两个属性:

- (NSUInteger)fetchOffset;
– fetchBatchSize;
使用这两个属性,您可以将返回的
NSManagedObject
s数量限制为给定的批大小

打开一个你也可以写的流。设置循环以执行提取请求。但是设置一个批处理大小(x),然后在循环代码的末尾为循环的下一次迭代更新获取请求的获取偏移量

myFetchRequestObject.fetchOffset += x;
在开始循环的下一次迭代之前,处理将JSON数据写入开放流的一批数据对象

myFetchRequestObject.fetchOffset += x;
如果没有返回更多对象,或者提取返回的对象数小于批大小,请退出循环


关闭流。

[更新以实现嵌套文件夹层次结构作为嵌套JSON对象文件的低内存串行输出]

现在您提供了更多的细节,很明显,原始问题陈述缺乏足够的细节,任何人都无法为您提供答案。您的问题实际上是一个由来已久的问题,即如何以内存高效的方式遍历层次结构,再加上iOS JSON库非常轻巧,并且不容易支持流式写入深层层次结构)

最好的方法是使用一种称为访问者模式的技术。对于上面显示的每个NSManagedObject类型,实现一个名为visitor的协议,例如,每个对象的接口行应如下所示:

@interface Folder : NSManagedObject <Visitable>

@interface Word : NSManagedObject <Visitable>
@接口文件夹:NSManagedObject
@接口字:NSManagedObject
访问者协议应该为符合协议的所有对象定义一个方法调用

@protocol Visitable <NSObject>

- (void)acceptVisitor:(id<Visitor>)visitor;

@end
@协议可访问
-(无效)接受访客:(id)访客;
@结束
您将定义一个visitor对象,它本身实现一个visitor协议

@protocol Visitor <NSObject>

- (void)visitFolder:(Folder*)folder;
- (void)visitWord:(Word*)word;

@end



@interface JSONVisitor : NSObject <Visitor>

@property (nonatomic, strong) NSURL *streamURL;

- (void)startVisiting:(id<Visitable>)visitableObject;

@end


@implementation JSONVisitor

@property (nonatomic, strong) NSOutputStream *outputStream;

- (void)startVisiting:(id<Visitable>)visitableObject
{
    if ([visitableObject respondsToSelector:@selector(acceptVisitor:)] 
    {
        if (_outputStream == nil) 
        {
            // more code required set up your output stream
            // specifically as a JSON output stream.

            // add code to either set the stream URL here, 
            // or set it when the visitor object is instantiated. 

           _outputStream = [NSOutputStream outputStreamWithURL:_streamURL append:YES];
        }

        [_outputStream open];

        // Note 1a Bypass Apple JSON API which doesn't support
        // writing of partial objects (doing so is very easy anyway).
        // Write opening root object fragment text string to stream
        // such as:

        // {
        //     "$schema" : "http://myschema.com/draft-01/schema#Folder1",
        //     "name" : "Folder export",
        //     "created" : "2013-07-16T19:20:30.45+01:00",
        //     "Folders" : [

        [visitableObject acceptVisitor:self];

        // Note 1b write closing JSON  root object
        // e.g. 

        //     ]
        // }

        [_outputStream close];

    }
}


- (void)visitFolder:(Folder*)folder
{

    // Note 2a Bypass Apple JSON API which doesn't appear to support
    // writing of partial objects (Writing JSON is very easy anyway).
    // This next step would be best done with a proper templating system,
    // but for simplicity of illustration I'm suggesting writing out raw
    // JSON object text fragments.

    // Write opening JSON Folder object fragment text string to stream
    // e.g. 

    // "Folder" : { 

    if ([folder.folders count] > 1) {

        // Write opening folder array fragment to stream e.g.

        // "Folders" : [


        // loop through folder member NSManagedObjects here 
        // (note defensive checks for nulls not included).

        NSUInteger count = 0;

        for (Folder *nestedFolder in folder.folders)
        {
           if (count > 0) // print comma to output stream
           [nestedFolder acceptVisitor:self];
           count++;
        }

        // write closing folders array to stream

        // ]
    }

    if ([folder.words count] > 1) {

        // Write opening words array fragment to stream e.g.

        // "Words" : [

        // loop through Word member NSManagedObjects here 
        // (note defensive checks for nulls not included).

        NSUInteger count = 0;

        for (Word *nestedWord in folder.words)
        {
           if (count > 0) // print comma to output stream
           [nestedFolder acceptVisitor:self];
           count++;
        }

        // write closing Words array to stream

        // ]
    }

    // Print closing Folder object brace to stream (should only be followed
    // a comma if there are more members in the folder this object is contained by)
    // e.g.

    // },

    // Note 2b Next object determination code here. 
}

- (void)visitWord:(Word*)word
{
    // Write to JSON stream

    [NSJSONSerialization writeJSONObject:word toStream:_outputStream options: NSJSONWritingPrettyPrinted error:nil];
}

@end
@协议访问者
-(无效)访问文件夹:(文件夹*)文件夹;
-(空)visitWord:(单词*)单词;
@结束
@接口JSONVisitor:NSObject
@属性(非原子,强)NSURL*streamURL;
-(void)开始浏览:(id)visitableObject;
@结束
@JSONVisitor的实现
@属性(非原子,强)NSOutputStream*outputStream;
-(无效)开始浏览:(id)visitableObject
{
if([visitableObject respondsToSelector:@selector(acceptVisitor:)]
{
if(_outputStream==nil)
{
//需要更多代码来设置输出流
//特别是作为JSON输出流。
//添加代码以在此处设置流URL,
//或者在实例化访问者对象时设置它。
_outputStream=[NSOutputStream outputStreamWithURL:\u streamURL append:YES];
}
[_outputstreamopen];
//注1绕过不支持的Apple JSON API
//编写部分对象(无论如何,这样做很容易)。
//将打开的根对象片段文本字符串写入流
//例如:
// {
//“$schema”:”http://myschema.com/draft-01/schema#Folder1",
//“名称”:“文件夹导出”,
//“已创建”:“2013-07-16T19:20:30.45+01:00”,
//“文件夹”:[
[visitableObject acceptVisitor:self];
//注1b写入结束JSON根对象
//例如。
//     ]
// }
[_outputstreamclose];
}
}
-(无效)访问文件夹:(文件夹*)文件夹
{
//注2a绕过苹果JSON API,该API似乎不支持
//编写部分对象(无论如何,编写JSON非常容易)。
//下一步最好使用合适的模板系统,
//但为了简单起见,我建议写下原始数据
//JSON对象文本片段。
//将打开的JSON文件夹对象片段文本字符串写入流
//例如。
//“文件夹”:{
如果([folder.folders count]>1){
//将打开的文件夹数组片段写入流,例如。
//“文件夹”:[
//在此处循环浏览文件夹成员NSManagedObjects
//(注意不包括对空值的防御检查)。
整数计数=0;
用于(文件夹*文件夹中的嵌套文件夹。文件夹)
{
if(count>0)//将逗号打印到输出流
[nestedFolder acceptVisitor:self];
计数++;
}
//将关闭文件夹数组写入流
// ]
}
如果([folder.words count]>1){
//将开始词数组片段写入流,例如。
//“文字”:[