Вопрос

I have the following subclassed managed objects loaded into arrays when the view loads.

@class Aircraft;

@interface AircraftTypes : NSManagedObject

@property (nonatomic, retain) NSNumber * isIFRCapable;
@property (nonatomic, retain) NSString * model;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * numEngines;
@property (nonatomic, retain) NSString * type;
@property (nonatomic, retain) Aircraft *tailNumber;
@property (nonatomic, retain) NSNumber *sortOrder;
@end

and

@class AircraftTypes;

@interface Aircraft : NSManagedObject

@property (nonatomic, retain) NSString * homeStation;
@property (nonatomic, retain) NSNumber * isSimulator;
@property (nonatomic, retain) NSString * owner;
@property (nonatomic, retain) NSString * tailNumber;
@property (nonatomic, retain) AircraftTypes *aircraftType;
@property (nonatomic, retain) NSManagedObject *loggedFlights;

@end

The relationship is

AircraftTypes <--->> Aircraft

I can and have been successfully playing with child objects within a relationship in UITableView cells and segueing to edit them. What I want to do is figure out how to successfully create UITableView sections based on the AircraftType and populate each section with aircraft that belong to that type as well as successfully reference the original Array(index) depending on which rows are deleted. This is what I have so far, but I am stuck.

Get the arrays:

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated];

self.managedObjectContext = [(ATPAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
managedObjectContext = self.managedObjectContext;

self.aircraftList = [CoreDataHelper getObjectsForEntity:@"Aircraft" withSortKey:@"tailNumber" andSortAscending:YES andContext:self.managedObjectContext];
self.aircraftTypeList = [CoreDataHelper getObjectsForEntity:@"AircraftTypes" withSortKey:@"sortOrder" andSortAscending:YES andContext:self.managedObjectContext];   
}

Load the data (this entire block works so far):

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [aircraftTypeList count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    // return the title of an individual category
AircraftTypes *thisType = [self.aircraftTypeList objectAtIndex:section];

return [NSString stringWithFormat:@"%@ %@", thisType.type, thisType.model];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

AircraftTypes *thisType = [aircraftTypeList objectAtIndex:section];
int count = 0;

for (Aircraft *thisAircraft in self.aircraftList) {
    if (thisAircraft.aircraftType == thisType) {
        count++;
    }
}

if (self.editing) { //Add insert row
    count++;
}

return count;

}

This one is causing errors, I did preload some data into the stack and saved successfully during applicationDidFinishLaunchingWithOptions

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"AircraftCell";
ATPSettingsMyAircraftTableCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

if (cell == Nil) {
    cell = [[ATPSettingsMyAircraftTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: cellIdentifier];
}

AircraftTypes *thisType = [aircraftTypeList objectAtIndex:indexPath.section];

cell.labelTailNumber.text = thisType.tailNumber.tailNumber;
cell.labelHomeStation.text = thisType.tailNumber.homeStation;
cell.labelAircraftModel.text = [NSString stringWithFormat:@"%@ %@",
                                thisType.type, thisType.model];

cell.labelHours.text = @"";
    //calcuate aircraft hours later

return cell;
}

And I don't even begin to know how to reference the correct object for commitEditingStyle. This is a snippet from another TableViewController that doesn't use sections and has a single array referencing my managedObject, so I need to know what changes need to be made to this to reference the right object since I'm going to be dealing with indexPath.section and .row:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {

        // Ensure that if the user is editing a name field then the change is committed before deleting a row -- this ensures that changes are made to the correct event object.
    [tableView endEditing:YES];

        // Delete the managed object at the given index path.
    NSManagedObject *flightConditionList = (self.flightConditionList)[indexPath.row];
    [self.managedObjectContext deleteObject:flightConditionToDelete];

        // Update the array and table view.
    [self.flightConditionList removeObjectAtIndex:indexPath.row];
    [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

        // Commit the change.
    NSError *error;
    if (![self.managedObjectContext save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}
}

Thanks in advance if it's so easy a pilot could do it.

This is an edit, trying to go with the first answer. Not sure if I am doing it right to separate the entity into sections on the AircraftTypes entity, but I also need to name the section headers based on aircraftTypes.type and .model.

Trying it with the following code. Not sure if the sectionNameKeyPath is coded right for a relationship entity of type aircraftTypes. Also, I need the section headers to be labeled from two properties of the aircraftTypes entity Type and Model.

- (NSFetchedResultsController *) fetchedResultsController {
if (fetchedResultsController != nil) {
    return fetchedResultsController;
}

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Aircraft" inManagedObjectContext:self.managedObjectContext];

[fetchRequest setEntity:entity];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
                                    initWithKey:@"tailNumber" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

[fetchRequest setFetchBatchSize:20];

NSFetchedResultsController *theController = [[NSFetchedResultsController alloc]
                                             initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"aircraftType" cacheName:@"Master"];

self.fetchedResultsController = theController;

fetchedResultsController.delegate = self;

return fetchedResultsController;
}
Это было полезно?

Решение

The short answer is use NSFetchedResultsController.

A NSFetchedResultsController is the right choice to work with tables. In particular, it can be created with a sectionNameKeyPath that allows you to control sections.

Here the value sectionNameKeyPath can be your aircraftType.

Update 1

To have a working example on NSFetchedResultsController you can take a look to both NSFetchedResultsController Class Reference, sample code by Apple and Core Data Tutorial for iOS: How To Use NSFetchedResultsController.

Obviously, a NSFetchedResultsController is the right way to work with tables since

  • it allows to work with sections
  • it allows to lazy loading data using batch size and hence have a low memory footprint
  • it allows to react to modifications (add, remove, delete) to the entity registered with
  • etc.

A note is that when you work with NSFetchedResultsController and sections, you need to take in mind the following

If the controller generates sections, the first sort descriptor in the array is used to group the objects into sections; its key must either be the same as sectionNameKeyPath or the relative ordering using its key must match that using sectionNameKeyPath.

Другие советы

So I was able to solve this using your method with the fetchedResultsController, however, it required me redesigning the Data Model to combine the Type and Model of aircraft into one object. (Like the Make and Model of a car). It works, but if you can think of a way to get it to work with them being separate objects, that'd be great. Thanks for the help though!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top