NSPredicate 设置时 UITableView 不刷新

UITableView doesn't refresh when NSPredicate set

前言:我试过了[self.tableview reloadData]。我的应用程序没有崩溃,但也没有刷新。

我正在尝试在一个 TableViewController 上显示 2 组结果,具体取决于是否设置了 NSPredicate。我正在尝试找到一个无术语的答案如何在设置谓词后更新 UITableViewController

我的数据在视图最初加载时正确显示。我的谓词设置正确,我在 return 值中抛出的所有日志语句...但是设置后什么也没有发生。

我知道这是一个非常愚蠢的问题,但我太笨了。我找到的每个答案都涉及 UISearchBar、已弃用的方法,或者是答案的片段等。

我要显示的内容:

1) 显示所有内容的 vanilla fetchRequest——这有效: 我在 viewDidLoad w/o w/o 中设置的 managedObjectContext 中的所有内容=16=].

2) 设置 NSPredicate 后,我想更新 tableView--这不会崩溃,但不会更新 tableView

MyTableViewController 上,我有一个弹出窗口,当我单击 MyTableViewController 上的 UIBarButtonItem 时它会实例化。在弹出窗口上,我在 MyTableViewController 上设置了一个谓词。

基本上,我想切换显示的内容,显示切换是由我的变量是 nil(显示所有内容)还是过滤(变量设置谓词)驱动的。

我是第一个尝试软件工程壮举的人,也是最愚蠢的人。考虑到我作为最终用户看到过多少次,我会打赌后者。 如果您知道我做错了什么,我将不胜感激。感谢您的阅读。

我有两个实体:PointOfInterestLocationCategory。我有一个 UIBarButton 触发弹出窗口,其中 MyTableViewController 是一个委托。单击弹出窗口将 selectedCategory 属性 设置为 MyTableViewController。:

// This gets set by PopoverTableViewController    
@property (nonatomic, strong) LocationCategory *selectedCategory;     

// This is set on `MyTableViewController`
@property (nonatomic, strong) NSPredicate *searchPredicate;

属性 在 MyTableViewController 上正确设置。我正在尝试使用 selectedCategory 对象作为谓词的基础来显示 "filtered" 对象的 'pointOfInterest' 列表。我从这个 TVC 中省略了样板代码,但我在 TVC.

上获得了 tableView 委托方法

我想我需要将我的 fetchedResultsController 设置为 nil 并在我的 refreshTableViewController 方法中使用谓词重新实例化它。它不会崩溃,但也不起作用。

这是 MyTableViewControllerviewDidLoad

- (void)viewDidLoad {
    [super viewDidLoad];

    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    self.managedObjectContext = appDelegate.managedObjectContext;

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

    NSLog(@"savedPOI managedObjectContext is %@", self.managedObjectContext);

    // Initialize fetch request
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]initWithEntityName:@"PointOfInterest"];

    // Add sort descriptors
    [fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]];

    // Initialize Fetched Results Controller
    self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];

    // Configure a fetchedResultsController
    [self.fetchedResultsController setDelegate:self];

    // Perform fetch
    NSError *error = nil;
    [self.fetchedResultsController performFetch:&error];

    if (error) {
        NSLog(@"Unable to perform fetch");
        NSLog(@"%@, %@", error, error.localizedDescription);
    }

    // This sets up an observer that listens for when `selectedCategory` is set
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(refreshTableViewController:) name:@"CategorySelected" object:nil];    
}

设置好 selectedCategory 后,我将以下方法设置为 运行。它不会崩溃,但不会刷新 MyTableViewController。我怀疑我这里有一个小错误,但我不确定我做错了什么。

- (void)refreshTableViewController:(NSNotification *)notification {
    if ([[notification name]isEqualToString:@"CategorySelected"]) {
        NSLog(@"NSNotification on SavedPOITableViewController's self.selectedCategory is %@", self.selectedCategory.categoryName);

        // Nuke the cache that was loaded in viewDidLoad
        [NSFetchedResultsController deleteCacheWithName:@"PointOfInterest"];

        // Nuke the fetchedResultsController alloc/inited in viewDidLoad
        self.fetchedResultsController = nil;

        // Alloc init a new fetchRequest
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

        // Set the entity
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"PointOfInterest" inManagedObjectContext:self.managedObjectContext];
        [fetchRequest setEntity:entity];

        // Add sort descriptors
        [fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]]];

        // Reinstantiate the fetchedResultsController
            self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];

        NSString *predicateString = self.selectedCategory.categoryName;
        NSLog(@"predicateString is %@", predicateString);

        self.searchPredicate = [NSPredicate predicateWithFormat:@"locationCategory.categoryName == %@", predicateString];
        NSLog(@"self.searchPredicate in refreshTableViewController is %@", predicateString);

        // Do the fetchRequest with the predicate
        [fetchRequest setPredicate:self.searchPredicate];

        // Perform fetch
        NSError *error = nil;
        [self.fetchedResultsController performFetch:&error];

        if (error) {
            NSLog(@"Unable to perform fetch");
            NSLog(@"%@, %@", error, error.localizedDescription);
        }
        [self.tableView reloadData];        


    }
}

为了完整起见,这是我的 PointOfInterestLocationCategory 课程:

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class LocationCategory;

@interface PointOfInterest : NSManagedObject

@property (nonatomic, retain) NSString * note;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * address;
@property (nonatomic, retain) NSNumber * latitude;
@property (nonatomic, retain) NSNumber * longitude;
@property (nonatomic, retain) NSString * phoneNumber;
@property (nonatomic, retain) NSString * url;
@property (nonatomic, retain) LocationCategory *locationCategory;

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class PointOfInterest;

@interface LocationCategory : NSManagedObject

@property (nonatomic, retain) id categoryColor;
@property (nonatomic, retain) NSString * categoryName;
@property (nonatomic, retain) NSSet *pointOfInterest;
@end

我想通了:

我在 MyTableViewController 上将其添加到我的实施文件中:

@synthesize fetchedResultsController = _fetchedResultsController;

如我所料,我漏掉了一些非常愚蠢的东西——我是**对的!!

我在 Ray Wenderlich 的网站上读到了这个 post,我注意到它在实现中有那一行,但我没有。我从来没有遇到过需要使用 @synthesize 的情况,而且我在其他地方看到过提到 "you almost never need it" 等。好吧,事实证明,你需要!

http://www.raywenderlich.com/14742/core-data-on-ios-5-tutorial-how-to-work-with-relations-and-predicates

Whosebug 上的这个 post 涵盖了 @synthesize 的基础知识。

What exactly does @synthesize do?