gpt4 book ai didi

用于根据相关数据进行过滤的 iOS Core Data Predicate

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:04:54 25 4
gpt4 key购买 nike

好吧,我是谓词菜鸟。他们对我来说是陌生的。

关于应用程序:

我有一个处理游戏比赛的应用程序。有用于玩家、签到和比赛的实体。这个想法是将球员添加到应用程序,然后可以登记参加比赛,并存储比赛结果。

关系:

玩家 <->> 签到(每个玩家可以在不同日期多次签到)

  • 来自:玩家实体
  • 关系:playerCheckins
  • 反向:checkedInPlayer
  • 目的地: checkin 实体

选手 <<->> 比赛(每场比赛可以有两名选手,选手每次比赛可以有多场比赛)

  • 来自:玩家实体
  • 关系:playerMatches
  • 逆向:matchPlayers
  • 目标:匹配实体

我有一个共享 Collection View ,其中列出了应用中的所有玩家。当玩家签到以及将他们添加到新的比赛条目时使用它。到目前为止一切正常。

我想做什么:

我希望玩家 Collection View 能够根据签到状态过滤列出的玩家。例如,签到新玩家时,玩家 Collection View 应该只显示当天尚未签到的玩家。 (CheckIns 对每个条目都有一个日期属性)此外,在将玩家添加到比赛中时, Collection View 应仅显示当天已经签到的玩家。

我计划在模态加载 Collection View 时将 NSString 属性添加到使用谓词文本设置的玩家 Collection View 。这样,我可以根据我是否分别从我的匹配和 checkin View 中调用 Collection View 来更改谓词。

这对我正在尝试做的事情可能吗?这些谓词字符串会是什么样子?

谢谢!

更新

我应该更清楚。我正在使用 fetchedresultscontroller 让玩家进入 collectionview,所以我正在寻找要在获取请求中使用的谓词...

添加代码...

我的收藏 View Controller :

PlayersCollectionViewController.h
#import "CoreCollectionViewController.h"
#import "Player.h"

@protocol PlayersCollectionViewControllerDelegate;


@interface PlayersCollectionViewController : CoreCollectionViewController <NSFetchedResultsControllerDelegate>

@property (nonatomic, assign) id <PlayersCollectionViewControllerDelegate> delegate;
@property (nonatomic, strong) NSString *titleText;
@property (nonatomic, strong) NSString *predicate;

- (IBAction)cancel:(UIBarButtonItem *)sender;
- (IBAction)done:(UIBarButtonItem *)sender;

@end

@protocol PlayersCollectionViewControllerDelegate <NSObject>

@optional
-(void)ViewController:(UIViewController *)sender
didSelectPlayer:(Player *)selectedPlayer;

@optional
-(void)ViewController:(UIViewController *)sender
didSelectPlayer1:(Player *)selectedPlayer1;

@optional
-(void)ViewController:(UIViewController *)sender
didSelectPlayer2:(Player *)selectedPlayer2;

@end

...和实现:

#import "PlayersCollectionViewController.h"
#import "AppDelegate.h"
#import "PlayerCollectionViewCell.h"

@interface PlayersCollectionViewController ()
@property(nonatomic, strong) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@end

@implementation PlayersCollectionViewController
@synthesize titleText, predicate;

static NSString * const reuseIdentifier = @"Cell";

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

-(NSManagedObjectContext*)managedObjectContext{
return [(AppDelegate*)[[UIApplication sharedApplication]delegate]managedObjectContext];
}

- (void)viewDidLoad
{
[super viewDidLoad];

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

// Register cell classes
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];

// Do any additional setup after loading the view.
NSError *error = nil;
if (![[self fetchedResultsController]performFetch:&error]) {
NSLog(@"Error: %@", error);
abort();
}
}

-(void)viewWillAppear:(BOOL)animated
{
[self setTitle:titleText];
[self.collectionView reloadData];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/

#pragma mark <UICollectionViewDataSource>

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return [[self.fetchedResultsController sections]count];
}


- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [[self.fetchedResultsController fetchedObjects]count];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

PlayerCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"PlayerCollCell" forIndexPath:indexPath];
Player *player = [self.fetchedResultsController objectAtIndexPath:indexPath];

// Configure the cell

if (player.playerImage) {
cell.playerImageView.image = [UIImage imageWithContentsOfFile:player.playerImageSmall];
}

[cell.playerNameLabel setText:player.firstName];

return cell;
}

