0

過去 18 か月間、CoreData からデータのテーブルを正常に読み込んでいる単純なビューがあります。IOS 7 にアップグレードされたデバイスでも動作するようになりました。しかし、Xcode5 にアップグレードして IOS7 3.5 インチ Retina シミュレーターを実行すると、テーブルが常に空になります。以下にコードを貼り付けました。NSLog 出力でこれを確認できるため、fetchRequests がデータを返していることを確認できます。しかし、なぜテーブルがセルへの入力を停止したのでしょうか?

私はこれを理解できないので、本当にばかげていると感じます…</p>

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        NSLog(@"listData count in numberOFRowsInSection is: %i", listData.count);
        return [self.listData count];
    }

    - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
        Sessions *info = [_fetchedResultsController objectAtIndexPath:indexPath];
        NSLog(@"info content is: %@", info.sport);
        //Format cell data ready to be displayed
        NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
        [dateFormat setDateFormat:@"EE, dd LLL yyyy"];
        NSString *dateString = [dateFormat stringFromDate:info.date];

        NSNumber *dist1Nbr = info.dist1;
        int dist1Int = [dist1Nbr integerValue];
        float distIntKorM = ([dist1Nbr integerValue])/1000;
        NSString *dist1StrMeters = [[NSString alloc] initWithFormat:@"%i", dist1Int];
        NSString *dist1StrKorM = [[NSString alloc] initWithFormat:@"%.01f", distIntKorM];


        //Select image to display
        if ([info.sport isEqualToString:@"Run"]) {
            UIImage *image = [UIImage imageNamed:@"trainers-15x10.png"];
            cell.imageView.image = image;
            cell.textLabel.text = [[NSString alloc] initWithFormat:@"%@: (%@),", dateString, info.sport];
            cell.detailTextLabel.text = [[NSString alloc] initWithFormat:@"Type: %@,  Dist: %@", info.sessiontype, dist1StrKorM];
            NSLog(@"Cell text for Runs shoudl be: %@", cell.textLabel.text);
        } else if ([info.sport isEqualToString:@"Other"]) {
            UIImage *image = [UIImage imageNamed:@"weights-15x10.png"];
            cell.imageView.image = image;
            cell.textLabel.text = [[NSString alloc] initWithFormat:@"%@: (%@),", dateString, info.sport];
            cell.detailTextLabel.text = [[NSString alloc] initWithFormat:@"Type: %@,  Dist: %@", info.sessiontype, dist1StrKorM];
        } else if ([info.sport isEqualToString:@"Swim"]) {
            UIImage *image = [UIImage imageNamed:@"goggles-15x10.png"];
            cell.imageView.image = image;
            cell.textLabel.text = [[NSString alloc] initWithFormat:@"%@: (%@),", dateString, info.sport];
            cell.detailTextLabel.text = [[NSString alloc] initWithFormat:@"Type: %@,  Dist: %@m", info.sessiontype, dist1StrMeters];
            NSLog(@"Cell text for Swims shoudl be: %@", cell.textLabel.text);
        } else if ([info.sport isEqualToString:@"Cycle"]) {
            UIImage *image = [UIImage imageNamed:@"bike-15x10.png"];
            cell.imageView.image = image;
            cell.textLabel.text = [[NSString alloc] initWithFormat:@"%@: (%@),", dateString, info.sport];
            cell.detailTextLabel.text = [[NSString alloc] initWithFormat:@"Type: %@,  Dist: %@", info.sessiontype, dist1StrKorM];
        } else if ([info.sport isEqualToString:@"Brick"]) {
            UIImage *image = [UIImage imageNamed:@"brick-15x10.png"];
            cell.imageView.image = image;
            cell.textLabel.text = [[NSString alloc] initWithFormat:@"%@: (%@),", dateString, info.sport];
            cell.detailTextLabel.text = [[NSString alloc] initWithFormat:@"Type: %@,  Dist: %@", info.sessiontype, dist1StrKorM];
        }

    }

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

        static NSString *CellIdentifier = @"editSession";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

            }
            // this cell backgrond colour alternating works!
            UIView *bgColor = [cell viewWithTag:100];
            if (!bgColor) {
                CGRect frame = CGRectMake(0, 0, 320, 50);
                bgColor = [[UIView alloc] initWithFrame:frame];
                bgColor.tag = 100;
                [cell addSubview:bgColor];
                [cell sendSubviewToBack:bgColor];
            }

            if (indexPath.row % 2 == 0) {
                bgColor.backgroundColor = [UIColor colorWithRed:233.0/255.0 green:233.0/255.0 blue:233.0/255.0 alpha:1.0];
                    } else {
                        bgColor.backgroundColor = [UIColor clearColor];                                }

        [self configureCell:cell atIndexPath:indexPath];

        return cell;
    }


    - (id)initWithStyle:(UITableViewStyle)style
    {
        self = [super initWithStyle:style];
        if (self) {
            // Custom initialization
        }
        return self;
    }


    - (void)didReceiveMemoryWarning
    {
        // Releases the view if it doesn't have a superview.
        [super didReceiveMemoryWarning];

        // Release any cached data, images, etc that aren't in use.
    }

    #pragma mark - View lifecycle

    - (void)viewDidLoad
    {
        [super viewDidLoad];

        // Uncomment the following line to preserve selection between presentations.
        // self.clearsSelectionOnViewWillAppear = NO;

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem;
        if (_context == nil) 
        { 
            _context = [(SGK_T4T_01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
            NSLog(@"After managedObjectContext: %@",  _context);
        }

        NSError *error;
        if (![[self fetchedResultsController] performFetch:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            exit(-1);
        } else {
            NSLog(@"After fetchedResultsController: %@",  _fetchedResultsController);
            //NSLog(@"After managedObjectContext: %@",  _fetchedResultsController);
        }
        self.title = @"Sessions";


    }

    - (void)viewDidUnload
    {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;

        [self setListData:nil];
        [self setSelectedSession:nil];
        [self setSessionSport:nil];
        //[self setRecordCount:nil];
        [self setFetchedResultsController:nil];
        [self setContext:nil];
    }

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

        SGK_T4T_01AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
        NSManagedObjectContext *context = [appDelegate managedObjectContext];
        NSEntityDescription *entityDiscription = [NSEntityDescription entityForName:@"Sessions" inManagedObjectContext:context];
        //NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"refid" ascending:YES];
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        [request setEntity:entityDiscription];


        NSError *error;
        NSArray *objects = [context executeFetchRequest:request error:&error];
        if (objects == nil) {

            NSLog(@"The fetch request returned an array == nil");
        } else {
            NSLog(@"The fetch request returned an array!!!");
            NSLog(@"objects contents is: %@", objects);
            NSLog(@"objects count = %i", [objects count]);
            listData = objects;
            NSLog(@"listData count = %i", [listData count]);
            //NSUInteger *recordCount = [objects count];
            recordCount = [objects count];
        }

        //reload tableView:dataSource from CoreData when view reappears...
        if (_context == nil)
        {
            _context = [(SGK_T4T_01AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
            NSLog(@"After managedObjectContext: %@",  _context);
        }

        NSError *error1;
        if (![[self fetchedResultsController] performFetch:&error1]) {
            NSLog(@"Unresolved error %@, %@", error1, [error1 userInfo]);
            exit(-1);
        } else {
            NSLog(@"viewWillAppear: fetchedResultsController: %@",  _fetchedResultsController);
        }
        //end of reload tableView:dataSource from CoreData when view reappears...

        [self.tableView reloadData];
    }

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

    }

    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        //[self setFetchedResultsController:nil];
    }

    - (void)viewDidDisappear:(BOOL)animated
    {
        [super viewDidDisappear:animated];
        //[self setFetchedResultsController:nil];
    }

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        // Return YES for supported orientations
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }

    #pragma mark - Table view data source

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
    //#warning Potentially incomplete method implementation.
        // Return the number of sections.
        return 1;
    }

    /*
    // Override to support conditional editing of the table view.
    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // Return NO if you do not want the specified item to be editable.
        return YES;
    }
    */


    // Override to support editing the table view.
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            // Delete the row from the data source
            [_context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];

            NSError *error = nil;
            if (![_context save:&error]) {
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
                }
            } else if (editingStyle == UITableViewCellEditingStyleInsert) {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }
        [self.tableView reloadData];
    }

    - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
    {
        if (type == NSFetchedResultsChangeDelete) {
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        }
    }

    #pragma mark - Table view delegate

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {

    }

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
        NSUInteger index = indexPath.row;
        //NSLog(@" Prep4Seg indexPath.row = %u", index);
        //NSLog(@" Prep4Seg recordCount = %u", recordCount);
        /*
            Subtract the row index from the row count to get the correct position in the Array (because I am sorting on date order so tableCell position 0 is position 2 in the Array (if there are 3 only items in the table and array) so if you don't invert the indexPath you end up passing the last item instead of the first or second last item instead of the second and so on...
         */
        NSUInteger arrayIndex = (recordCount-index-1);
        //NSLog(@" Prep4Seg arrayIndex = %u", arrayIndex);
        selectedSession = [listData objectAtIndex:arrayIndex];
        //NSLog(@"listData = %@", listData);
        //NSLog(@"SelectedSession = %@", selectedSession);

        NSNumber *refId = [selectedSession valueForKey:@"refid"];
        NSString *refIdToSend = [[NSString alloc] initWithFormat:@"%@", refId];
        NSLog(@"Prep4Seg in tableView: refIdToSend = %@", refIdToSend);

        if ([segue.identifier isEqualToString:@"editSession"]) {
            SGK_T4T_EditSessionDetail *editSessionDetail = segue.destinationViewController;
            editSessionDetail.delegate = (id)self;
            editSessionDetail.returnFromDatePickerView = [[NSString alloc] initWithFormat:@"no"];
            editSessionDetail.recedIndex = refIdToSend;
        }
    }

    - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
        // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
        [self.tableView beginUpdates];
    }


    - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

        switch(type) {

            case NSFetchedResultsChangeInsert:
                [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
                break;

            case NSFetchedResultsChangeDelete:
                [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
                break;
        }
    }


    - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
        // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
        [self.tableView endUpdates];
    }

