I have a data model entity called Object laid out like so:
name: String
createdDate: Date()
updatedDate: Date()
My fetch request:
#FetchRequest(sortDescriptors: [SortDescriptor(\.updatedDate, order: .reverse)]) var objects: FetchedResults<Object>
I want to have my list of objects sorted with the most recently updated (keyed off updatedDate) at the top. I chose this sort method, because when combined with withAnimation I get a real nice animation when items lower in the list are updated and move to the top.
When the user creates a new object however, it goes to the bottom of the list because this new object doesn't have a value for updatedDate (intentional because my users tell the app when an object is updated). This behaviour makes sense but is undesired.
My current ObjectListView looks like this (simplified to focus on my question):
struct intervalsExist: View {
#Environment(\.managedObjectContext) private var viewContext
#FetchRequest(sortDescriptors: [SortDescriptor(\.updatedDate, order: .reverse)]) var objects: FetchedResults<Object>
var body: some View {
List {
ForEach(objects) { object in
NavigationLink {
ObjectDetailView(object: object)
} label: {
Text(object.name ?? "Unknown name")
}
.swipeActions(edge: .leading) {
withAnimation {
// Update `updatedDate` with current Date()
}
}
}
}
}
}
What I would like is for my list of objects to be presented as such:
---
Object with no updatedDate, most recent
Object with no updatedDate
Object with no updatedDate
Object with updatedDate, most recent
Object with updatedDate
Object with updatedDate
---
Where objects with updatedDate will reorder themselves to the the newest at the top when they are updated.
I tried using 2 sort methods in my fetch request, like so:
#FetchRequest(sortDescriptors: [
SortDescriptor(\.createdDate, order: .reverse),
SortDescriptor(\.updateDate, order: .reverse),
]) var objects: FetchedResults<Object>
While this gets me the ordering I am looking for above, items no longer re-order themselves within the list which is a key part of what I'm trying to build.
Even if I run the risk of asking a question twice and I'm too blind to see:
How can I sort a FetchRequest by an Attribute of an related Entity. In my special case, I've got three tables:
Client <-> ClientToContacts <-> Contacts. In a List View I like to list all ClientToContacs sorted by Contacs.lastName.
How can I do it by sortDescriptors?
This is my FetchRequest so far. But the sortDescriptors throw errors.
sortDescriptors: [
NSSortDescriptor(keyPath: \ClientsToContacts?.toContacts!.lastName, ascending: true),
NSSortDescriptor(keyPath: \ClientsToContacts?.toContacts!.firstName, ascending: true)
],
predicate: NSPredicate(format: "(toContacts.lastName CONTAINS[cd] %#) OR (toContacts.firstName CONTAINS[cd] %#) OR (toContacts.company CONTAINS[cd] %#) OR (toContacts.department CONTAINS[cd] %#) OR (toContacts.zip CONTAINS[cd] %#)", filter, filter, filter, filter, filter),
animation: .default
The predicate works fine so far and filters my results. Only sorting...
Thanks for helping. :-)
I am trying to use a fetch request in a SwiftUI Charts package/CocoaPod. My issue is that when I use a ForEach to iterate over the Attribute (ACFTScores.totalScore) it populates one value per chart... I know this is because the BarChart is in the body of the ForEach but I don't know how to grab the range of the fetch and make it work with the SwiftUI Charts.
struct DashboardACFT: View {
#FetchRequest(entity: ACFTScores.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \ACFTScores.totalScore, ascending: true)]) var acftScores: FetchedResults<ACFTScores>
var body: some View {
VStack {
ForEach(acftScores, id: \.id) { score in
BarChartView(data: [Int(score.totalScore)], title: "Title", legend: "Legendary")
}
}
}
}
I haven't worked with charts but you need to map your fetch request into an array containing the values you want to use in your chart. Something like this
var body: some View {
VStack {
BarChartView(data: acftScores.map {$0.totalScore}, title: "Title", legend: "Legendary")
}
}
}
Since you for some reason seems to need to convert the property to Int using compactMap might be better.
acftScores.compactMap {Int($0.totalScore)}
I tried to return required parameter in DataSet. Whenever am return the data to row am not able to encode the data with struct Type,If suppose am using Map/JSONObject it was throwing Map/jsonobject it not a valid External schema, Below code i tried? Any help will be appreciate thanks in advance
DataSet<Row>//
Row rowdat=RowFactory.create(jsondata)
Return rowdat.iterator();
//Dataset data will be **** [[{"employees:"accountant","firstname":"walter", "age":"54"}]]
StructType schema = DataTypes.createStructType(new StructField[] {
DataTypes.createStructField("employees", DataTypes.StringType, true),
DataTypes.createStructField("firstname", DataTypes.StringType, true),
DataTypes.createStructField("age", DataTypes.StringType, true)
});
ExpressionEncoder express=RowCoder.apply(schema)
hello am using grid to display dynamic data dojo, but what I get is that sample (n) times, but always shows me the last record, but if I do it with dummy data works well, I hope you help me with this issue.
define(["js/module/modControllerPersona", "dojo/store/Memory", "gridx/Grid", "gridx/core/model/cache/Sync", "dojo/data/ObjectStore"],
function(modControllerPersona, Store, Grid, Cache, ObjectStore){
var grid, store, data;
var persona = new Array();
return{
datagridx: function(){
modControllerPersona.persona().then(function(result){
persona = JSON.parse(result);
data = persona.items;
store = new Store({data: data});
var columns = [
{name: 'id', field: 'descripcion'},
{name: 'descripcion', field: 'id_Maquinaria'},
{name: 'descripcion', field: 'id_tipo_Maquinaria'},
{name: 'Nombre', field: 'kind'},
{name: 'Nombre', field: 'nombre'},
{name: 'Nombre', field: 'visible'}
];
grid = new Grid({
cacheClass: Cache,
store: store,
structure:columns
}, 'gridNode');
grid.startup();
});
Perhaps this can help you, I had a similar problem. If you don't have a column id it doesn't work right. But if you adjust your store to something like this:
var store = new Memory({
data: data,
idProperty: 'descripcion'
});
Perhaps the "new Memory" is not necassary. In my case this works (but I didn't tested it here again). I have no id but I have another unique field instead of this. I suppose it is because of your
{name: 'id', field: 'descripcion'}
If you use instead of "descripcion" the name "id" I think it should work too.
Just add "idProperty" for Gridx, I solved my problem
My dynamic data:
var data = [{"ID":"1","Số liệu thống kê":"Năng suất lập trình","Ngôn ngữ LT":"Java Web","Công đoạn":"Code - Review Code","Loại Project":"Customize/Full","Đơn vị tính":"KLOC/ManMonth","UCD1":"11.6","ITS":null},{"ID":"2","Số liệu thống kê":"Năng suất lập trình","Ngôn ngữ LT":"Java Web","Công đoạn":"Code - Review Code - UT","Loại Project":"Customize/Full","Đơn vị tính":"KLOC/ManMonth","UCD1":"4.6","ITS":null},{"ID":"3","Số liệu thống kê":"Năng suất lập trình","Ngôn ngữ LT":"Java Web","Công đoạn":"Code","Loại Project":"Customize/Full","Đơn vị tính":"KLOC/ManMonth","UCD1":"15.15","ITS":null}];
require([
'dojo/store/Memory',
'gridx/Grid',
'gridx/core/model/cache/Sync'
], function (Memory, Grid, Cache) {
var store = new Memory({
data: data,
idProperty: 'ID'
});
Hope this help