ios - CoreData Sort by relation -
my relation shown on picture below.
i'd sort events first in active promotion , start date. promotion active if current date between start , end date. unfortunately, because of coredata, i'm not able use transient properties sorting. in controller i'm not using fetch controller.
is there way achieve that?
update:
i've following sort descriptors:
// first incorrect [nssortdescriptor(key: "promotion.start", ascending: false), nssortdescriptor(key: "start", ascending: true)]
predicates (they're ok, though):
let promotionspredicate = nspredicate(format: "(%@ >= promotion.start && %@ <= promotion.end) && " + "(any promotion.cities.id == %@)", nsdate(), nsdate(), objectid) let eventspredicate = nspredicate(format: "start >= %@ && venue.city.id == %@", nsdate(), objectid) let subpredicates = [eventspredicate, promotionspredicate] let compoundpredicate nscompoundpredicate(orpredicatewithsubpredicates: subpredicates)
and request (i'm using corestore, idea should clear):
class func pagedeventsforpredicatesortedbyinpromoandstartdate(predicate: nspredicate, descriptors: [nssortdescriptor], fetchoffset: int, fetchlimit: int) -> [event] { return corestore.fetchall(from(event), where(predicate), orderby(descriptors), tweak { (fetchrequest) -> void in fetchrequest.fetchoffset = fetchoffset fetchrequest.fetchlimit = fetchlimit fetchrequest.returnsobjectsasfaults = false }) ?? [] }
as understood have event
objects, in proper order. such complicated order, includes relationship, far know have fetch events , sort them using nsarray's
method
- (nsarray<objecttype> *)sortedarrayusingcomparator:(nscomparator)cmptr
here pieces of code
1. fetch core data
// right context here nsmanagedobjectcontext *yourcontext; nsfetchrequest *request = [nsfetchrequest fetchrequestwithentityname:@"event"]; // line, predicate nil default, other required predicate written here request.predicate = nil; __block nsarray *results = nil; [yourcontext performblockandwait:^{ nserror *error = nil; results = [yourcontext executefetchrequest:request error:&error]; if (error) { // handle error here } }];
fetch made manually core methods , may use magical record
or other framework works core data make in row.
2. sort results
__weak typeof(self) weakself = self; nsdate *now = [nsdate date]; nsarray *sortedresults = [results sortedarrayusingcomparator:^nscomparisonresult(event *_nonnull obj1, event *_nonnull obj2) { bool isobj1inactivepromotion = [weakself date:now isbetweendate:obj1.promotion.start anddate:obj1.promotion.end]; bool isobj2inactivepromotion = [weakself date:now isbetweendate:obj2.promotion.start anddate:obj2.promotion.end]; // if eather in active promotion or no, compare them start date of event if (isobj1inactivepromotion == isobj2inactivepromotion) { return [obj1.start compare:obj2.start]; } else { return isobj1inactivepromotion ? nsorderedascending : nsordereddescending; } }];
3. additional method work nsdate
this method used in sorting method
+ (bool)date:(nsdate *)date isbetweendate:(nsdate *)begindate anddate:(nsdate *)enddate { if ([date compare:begindate] == nsorderedascending) { return no; } if ([date compare:enddate] == nsordereddescending) { return no; } return yes; }
i could't check code obvious reasons, sorry typos if are.
Comments
Post a Comment