-(BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{

PlayerCollectionViewCell *selectedPlayerCell = (PlayerCollectionViewCell*)[collectionView cellForItemAtIndexPath:indexPath];

[collectionView dequeueReusableCellWithReuseIdentifier:@"PlayerCollCell" forIndexPath:indexPath];

selectedPlayerCell.backgroundColor = [UIColor lightGrayColor];

Player *selectedPlayer = [self.fetchedResultsController objectAtIndexPath:indexPath];

NSLog(@"Selected player %@", selectedPlayer.firstName);

if ([self.title isEqualToString:@"Select Player 1"]) {
[self.delegate ViewController:self didSelectPlayer1:selectedPlayer];
} else if ([self.title isEqualToString:@"Select Player 2"]) {
[self.delegate ViewController:self didSelectPlayer2:selectedPlayer];
} else if ([self.title isEqualToString:@"Select Player"]) {
[self.delegate ViewController:self didSelectPlayer:selectedPlayer];
}

[self dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark - ViewController methods
- (IBAction)cancel:(UIBarButtonItem *)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}

- (IBAction)done:(UIBarButtonItem *)sender { //not sure if this method and UI are needed...
[self dismissViewControllerAnimated:YES completion:nil];
}


#pragma mark - Fetched Results Controller Section
-(NSFetchedResultsController*) fetchedResultsController
{
if (_fetchedResultsController !=nil) {
return _fetchedResultsController;
}

NSFetchRequest *fetchedRequest = [[NSFetchRequest alloc]init];

NSManagedObjectContext *context = [self managedObjectContext];

NSEntityDescription *entity =[NSEntityDescription entityForName:@"Player" inManagedObjectContext:context];

[fetchedRequest setEntity:entity];

NSSortDescriptor *lastNameSortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"lastName" ascending:YES];
NSSortDescriptor *firsttNameSortDescriptor = [[NSSortDescriptor alloc]initWithKey:@"firstName" ascending:YES];

NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:lastNameSortDescriptor, firsttNameSortDescriptor, nil];

fetchedRequest.sortDescriptors = sortDescriptors;


_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchedRequest
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:nil];

_fetchedResultsController.delegate = self;

return _fetchedResultsController;

}

#pragma mark - Fetched Results Controller Delegates
/*
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.collectionView beginUpdates];
}

-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.collectionView endUpdates];
}
*/

-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

UICollectionView *collectionView = self.collectionView;

switch (type) {
case NSFetchedResultsChangeInsert:
[collectionView insertItemsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath, nil]];
break;

case NSFetchedResultsChangeDelete: [collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]];
break;

case NSFetchedResultsChangeUpdate: {
PlayerCollectionViewCell *selectedPlayerCell = (PlayerCollectionViewCell*)[collectionView cellForItemAtIndexPath:indexPath];

//selectedPlayerCell.backgroundColor = [UIColor lightGrayColor];

Player *selectedPlayer = [self.fetchedResultsController objectAtIndexPath:indexPath];

if (selectedPlayer.playerImage) {
selectedPlayerCell.playerImageView.image = [UIImage imageWithContentsOfFile:selectedPlayer.playerImageSmall];
}

[selectedPlayerCell.playerNameLabel setText:selectedPlayer.firstName];

}
break;

case NSFetchedResultsChangeMove: [collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]];
[collectionView insertItemsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath, nil]];
break;

}

}

@end

最佳答案

暂时离开 View Controller 和获取结果 Controller 。您的谓词属于模型层,而不属于 Controller 或 View 层。 NSFetchRequest 或 NSFetchedResultsController 的谓词没有什么特别之处。它仍然只是一个 NSPredicate。

为什么要在模型层做这个?您基于“当天签到”进行过滤的问题与 View 或向用户显示的内容无关。这纯粹是一个数据问题。所以在模型层解决它(好处:现在很容易为这个获取编写单元测试)。

如果您稍微作弊并使用您对数据的了解,您可以使这更容易。使 Player<->>CheckIn 关系有序(旁注:Core Data 中的实体名称是单数,就像类名一样,尽管对多关系是复数)。现在很容易获得玩家最近的签到:它是 thePlayer.checkins[0] , 签到时间是[thePlayer.checkins[0] timeOfEvent] .只要确保在添加 CheckIn 时到 Player ,你把它放在索引 0 处。

不过,您可以通过稍微非规范化您的数据模型来使其更容易。保持来自 Player 的一对多关系至 CheckIn .但是在 Player 上添加一个属性, timeOfLastCheckIn .确保更新 timeOfLastCheckIn每当您添加签到时; “说一次”意味着您应该将这对步骤包装在一个方法中,并始终调用该方法来添加 CheckIn。

现在进入 Xcode 数据建模器。在 Player 上创建一个新的获取请求带有替代变量。在下拉列表中选择表达式并输入 timeOfLastCheckIn > $fromdate .在 Player 上写一个方法( +playersCheckingInAfterDate:context: ) 执行该获取请求,接受两个参数, NSManagedObjectContext和一个 NSDate ,并返回 Players 的数组.您将使用 fetchRequestFromTemplateWithName:substitutionVariables:实例化一个获取请求,将对应于本地午夜的 NSDate 替换为 $fromdate .添加一个包装器方法,如果你愿意,计算本地午夜时间并将其传递给 +playersCheckingInAfterDate:context: .您可以切换 ><在一组类似的方法/获取模板中找到今天没有签到的玩家。

关于用于根据相关数据进行过滤的 iOS Core Data Predicate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24564551/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com