how to fetch a particular value using NSFetchRequest - ios

I need to fetch a particular managed entity where value is xxx.
my managed object is
Subscriptions : NSManagedObject{
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSNumber * id;
#property (nonatomic, retain) NSNumber * category;
#property (nonatomic, retain) NSNumber * frequency;
#property (nonatomic, retain) NSNumber * alertType;
}
I need to fetch only the one entities where name is "xxx".
(There will be only one entities where name is xxx.)
I also need to fetch all entities where category is 1.
How can I do this using NSFetchRequest. I know how to use NSFetchedResultsController to fetch all entity values for an entity, but I want to fetch only one where name is xxx.

Suppose you have a NSManagedObjectContext *context, then:
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; //Note don't use autorelease if you're using ARC
request.entity = [NSEntityDescription entityForName:#"Subscriptions" inManagedObjectContext:context];
NSString *someName = #"xxx";
request.predicate = [NSPredicate predicateWithFormat:#"name ==[c] %#", someName]; //[c] means case insensitive
NSArray *result = [context executeFetchRequest:request error:nil];
The result array will contain all returned results and will be of type Subscriptions. If the predicate matches only one item there will be only one result, if matches none, the array would be initialized, but its count property would be 0. You may take a look at NSPredicate Class Reference and how you use it with CoreData.

Related

how to form predicate to get objects from Core Data that contain string elements from Array

I need to create a predicate to get object from core data,
My entity "Form" looks like that:
#interface EEForm (CoreDataProperties)
#property (nullable, nonatomic, retain) NSDate *date;
#property (nullable, nonatomic, retain) NSString *descriptor;
#property (nullable, nonatomic, retain) NSString *location;
#property (nullable, nonatomic, retain) NSMutableSet<Participants *> *participants;
entity "Participants" look like that:
#interface Participants (CoreDataProperties)
#property (nonatomic, assign) NSInteger indexRow;
#property (nullable, nonatomic, retain) NSString *participant;
#property (nullable, nonatomic, retain) EEForm *form;
I want to get objects on the base of participants field, that contains all objects from a given array (this array consist of string objects and it changes dependently of what the user selects).
Fetch request is performed by FetchResultController. I set the predicate in initialisation of it.
I did it in that way, but it includes all objects that contains at least one object from the given array.
- (NSFetchedResultsController *)fetchResultController {
if(_fetchResultController != nil) {
return _fetchResultController;
}
NSPredicate *lPredicate = [NSPredicate predicateWithFormat:#"ANY participants.participant IN %#", _selectedForPredicatel];
NSFetchRequest *lRequest = [[NSFetchRequest alloc]init];
[lRequest setPredicate:lPredicate];
NSEntityDescription *lEntity = [NSEntityDescription entityForName:#"Form" inManagedObjectContext:self.managedObjectContext];
[lRequest setEntity:lEntity];
[lRequest setFetchBatchSize:10];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey:#"date" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
[lRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *fetchResultController = [[NSFetchedResultsController alloc]initWithFetchRequest:lRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
fetchResultController.delegate = self;
self.fetchResultController = fetchResultController;
NSError *error = nil;
if(![[self fetchResultController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return fetchResultController;
}
Could you please advice how to set predicate properly to filter objects that contain all elements from the given array.
EDIT:
array that is used for predicate looks like that:
_selectedForPredicatel = [[NSMutableArray alloc]initWithObjects:#"Child",#"Adult", #"Group of people", #"Family", #"Teenager", nil];
every time user selects parameters by which filter 'Form' objects, this array is updating, so I need fetch request to be done according to it. So if 'Form' has included participants: #"Child",#"Adult", but in an array _selectedForPredicatel there are objects: #"Adult", #"Group of people", in this case this 'Form' shouldn't be fetched. Should be fetched only that 'Form'that includes both elements of _selectedForPredicatel array.
Thanks a lot for any advice.
You want to include the forms if, for each of the user's selections, there is at least one Participant that has a participant attribute that matches.
If the participant names were unique (at least for each Form), you could count the matches and compare to the count of the user's selections. But if not, you need to create a predicate test each of the user's selections separately, and then combine the results into one big predicate:
NSPredicate *template = [NSPredicate predicateWithFormat:#"(SUBQUERY(participants, $p, $p.participant == $SELECTED).#count > 0)"];
NSMutableArray *predicateArray = [NSMutableArray array];
for (NSString *testString in _selectedForPredicatel) {
NSDictionary *subsVars = #{#"SELECTED" : testString};
NSPredicate *testPredicate = [template predicateWithSubstitutionVariables:subsVars];
[predicateArray addObject:testPredicate];
}
NSPredicate *finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateArray];
NSLog(#"finalPredicate is %#", finalPredicate);
NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:#"ListEntity"];
fetch.predicate = finalPredicate;
Here template is a dummy predicate using $SELECTED as a placeholder for the user's selection. The for loop uses this to create a predicate for each of the user's selections and adds it to a mutable array. The final predicate is built by compounding the array of predicates using AND clauses.
It's pretty messy (the final predicate is bad enough, the underlying SQL is horrible) so performance might be dismal.
Instead of ANY you can use ALL :
NSPredicate *lPredicate = [NSPredicate predicateWithFormat:#"ALL participants.participant IN %#", _sortByParticipants];
This will check if all objects are in your collection.

coredata NSFetchRequest one to many relationship Relationship fault on managed object

I have a coredata project with the following entities:
I'm trying to get the list of the content base on the category:
here is my coredata clasess .h:
#interface Content : NSManagedObject
#property (nonatomic, retain) NSString * contenido;
#property (nonatomic, retain) NSNumber * index;
#property (nonatomic, retain) NSString * titulo;
#property (nonatomic, retain) NSNumber * uploadCloudKit;
#property (nonatomic, retain) Categories *category;
---
#class Content;
#interface Categories : NSManagedObject
#property (nonatomic, retain) NSString * categoryName;
#property (nonatomic, retain) NSSet *content;
#end
NSEntityDescription *categoryDescription = [ NSEntityDescription entityForName:#"Categories" inManagedObjectContext:moc];
NSFetchRequest *categoRequest = [NSFetchRequest new];
categoRequest.entity = categoryDescription;
NSPredicate *categoPredicate = [NSPredicate predicateWithFormat:#"categoryName like %#", category];
categoRequest.predicate = categoPredicate;
NSArray *results = [moc executeFetchRequest:categoRequest error:&error];
but when I try to access the content on the result for the category I get:
po [results valueForKey:#"content"]
<__NSArrayI 0x6080000243a0>(
Relationship 'content' fault on managed object (0x6080000a2220) <Categories: 0x6080000a2220> (entity: Categories; id: 0x40002b <x-coredata://FDBA3FB2-F1F8-498E-9071-3A5D1ABE66F0/Categories/p1> ; data: {
categoryName = movies;
content = "<relationship fault: 0x610000030fa0 'content'>";
})
)
Any of you knows how can I get the content items of the result?
I'll really appreciate your help
It's a normal behaviour for CoreData. You should read Apple Documentation. There you can read about fault objects for CoreData. In two words - fault means that CoreData has this object but know (for some reason CoreData won't print you all fields of the object).
In order to see all vields you should do this:
[categoRequest setReturnsObjectsAsFaults:NO];
But I recomend you to do this only for debug, because CoreData smarter and know what to do with memory managment)

Get Specific data of relational entity from CoreData

I am having Country, State and City entities in my CoreData model. Here is the structure:
#interface Country : NSManagedObject
#property (nonatomic, retain) NSString * cId;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSSet *states; // This will contain State object
#end
#interface State : NSManagedObject
#property (nonatomic, retain) NSString * sId;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) NSSet *cities; // This will contain City object
#property (nonatomic, retain) Country *country;
#end
#interface City : NSManagedObject
#property (nonatomic, retain) NSString * cityId;
#property (nonatomic, retain) NSString * title;
#property (nonatomic, retain) State *state;
#end
As you can see I have one to many relation between Country - State and State - City.
Now what I want is to fetch Country list with all states, but don't want city list associated with States.
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Country"];
[request setPropertiesToFetch:#[#"cId", #"title", #"states"]];
NSError *error = nil;
NSArray *aryCategories = [gblAppDelegate.managedObjectContext executeFetchRequest:request error:&error];
setPropertiesToFetch Setting this property allows to have only mentioned fields from the entity but how to set only sid and title for NSSet states which contain State object.
For getting city list I will send another request.
Please help me on this.
You do not need propertiesToFetch. This feature (which BTW needs the NSDictionaryResultType) is for special situations where you have lots of data and only need certain fields. This is definitely not necessary in your case!
Just fetch the Country objects. Core Data will automatically optimize to avoid fetching unnecessary data into memory.
NSFetchRequest *request = [NSFetchRequest fetchRequestsWithEntityName:#"Country"];
// consider sorting
NSArray *countryList = [context executeFetchRequest:request error:nil];
You now have a country list. It contains also the states. To get the states of a particular country could not be simpler.
NSSet *states = country.states;
NB: I think calling your to-one relationship from City to State "country" is problematic. I suggest renaming it to state.

Find objects which contains subjects with given parameter

I'm trying to figure out NSPredicate which will find all objects which contains subjects with given parameter.
I have this objects:
#interface User : NSManagedObject
#property (nonatomic, strong) NSString * name;
#property (nonatomic, strong) NSMutableOrderedSet * items;
#end
and:
#interface Item : NSManagedObject
#property (nonatomic, strong) NSNumber * itemId;
#end
I have array of users and I want to find all users which contain item with itemId == 1.
Have no more clues how to get it
NSNumber *theItemId = #1; // The id that you are looking for
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY items.itemId == %#", theItemId];
should do it. You can use this predicate in a fetch request to fetch all matching users,
or with filteredArrayUsingPredicate: to filter an array of users.

EXC_BAC_ACCESS error when saving core data Boolean field

I am getting a EXC_BAC_ACCESS error when attempting to save a TRUE value into a managed object that contains a Boolean attribute.
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TrafficCameraInfo"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"code=%#",self.selectedTrafficCamera.code]];
NSError *error;
TrafficCameraInfo *cgTrafficCamera;
cgTrafficCamera = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] lastObject];
NSString *alertMessage;
if (cgTrafficCamera.favourite == NO){
cgTrafficCamera.name = #"TEST"; <-- works ok
cgTrafficCamera.favourite = 1; <-- causes an error
} else {
cgTrafficCamera.favourite = 0;
}
error = nil;
if (![self.managedObjectContext save:&error]) {
The managed object interface looks like this:
#interface TrafficCameraInfo : NSManagedObject
#property (nonatomic, retain) NSString *code;
#property (nonatomic, retain) NSString *postCode;
#property (nonatomic, retain) NSNumber *latitude;
#property (nonatomic, retain) NSNumber *longitude;
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *url;
#property (nonatomic) Boolean favourite;
#end
Elsewhere in my app i am updating another Boolean field by passing a 1 to it and am not encountering a problem.
Any ideas what is causing the error?
I think in your core data attribute table you define "favorite" variable to BOOL,well that means it's an NSNumber Type,so you should set the data using NSNumber
A Boolean is a simple, scalar, non-pointer datatype. Core Data properties are always stored as objects. The Objective-C object wrapper for numeric datatypes is NSNumber. So if favourite is a regular stored property, you should declare it as:
#property (nonatomic, retain) NSNumber *favourite;
Assignment would be done like this:
cgTrafficCamera.favourite = [NSNumber numberWithBool:YES]; // Obj-C style is "YES/NO" for BOOL
Or this if you prefer:
cgTrafficCamera.favourite = [NSNumber numberWithBool:1];
If you don't need to store the Boolean, you can leave it as such and make it a transient property. You'll probably need to get rid of the "(nonatomic)" in that case.

Resources