Maciej Swic
Maciej Swic

Reputation: 11359

NSCache isn't returning data the first time it's asked

for my app i have to convert some HTML into NSAttributedStrings in tableViews. This is a very CPU intensive operation so i decided to leverage NSCache to effectively cut this time in half since the HTML is converted twice, once to measure the size of the cell and once more to draw the cell.

The problem is that the first time the cache is queried for the object, it returns nil like if it was never sent to the cache.

Both requests are made on the same queue (main), i have verified that the cache key is the same and that the cache in use is the same. What am i doing wrong?

There is my code:

#import "HITProduct+Cache.h"

@implementation HITProduct (Cache)

static NSCache *cache;

- (NSAttributedString *)attributedString
{
    @synchronized(cache) {
        if (!cache) {
            cache = [NSCache new];
            cache.evictsObjectsWithDiscardedContent = NO;
            cache.countLimit = 10;
        }
    }

    NSMutableAttributedString *attributedString;
    @synchronized(cache) {
        attributedString = [cache objectForKey:self.title];
    }

    if (!attributedString) {
        attributedString = [[[NSAttributedString alloc] initWithData:[self.title dataUsingEncoding:self.title.fastestEncoding] options:@{NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType} documentAttributes:nil error:nil] mutableCopy]; //This is very slow

        @synchronized(cache) {
            [cache setObject:attributedString forKey:self.title];
        }
    }

    return [attributedString copy];
}

@end

Upvotes: 1

Views: 508

Answers (1)

Krzysztof
Krzysztof

Reputation: 1471

Could you try this code (no @synchronized and ARC enabled):

- (NSAttributedString *)attributedString {
    if(self.title == nil){ return nil; }

    static NSCache *cache = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        cache = [NSCache new];
        cache.evictsObjectsWithDiscardedContent = NO;
        cache.countLimit = 10;
    });


    NSAttributedString *attributedString = [cache objectForKey:self.title];
    if (!attributedString) {
        attributedString = [[NSAttributedString alloc] initWithData:[self.title dataUsingEncoding:self.title.fastestEncoding]
                                                            options:@{NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType}
                                                 documentAttributes:nil error:nil];

        [cache setObject:attributedString forKey:self.title];
    }

    return attributedString;
}

Upvotes: 1

Related Questions