Search code examples
iosobjective-cuitableviewmagicalrecord

UItableView with MagicalRecord huge data set


I have a table that stores some data. Let's say data is too big to load into memory all at once. I want to show this data in UItableView.

-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
   return 1;
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
   return  [Item MR_numberOfEntities];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];


// How to get object for this row ???


return cell;

}

The only way i knew is to load all data into array with

NSArray *items = [Item MR_findAll];

But i don't want to do that. User will be shown first 10 rows, and why should i load all them from CoreData. Is there any way to fetch them one by one using MagicalRecord?


Solution

  • According to docs you need to init fetch request and also you may want to set the fetch offset depending on scroll progress.. but you will have to trace it manually. Here is a basic approach how it can be achieved. PS. I haven't tested this code . I just wrote it in the text editor :). but it should work as you requested. e.g loading items with limit 10.

        @property (nonatomic) int itemCount;
    
        @property (nonatomic, strong)  NSMutableArray * items 
    
        static const int FETCH_LIMIT = 10;
    
    
           -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
           {
            return  _itemCount;
           }
    
            - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
            {
                // Classic start method
                static NSString *cellIdentifier = @"MyCell";
                MyCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
                if (!cell)
                {
                    cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainMenuCellIdentifier];
                }
    
                MyData *data = [self.itemsArray objectAtIndex:indexPath.row];
                // Do your cell customisation
                // cell.titleLabel.text = data.title;
    
                if (indexPath.row == _itemCount - 1)
                {
                    [self loadMoreItems];
                }
            }
    
        -(void)loadMoreItems{
    
          int newOffset = _itemCount+FETCH_LIMIT; // Or _itemCount+FETCH_LIMIT+1 not tested yet
    
          NSArray * newItems = [self requestWithOffset: newOffset];
    
         if(!newItems || newItems.count == 0){
    
            // Return nothing since All items have been fetched
    
           return;
         }
    
          [ _items addObjectsFromArray:newItems ];
        // Updating Item Count
          _itemCount = _items.count;
    
        // Updating TableView
           [tableView reloadData];
        }
    
        -(void)viewDidLoad{
    
         [super viewDidLoad];
              _items = [self requestWithOffset: 0];
              _itemCount =  items.count;
        }
    
        -(NSArray*)requestWithOffset: (int)offset{
    
              NSFetchRequest *itemRequest = [Item MR_requestAll];
              [itemRequest setFetchLimit:FETCH_LIMIT]
              [itemRequest setFetchOffset: offset]
              NSArray *items = [Item MR_executeFetchRequest:itemRequest];
           return items;
        } 
    

    Hope you find it helpful :)