Based on the data model here: Photographer<------->>Photo
When the user goes to add a Photo, the user also specifies what Photographer took said picture. When the user decides to save the Photo, there is the possibility that the Photographer doesn't exist yet. After executing a NSFetchRequest to get a list of all instances of Photographer, how do I check if the NSMutableArray(photographerArray) contains an object that has the same fullName attribute as what the user is currently adding?
The naive way would be to simply get all the fullName of the array and check if it's in it.
BOOL photographerExist = [[listOfPhotographer valueForKey:#"fullName"] containsObject:enteredFullName];
However, it would be way more easier to put that directly in your fetch request. Just add a predicate to it.
NSPredicate *fullNamePredicate = [NSPredicate predicateWithFormat:#"fullName = %#", enteredFullName];
fetchRequest.predicate = fullNamePredicate;
If the result of the fetch is empty, then the photographer doesn't exist yet.
Related
I am fairly new to core data. I have database which contains articles with different categories. I want to fetch data from multiple categories, which can be selected by user on the fly. Now I have NSArray which contains selected multiple categories (count from 1 to n) I want to add predicate for selected categories but I'm not able to do so. as per my knowledge i have added for loop for adding categories in predicate but it is not working.
for i in 0...(catArray?.count)!-1 {
let str = String(format:"catId = %#",(catArray?.object(at: i) as? NSNumber)!)
predicateString = predicateString+str
}
let dP = NSPredicate(format:"%#",predicateString)
fetchedRequest.predicate=dP;
but app is crashing while fetching request.
Is there any other way to do it?
Please help me with this.
Any help is much appreciated.
To select objects which have any category from the given array
a simple predicate is sufficient:
NSPredicate(format: "catId IN %#", catArray)
Remark: Never use String(format:) to build predicates dynamically,
because almost surely the quoting and escaping will be wrong.
Use only NSPredicate(format:) and, if necessary, NSCompoundPredicate.
I've created three PHCollections within my app. In a different part of my app, I'm attempting to fetch them and display them in a table view. I can get all of the user created libraries by using the following code
let topLevelUserCollections: PHFetchResult = PHCollectionList.fetchTopLevelUserCollectionsWithOptions(nil)
self.collectionsFetchResults = [topLevelUserCollections];
self.collectionsLocalizedTitles = ["My Clips"];
PHPhotoLibrary.sharedPhotoLibrary().registerChangeObserver(self) //With this you need to conform to PHPhotoLibraryChangeObserver
but how can I fetch only the asset collection I want? Also, I only want video and not images, is there a way to fetch only results with videos assests?
You are calling PHCollectionList.fetchTopLevelUserCollectionsWithOptions with a parameter of nil. But that nil is the PHFetchOptions. Those PHFetchOptions are exactly how you make this sort of specification.
In particular, if you created these collections yourself, you have their localIdentifier values. That is exactly what you would specify in the PHFetchOptions predicate to pull out those collections. You could also do it by localizedTitle and so on.
Ok so I have a bunch of objects that exist in my database, they have all fields completed except for two... as the value could not be determined at the time that the objects were created.
Now I want to insert code in a payment received method that will write the SAME value (eg. $120.50) to the blank fields for ALL objects returned by the fetchedResultsController.
This is what I had previously done to create a NEW object and set the values for the properties.
newInvoice = [NSEntityDescription insertNewObjectForEntityForName:#"Invoice" inManagedObjectContext:managedObjectContext];
[newInvoice setValue:productTextField.text forKey:#"itemCode"];
What code do I use to set the value of ALL returned objects, for the properties below which are currently blank in the SQL database?
[newInvoice setValue:amountPaidLabel.text forKey:#"amountPaid"];
[newInvoice setValue:paymentMethod.text forKey:#"PaymentMethod"];
I hope that made sense, any input would be kindly appreciated
I would add a method on your invoice class...
- (void)updateEmptyPaid:(NSNumber *)aValue {
[self setValue:aValue forKey:#"amountPaid"];
}
... do the same for the payment method and then you can do....
[myInvoices makeObjectsPerformSelector:#selector(updateEmptyPaid:) withObject:newValue];
[myInvoices makeObjectsPerformSelector:#selector(updatePaymentMethod:) withObject:newValue];
Where myInvoices is an array of the results from NSFetchRequest.
here is my core data model:
Locations < --- >> ThemesList << --- > Themes
The entites have the following attributes:
Locations
- Property: Name
- Relationship: ThemesList
ThemesList
- Relationship: Locations
- Relationship: Themes
Themes
- Property: Name
- Relationship: Locations
I am running a fetch on entity Locations and I want to only pull values where the name property in Themes is equal to a particular value. Based on what I've read, I need to do a subquery. I've tried something along the lines of the code below, but I always receive the error of Unable to parse the format string
[NSString stringWithFormat:#"SUBQUERY(ThemesList, $theThemes, $theThemes.Themes.Name LIKE %#)", #"a theme name"];
Any ideas on how I can accomplish this - what am I doing wrong?
Thanks
As a rule of thumb, you should fetch the objects of the entity you are testing with the predicate instead of starting with another entity altogether and walking a relationship inside the predicate. Walking relationships, especially to-many relationships inside of predicates is computationally intensive and slow.
Instead, I would recommend running the fetch against the Theme entity and then just ask the returned Theme objects for their associated Locations objects.
Your predicate would simplify to just:
NSPredicate *p = [NSPredicate predicateWithFormat:#"Themes.Name LIKE %#", #"a theme name"];
Then use a collection operator to find the location objects:
NSSet *locations=[fetchedThemes valueForKeyPath:#"#distinctUnionOfSets.locations"];
Your problem is this: $theThemes.Themes.Name. The parser will want to parse it as a variable expression (since it starts with a $), but when it comes across the ., it's going to produce an error.
As it turns out, the SUBQUERY is unnecessary. That same query can be effectively done as:
NSPredicate *p = [NSPredicate predicateWithFormat:#"ANY ThemesList.Themes.Name LIKE %#", #"a theme name"];
Hopefully Core Data will have an easier time handling that than the SUBQUERY.
I've been trying to see if there is any way I can improve on the performance of the following Predicate:
[NSPredicate predicateWithFormat:#"A=%# and SUBQUERY($self.words,$k,$k.keyword IN %#).#count==%d",
<value for A>,
keywordList,
[keywordList count]];
What I'm trying to do is return all the records of A that have keywords that are ALL contained in the supplied array (keywordList). I have a small database of about 2000 records. However, the keywords for each Entity ranges from 40-300 keywords. The keywords are represented as a to-Many relationship from A to an entity called Keywords. The above query works but takes about 7 seconds to run on my iPhone4. I want to see what I can do to shrink that down to a sub-second response.
Thanks,
Michael
This doesn't quite solve the problem as the results that come back from intersection of the fetchedObjs is not correct. It doesn't guarantee that all the 'A' objects contain all the supplied keywords. In fact, what comes back is an empty list and the entire process actually takes longer.
Something must be wrong with my model or the previous answer. I'm not getting the results I'm expecting. One alternative to returning a list of 'A' would be to return a list of ManagedObjectIDs of 'A'. [mo valueForKey: (NSString *)] returns the object of the relationship.
Note: I originally posted this question anonymously thinking I was logged in, so i can't seem to comment on anybody's answer.
I think you are approaching the problem backwards. If you have the keywords, you should search for the Keyword objects and then walk their A relationships to find the related A objects. Then check for overlap in the relationship sets.
So something like:
NSFetchRequest *fetch=//...set up fetch
[fetch setEntity:Keyword_entity];
NSPredicate *p=[NSPredicate predicateWithFormat:#"keyword IN %#",keywords];
[fetch setPredicate:p];
NSArray *fetchedObj=//... execute fetch
NSMutableSet *inCommon=[NSMutableSet setWithCapacity:[fetchedObjs count]];
for (NSManagedObject *mo in fetchedObjs){
if ([inCommon count]==0){
[inCommon addObjects:[mo valueForKey:#"aRelationshipName"]];
}else{
[inCommon intersectSet:[mo valueForKey:#"aRelationshipName"]];
}
}
... inCommon would then contain a set of all unique A objects that shared all the keywords.
Update:
From OP author:
This doesn't quite solve the problem
as the results that come back from
intersection of the fetchedObjs is not
correct. It doesn't guarantee that all
the 'A' objects contain all the
supplied keywords.
Okay, lets take another tack. Assuming you have a data model that looks something like this:
A {
keywords<<-->>Keyword.as
}
Keyword{
keyword:string
as<<-->>A.keywords
}
Then something like this should work:
NSFetchRequest *keyWordFetch=//...set up fetch
[keyWordFetch setEntity:Keyword_entity];
NSPredicate *p=[NSPredicate predicateWithFormat:#"keyword IN %#",keywords];
[keyWordFetch setPredicate:p];
NSArray *fetchedKeywords=//... execute keyWordFetch
NSFetchRequest *entityAFetch=//...set up fetch
[entityAFetch setEntity:A_entity];
NSPredicate *pred=[NSPredicate predicateWithFormat:#"ALL keywords IN %#", fetchedKeywords);
[entityAFetch setPredicate:pred];
NSArray *fetchedAs=//... execute fetch