2015-08-24 57 views
0

使用API​​我得到500張圖片,並以異步方式上傳。然後我想將所有這些圖片保存在CoreData中,但由於內存不足導致應用程序崩潰。上傳許多文件並保存在CoreData中

當上傳完成後我調用方法createFromBlock

+(id)createFromBlock:(MRBlock *)block{ 
    ManagedBlock *item = [ManagedBlock MR_createInContext:DefaultContext]; 
    item.id = @(block.id); 
    item.name = block.name; 
    item.slidesInBlock = @(block.slidesInBlock); 

    item.sizeBlock = block.sizeBlock; 
    item.desc = block.desc; 
    item.imagePath = block.imagePath; 
    item.image = [MRUtils transformedValue:block.image]; 
    item.price = block.price; 
    int i = 0; 
    ManagedItem *new = nil; 
    for (MRItem *lol in block.items){ 
     NSLog(@"%i", i); 
         new = [ManagedItem createFromItem:lol]; 
       new.block = item; 
       [item addItemsObject:new]; 
     new = nil; 
     i++; 
    } 

    [DefaultContext MR_saveWithOptions:MRSaveSynchronously completion:nil]; 

    return item; 
} 

在的foreach block.items應用的崩潰。大約在150-160個職位之後。

如果我評論new = [ManagedItem createFromItem:lol]; - 應用程序不崩潰

+(id)createFromItem:(MRItem *)object{ 
    ManagedItem *item = [ManagedItem MR_createInContext:DefaultContext]; 
    item.id = @(object.id); 
    item.title = object.title; 
    item.detail = object.detail; 
    item.imagePath = object.imagePath; 
    item.image = [MRUtils transformedValue:object.image]; 
    return item; 
} 
+2

你是否在某種批次中這樣做?或者只是一次 - 500個在一個循環中? –

+0

Grzegorz Krukowski,只需一次 - 500個在一個循環中 – user1771125

回答

0

首先,你應該不會加載所有數據,然後保存。您應該小批量加載,並保存每批。

但是,對於您的具體示例,我相信您可以在保存後將每個對象轉換爲故障。

我從來沒有使用過神奇的記錄,也不知道它是否會允許你在不調用它的方法的情況下執行某些事情。我只看了一次,但它爲我隱藏了太多的細節......除非你正在做最基本的事情,否則核心數據可能非常複雜,我想知道我的核心數據代碼正在發生的一切。

+(id)createFromBlock:(MRBlock *)block{ 
    @autoreleasepool { 
    ManagedBlock *item = [ManagedBlock MR_createInContext:DefaultContext]; 
    item.id = @(block.id); 
    item.name = block.name; 
    item.slidesInBlock = @(block.slidesInBlock); 

    item.sizeBlock = block.sizeBlock; 
    item.desc = block.desc; 
    item.imagePath = block.imagePath; 
    item.image = [MRUtils transformedValue:block.image]; 
    item.price = block.price; 

    NSUInteger const batchSize = 10; 
    NSUInteger count = block.items.count; 
    NSUInteger index = 0; 
    while (index < count) { 
     @autoreleasepool { 
     NSMutableArray *newObjects = [NSMutableArray array]; 
     for (NSUInteger batchIndex = 0; 
      index < count && batchIndex < batchSize; 
      ++index, ++batchIndex) { 
      MRItem *lol = [block.items objectAtIndex:index]; 
      ManagedItem *new = [ManagedItem createFromItem:lol]; 
      new.block = item; 
      [item addItemsObject:new]; 
      [newObjects addObject:new]; 
     } 
     [DefaultContext MR_saveWithOptions:MRSaveSynchronously completion:nil]; 
     for (NSManagedObject *object in newObjects) { 
      // Don't know if MagicalRecord will like this or not... 
      [DefaultContext refreshObject:object mergeChanges:NO]; 
     } 
     } 
    } 

    return item; 
} 

基本上,該代碼一次處理10個對象。當批處理完成時,上下文被保存,然後將這10個對象轉換成錯誤,釋放它們所持有的內存。自動釋放池確保在範圍退出時釋放包含範圍中創建的任何對象。如果沒有其他對象在對象上保留保留,則它們將被釋放。

這是處理核心數據中大量數據或大型對象時的一個關鍵概念。此外,瞭解@autoreleasepool是非常重要的,儘管從未使用過MRR的人不讚賞它的好處。

順便說一句,我只是把它輸入編輯器,所以不要指望它編譯和運行一個簡單的複製/粘貼。