0

I have an SearchStringTooltip ManagedObject. With property @dynamic tooltipText; (NSString)

I need to dynamically add new tooltips in database, but I need only unique values (insensitive).

They could come in more than 100 per one time; and every time I check for unique..

It looks like:

    if (newTooltips.count == 0)
        return;

    NSEntityDescription *entity = [NSEntityDescription
                                   entityForName:@"SearchStringTooltip"
                                   inManagedObjectContext:self.moc];
    NSFetchRequest *request = [NSFetchRequest new];
    [request setEntity:entity];

       for (NSString *name in newTooltips) {

        [request setPredicate:[NSPredicate predicateWithFormat:@"tooltipText = %@", name]]; //like = (=) + time *2(sometimes *3) ofcourse i know i need like.. Its insensitive

        NSInteger count = [self.moc countForFetchRequest:request error:nil]; //But its is very expensive operation expensive
        if (count > 0) {
            continue;
        }

        DBSearchStringTooltip *tooltip = [NSEntityDescription insertNewObjectForEntityForName:@"SearchStringTooltip"
                                                                       inManagedObjectContext:self.moc];
        tooltip.tooltipText = name;
    }

How can I do it more cheaply for memory? There can be > 10 000 tooltips for check unique... And I have to check them all.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Evgeniy S
  • 1,464
  • 12
  • 32

2 Answers2

1

You may try to fetch only distinct tooltipText via NSDictionaryResultType result type of the fetch request and setReturnsDistinctResults:YES. Then search the results in memory. This could be much faster then 10k fetches, as far as fetch always hits the disk. You may find more info here.

MANIAK_dobrii
  • 6,014
  • 3
  • 28
  • 55
1

Quick answer and I am sure more efficient. Use this code snippet instead of your loop:

[request setPredicate:[NSPredicate predicateWithFormat:@"tooltipText IN %@", newTooltips]]; 
[request setResultType:NSDictionaryResultType];
[request setPropertiesToFetch:@[@"tooltipText"]];

NSArray* result = [self.moc executeFetchRequest:request error:nil]; 
NSArray* existingTooltipNames = [result valueForKey:@"tooltipText"]; 

NSMutableOrderedSet* itemsToAdd = [NSMutableOrderedSet orderedSetWithArray:newTooltips];
[itemsToAdd minusSet:[NSSet setWithArray:existingTooltipNames]];
for (NSString *name in itemsToAdd) {
    DBSearchStringTooltip *tooltip = [NSEntityDescription insertNewObjectForEntityForName:@"SearchStringTooltip" inManagedObjectContext:self.moc];
    tooltip.tooltipText = name;
}
Mark Kryzhanouski
  • 7,251
  • 2
  • 22
  • 22
  • And what point of line [request setPredicate:[NSPredicate predicateWithFormat:@"tooltipText IN %@", newTooltips]]; [request setResultType:NSDictionaryResultType]; I can't understand.. If i comment it - it works fine.. – Evgeniy S Mar 21 '13 at 10:26
  • `[request setPredicate:[NSPredicate predicateWithFormat:@"tooltipText IN %@", newTooltips]];` allow you to return only those items which field 'tooltipText' is presented in newTooltips array. – Mark Kryzhanouski Mar 21 '13 at 10:55
  • `[request setResultType:NSDictionaryResultType];` works in conjunction with `[request setPropertiesToFetch:@[@"tooltipText"]];` and allow you fetch only desired fields to decrease memory impact. – Mark Kryzhanouski Mar 21 '13 at 10:57
  • Use `NSMutableSet` instead of `NSMutableOrderedSet`. The result will be pretty the same. Hope now is more clear. – Mark Kryzhanouski Mar 21 '13 at 10:59
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/26634/discussion-between-evgeniy-s-and-mark-kryzhanouski) – Evgeniy S Mar 21 '13 at 11:45