そして、私のログ出力は次のとおりです。

2013-11-09 16:04:04.034 trainForTri copy[6509:a0b] After managedObjectContext: <NSManagedObjectContext: 0xb589bc0>
2013-11-09 16:04:04.036 trainForTri copy[6509:a0b] After fetchedResultsController: <NSFetchedResultsController: 0xb5e2c40>
2013-11-09 16:04:04.040 trainForTri copy[6509:a0b] The fetch request returned an array!!!
2013-11-09 16:04:04.041 trainForTri copy[6509:a0b] objects contents is: (
    "<NSManagedObject: 0xb5c8570> (entity: Sessions; id: 0xb5ac970 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p1> ; data: <fault>)",
    "<NSManagedObject: 0xb5d6320> (entity: Sessions; id: 0xb58a2a0 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p2> ; data: <fault>)",
    "<NSManagedObject: 0xb5d0370> (entity: Sessions; id: 0xb5dc270 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p3> ; data: <fault>)",
    "<NSManagedObject: 0xb5e3dd0> (entity: Sessions; id: 0xb5ebcc0 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p4> ; data: <fault>)",
    "<NSManagedObject: 0xb585e40> (entity: Sessions; id: 0xb5e4e40 <x-coredata://B93EE0DE-E6FA-491C-9C8F-23692A36DD0C/Sessions/p5> ; data: <fault>)"
)
2013-11-09 16:04:04.041 trainForTri copy[6509:a0b] objects count = 5
2013-11-09 16:04:04.042 trainForTri copy[6509:a0b] listData count = 5
2013-11-09 16:04:04.043 trainForTri copy[6509:a0b] viewWillAppear: fetchedResultsController: <NSFetchedResultsController: 0xb5a01e0>
2013-11-09 16:04:04.043 trainForTri copy[6509:a0b] listData count in numberOFRowsInSection is: 5
4

1 に答える 1

0

OK、これで問題が見つかりました。最終的に、Xcode5 に不満を感じて Macbook を窓から放り出したくなった後、すべてをシャットダウンして再起動しました。Xcode を開いてアプリをビルドして実行すると、空のテーブルが読み込まれなくなりました。NSFetchedResultsController に問題があることを示すエラーが発生しました。キャッシュがクリアされない(または変更できない)問題を突き止めたので、キャッシュ名を削除してnilに設定すると、すべてが再び機能します。これが IOS7/Xcode5 の問題かどうかはわかりませんが、このアップグレードまで問題はありませんでした。同様の修正を探している人のために、問題のあるコード行を次に示します。

NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:@"Root"];

そして、これが機能するバージョンです!

NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:nil];

これに苦労しているのは私だけではないことを願っています。

于 2013-11-10T15:05:16.130 に答える