How can i filter the records displayed in NSTableView with predicate?
In my entity there is a BOOL isTemp and i want in the table to be displayed only elements which are BOOL = YES.
I solved the problem.Selectin ArrayController in XCode there is a field predicate :)
Related
Consider a Core Data model with two Entities: TermDictionary and Term. The TermDictionary has a "name" property, and a one-to-many relationship called "terms" which points to a set of Term objects, each of which consists of two properties: "name" and "score".
I've got an NSFetchRequest which I'm using as a data source for a UITableView which displays all of the TermDictionaries in the database. The idea is that the table will, for each cell, display the name of the dictionary, along with a count of the number of terms in that dictionary.
In the following code snippet, item contains an NSFetchRequestResult for the "TermDictionary" entity:
let thisDict = item as! TermDictionary
cell.textLabel?.text = thisDict.name
cell.detailTextLabel?.text = "\(thisDict.terms?.count ?? 0) terms"
...The table cells are correctly displaying the names of the Term Dictionaries, however it looks like thisDict.terms is always coming up nil, so the number-of-terms label always shows zero.
Do I need do do something special with item rather than just casting it to my TermDictionary managed object subclass?
You do not need to do anything special. If thisDict.terms prints as nil, it really is nil. Check your data store.
I have a Core Data model of cars created and I'd like select one of vehicle type PLUS any of several different colors Here's what I envision to do this:
Selection ViewController
1) Select the type of car (sedan, coupe, SUV, hybrid) (I envision a segmented control to set this as a predicate)
2) Once the type of vehicle is selected, I'd like to select from a list of colors and display only cars that satisfy the type of vehicle I selected in the first step. For example, I'd like to display only SUVs that are (red, green, and blue) or only hybrids that are black and white.
Results TableViewController
3) Once those are selected, I'd like to dump them on another TVC.
This post helps a bit, but person asking the question trying to find disparate items (ex: A, B, & C). I'm trying to find X, Y & Z within only A.
Can I apply multiple predicates to an NSFetchRequest? Would it be better to manually parse my results?
I'm running into trouble when I try retrieve one type of vehicle plus a list of selected colors
let vehiclePredicate = NSPredicate(format: "type == %#", "(one of sedan/coupe/SUV/hybrid)")
AND any of the following criteria
let colorRedPredicate = NSPredicate(format: "color == %#", "red")
let colorGreenPredicate = NSPredicate(format: "color == %#", "green")
let colorBluePredicate = NSPredicate(format: "color == %#", "red")
let colorBlackPredicate = NSPredicate(format: "color == %#", "black")
let colorWhitePredicate = NSPredicate(format: "color == %#", "white")
let colorPredicates: NSArray = [**add colors here when they're selected**]
I'm trying to figure out the cleanest way to do this, but the examples I've found only retrieve disparate items.
The other roadblock I've run into is how to get the results from my SelectionVC to the ResultsTVC. I know I'm going to need a delegate, but what will I need? Any assistance on this would be greatly appreciated.
You want to end up with a predicate like:
type == %# AND color IN %#
And then supply your type as a string and the colours as a collection. You can do this with a compound predicate created from 2 others or just change what your UI selection means and generate the two parameters as the segment name and an array of colours.
If you want to combine multiple options of the oboe then you need to create each and then use a compound predicate to combine them.
Your question is not clear. Your predicates have wrong syntax - are unintelligible. That being said, I think I guess what you want, so here it is.
You could start with a fully loaded table view without any filters. You could implement a filter menu (or buttons) and present the appropriate control (segmented control, table view with multiple selection, table view with single selection, slider etc) modally.
In your original table view you use a NSFetchedResultsController, and you keep a NSPredicate as a property. Whenever the predicate changes, you nil out the fetched results controller and reload your table.
The modal control views can feed back to your master view controller which then modifies the predicate. You can combine all predicates with the NSCompoundPredicate API. Maybe it is most convenient to keep them in a mutable array, so you have them handy.
var predicateArray = [NSPredicate]()
E.g. start with this
predicate = NSPredicate(value: "true")
predicateArray.append(predicate)
Now the color controller sends back ["red", "green", "blue"]. You could construct or predicates by constructing the right predicate string, or by using orPredicateWithSubpredicates, but it might be easier to just use collection operators:
let colorPredicate = NSPredicate(format: "color in %#", colorStrings)!
predicateArray.append(colorPredicate)
In your fetched results controller getter you reconstruct the predicate based on your predicate array:
fetchRequest.predicate =
NSCompoundPredicate.andPredicateWithSubpredicates(predicateArray)
SCENARIO
I have two entities: Item and ListDetail (which contains prices for different lists for every item). This is absolutely needed and I can't provide a price attribute for the Item entity because every item can have more prices for different dynamic lists (retail, b2b ecc.).
The relationship is:
Item (lists) <------->> (item) ListDetail
The current active list in my app change dinamically, so let's say I have an integer variable with the current active list: _ACTIVE_LIST_CODE_. When I need a price for an item object I use an helper method on the Item class:
-(NSNumber*) getPrice {
NSSet *lists=[self.lists filteredSetUsingPredicate: [NSPredicate predicateWithFormat:#"listId == %d",_ACTIVE_LIST_CODE_]];
ListDetail *activeList=[[lists allObjects] objectAtIndex:0];
return activeList.price;
}
THE PROBLEM
I use a UITableView with NSFetchedResultController in order to select and show some items for different sections. Nothing special. I would like to order the fetchedObjects using the items price for the active list. If price was an attribute of Item I would added simply a sort descriptor to the fetch request like so:
[NSSortDescriptor sortDescriptorWithKey:#"price" ascending:YES];
But as said before this is not possible, price is a dynamic attribute.
If using transient properties was possible for sort descriptors, I would set a price transient properties calculated on fly using my helper method. Nothing to do.
Using a keypath in the descriptor like "lists.price" is not possible (or maybe I don't know how to do that), just because it's a to-many relationship and it's modeled with a NSSet.
I tried some workaround, without success:
1) observing _ACTIVE_LIST_CODE_ changes to set items price in a non-transient attribute.
2) after the fetch request, before presenting the table view, reorder a brand new array with fetched objects using the transient "price" property, iterate the orderdered array following an ascending integer index "i" and assigning this value to a non-transient property "order" for the Item entity. Using "order" for sort descriptor in the fetch request. (This approach is described here: Re-ordering NSFetchedResultsController)
Both of them works, but they slow down performance because I have thousands of items in the fetch results... Any idea?
How about fetching ListDetail instead? You could restrict and sort with the appropriate predicates and sort descriptors, exactly as you propose.
fetchRequest.predicate =
[NSPredicate predicateWithFormat:#"listID = %#", activeListCode];
fetchRequest.sortDescriptors =
#[[NSSortDescriptor sortDescriptorWithKey:#"price" ascending:YES]];
Now, to group by some attribute of item should be simple and efficient because it is a to-one relationship. Your fetched results controller's sectionNameKeyPath can be something like
#"item.category"
Is there any way I can validate a value updated in a Core Data entity's property against values of the property in other entities in the collection?
At the moment I create an entity with some default values, add it to arrangedObjects, then get the user to modify the various property values. However, I would like to check a particular property and make sure there're no other entities in the array with the same value for that property. What's the best way to do this?
Many thanks,
Dany.
Manually checking is only a few lines of code with a fast enumeration loop:
BOOL unique = YES;
for (NSManagedObject *obj in collection) {
if (obj.property == value) {
unique = NO;
break;
}
}
I wound up modifying the source from a publically posted POC: http://datacogs.com/datablogs/archive/2007/08/26/641.aspx, which is a custom field definition for cascading drop downs. The modifications were to allow parent-child list boxes where a user can multiselect for filtering and selecting the values to be written back to a SharePoint list. I got the parent-child cascading behavior working, but the save operation only takes the first value that is selected from the list box. I changed the base type for the custom field control from "SPFieldText" to "SPMultiLineText", along with changing the FLD_TYPES field definition values from:
Text to Note and this did not work. So, I changed the field control base type to "SPFieldMultiChoice" and the FLD_TYPES to "MultiChoice" and still get the same result, which is only the first value that's selected, writing to the SharePoint list.
Does anyone have any idea how to get a custom field with multiple selections to write those multiple selections to a SharePoint list?
Thanks for taking the time to read through my post.
Cheers,
~Peter
I was able to accomplish this by inheriting from SPFieldLookup and overriding its internal handling of AllowMultipleValues:
In your FLDTYPES_*.xml set <ParentType>LookupMulti</ParentType>
In your extension of SPFieldLookup, be sure to override AllowMultipleValues (always true), FieldValueType (probably typeof(SPFieldLookupValueCollection)) and FieldRenderingControl. I also set base.LookupField = "LinkTitleNoMenu", though in retrospect I'm not sure why. :)
In your field editor control's OnSaveChange(), set the field's Mult value to true.
To set Mult, you can either string manipulation on field.SchemaXml:
string s = field.SchemaXml;
if (s.IndexOf(" Mult=", StringComparison.OrdinalIgnoreCase) < 0)
field.SchemaXml = s.Insert(s.IndexOf("/>", StringComparison.Ordinal), " Mult=\"TRUE\" ");
Or use reflection:
var type = field.GetType();
var mi = type.GetMethod("SetFieldBoolValue", BindingFlags.Instance | BindingFlags.NonPublic);
mi.Invoke(field, new object[] { "Mult", true });
It's been a while, so I might be forgetting something, but that should be most of it.