objective c - NSTokenField representing Core Data to-many relationship -
i'm having problem figuring out how represent many-to-many relationship model in nstokenfield. have 2 (relevant) models:
item tag
an item can have many tags , tag can have many items. it's inverse to-many relationship.
what represent these tags in nstokenfield. end tokenfield automatically suggesting matches (found out way tokenfield:completionsforsubstring:indexoftoken:indexofselecteditem) , being able add new tag entities if wasn't matched existing one.
okay, hope you're still me. i'm trying bindings , array controllers (since makes sense, right?)
i have array controller, "item array controller", bound app delegates managedobjectcontext. tableview showing items has binding array controller.
my nstokenfield's value has binding array controllers selection key , model key path: tags.
with config, nstokenfield won't show tags. gives me:
<nstokenfieldcell: 0x10014dc60>: unknown object type assigned (relationship objects {( <nsmanagedobject: 0x10059bdc0> (entity: tag; id: 0x10016d6e0 <x-coredata://9d77d47a-1171-4397-9777-706f599d7e3b/tag/p102> ; data: <fault>) )} on 0x100169660). ignoring...
this makes sense me, no worries. i've looked @ of nstokenfield delegate methods , seems should use:
- (nsstring *)tokenfield:(nstokenfield *)tokenfield displaystringforrepresentedobject:(id)representedobject
problem is, method not called , same error before.
alright, next move try , make valuetransformer. transforming array tag entity -> array strings (tag names) good. other way more challenging.
what i've tried every name in shared app delegate managed object context , return matching tags. gives me problem different managed object contexts apparently:
illegal attempt establish relationship 'tags' between objects in different contexts (source = <nsmanagedobject: 0x100156900> (entity: item; id: 0x1003b22b0 <x-coredata://9d77d47a-1171-4397-9777-706f599d7e3b/item/p106> ; data: { author = "0x1003b1b30 <x-coredata://9d77d47a-1171-4397-9777-706f599d7e3b/author/p103>"; createdat = nil; filepath = nil; tags = ( ); title = "great presentation"; type = "0x1003b1150 <x-coredata://9d77d47a-1171-4397-9777-706f599d7e3b/type/p104>"; }) , destination = <nsmanagedobject: 0x114d08100> (entity: tag; id: 0x100146b40 <x-coredata://9d77d47a-1171-4397-9777-706f599d7e3b/tag/p102> ; data: <fault>))
where going wrong? how resolve this? right approach (seems weird me woud have use valuetransformer?)
thanks in advance!
i've written custom nsvaluetransformer
map between bound nsmanagedobject/tag
nsset
, nsstring
nsarray
of token field. here 2 methods:
- (id)transformedvalue:(id)value { if ([value iskindofclass:[nsset class]]) { nsset *set = (nsset *)value; nsmutablearray *ary = [nsmutablearray arraywithcapacity:[set count]]; (tag *tag in [set allobjects]) { [ary addobject:tag.name]; } return ary; } return nil; } - (id)reversetransformedvalue:(id)value { if ([value iskindofclass:[nsarray class]]) { nsarray *ary = (nsarray *)value; // check each nsstring in array representing tag name if corresponding // tag managed object exists nsmutableset *tagset = [nsmutableset setwithcapacity:[ary count]]; (nsstring *tagname in ary) { nsmanagedobjectcontext *context = [[nsapp delegate] managedobjectcontext]; nsfetchrequest *request = [[nsfetchrequest alloc] init]; nspredicate *searchfilter = [nspredicate predicatewithformat:@"name = %@", tagname]; nsentitydescription *entity = [nsentitydescription entityforname:[tag classname] inmanagedobjectcontext:context]; [request setentity:entity]; [request setpredicate:searchfilter]; nserror *error = nil; nsarray *results = [context executefetchrequest:request error:&error]; if ([results count] > 0) { [tagset addobjectsfromarray:results]; } else { tag *tag = [[tag alloc] initwithentity:entity insertintomanagedobjectcontext:context]; tag.name = tagname; [tagset addobject:tag]; [tag release]; } } return tagset; } return nil; }
coredata seems automatically establish object relationships on return (but have not verified yet)
hope helps.
Comments
Post a Comment