Skip to content

Instantly share code, notes, and snippets.

@jonnolen
Last active December 14, 2015 14:59
Show Gist options
  • Save jonnolen/5104724 to your computer and use it in GitHub Desktop.
Save jonnolen/5104724 to your computer and use it in GitHub Desktop.
@interface CachedAnnotation : NSObject
@property (nonatomic, strong) NSManagedObjectID *objectId;
@property (nonatomic, strong) PSPDFAnnotation *annotation;
+(CachedAnnotation *)cachedAnnotationWithCoreDataAnnotation:(Annotation *)annotation;
+(CachedAnnotation *)cachedAnnotationWithObjectId:(NSManagedObjectID *)objectId nativeAnnotation:(PSPDFAnnotation *)annotation;
@end
#import "CachedAnnotation.h"
@implementation CachedAnnotation
+(CachedAnnotation *)cachedAnnotationWithCoreDataAnnotation:(Annotation *)annotation{
id objectFromJson = [annotation.annotationJson objectFromJSONString];
NSLog(@"objectFromJsonString: %@", objectFromJson);
PSPDFAnnotation *nativeAnnotation = [PSPDFAnnotation modelWithExternalRepresentation:objectFromJson inFormat:PSPDFModelJSONFormat];
return [self cachedAnnotationWithObjectId:annotation.objectID nativeAnnotation:nativeAnnotation];
}
+(CachedAnnotation *)cachedAnnotationWithObjectId:(NSManagedObjectID *)objectId nativeAnnotation:(PSPDFAnnotation *)annotation{
CachedAnnotation *result = [self new];
result.objectId = objectId;
result.annotation = annotation;
return result;
}
@end
@interface PSPDFAnnotation (CustomTransformers)
+(NSValueTransformer *)boundingBoxTransformer;
+(NSValueTransformer *)rectsTransformer;
@end
#import "PSPDFAnnotation+CustomTransformers.h"
@implementation PSPDFAnnotation (CustomTransformers)
+(NSValueTransformer *)boundingBoxTransformer{
return [PSPDFValueTransformer reversibleTransformerWithForwardBlock:^(NSString *string){
return [NSValue valueWithCGRect:CGRectFromString(string)];
} reverseBlock:^(NSValue *rectValue){
return NSStringFromCGRect(rectValue.CGRectValue);
}];
}
+(NSValueTransformer *)rectsTransformer{
return [PSPDFValueTransformer reversibleTransformerWithForwardBlock:^(NSArray *rectStrings){
return [rectStrings collect:^(NSString *rectString){
return [NSValue valueWithCGRect:CGRectFromString(rectString)];
}];
}
reverseBlock:^(NSArray *rectValues){
return [rectValues collect:^(NSValue *rectValue){
return NSStringFromCGRect(rectValue.CGRectValue);
}];
}];
}
@end
#import "UserCoreDataAnnotationProvider.h"
#import "Annotation.h"
#import "CachedAnnotation.h"
#import "PSPDFAnnotation+CustomTransformers.h"
@interface UserCoreDataAnnotationProvider()
@property (nonatomic, strong) NSMutableDictionary *pageCache;
@property (nonatomic, strong) Packet *packet;
@property (nonatomic, strong) NSString *username;
@end
@implementation UserCoreDataAnnotationProvider
@synthesize providerDelegate;
+(UserCoreDataAnnotationProvider *)coreDataAnnotationProviderWithPacket:(Packet *)packet andUser:(NSString *)username{
UserCoreDataAnnotationProvider *result = [self new];
result.packet = packet;
result.username = username;
return result;
}
-(id)init{
if (self = [super init]){
_pageCache = [NSMutableDictionary dictionaryWithCapacity:1];
}
return self;
}
-(BOOL)addAnnotations:(NSArray *)annotations forPage:(NSUInteger)page{
__block BOOL supportsAllAnnotations = YES;
[annotations enumerateObjectsUsingBlock:^(PSPDFAnnotation *annotation, NSUInteger indx, BOOL *stop){
if ((annotation.type & [self supportedTypes]) != annotation.type){
*stop = YES;
supportsAllAnnotations = NO;
return;
}
}];
if (!supportsAllAnnotations){
return NO;
}
@synchronized(self){
[annotations enumerateObjectsUsingBlock:^(PSPDFAnnotation *annotation, NSUInteger idx, BOOL *stop){
Annotation *coreDataAnnotation = [self saveAnnotation:annotation];
CachedAnnotation *cachedAnnotation = [CachedAnnotation cachedAnnotationWithObjectId:coreDataAnnotation.objectID nativeAnnotation:annotation];
[self cacheAnnotationToProperPage:cachedAnnotation];
}];
}
return YES;
}
- (void) didChangeAnnotation:(PSPDFAnnotation *)annotation originalAnnotation:(PSPDFAnnotation *)originalAnnotation keyPaths:(NSArray *)keyPaths options:(NSDictionary *)options{
@synchronized(self){
CachedAnnotation *cachedAnnotation = [self cachedAnnotationForNativeAnnotation:annotation];
if (cachedAnnotation){
Annotation *coreDataAnnotation = (Annotation *)[[NSManagedObjectContext MR_contextForCurrentThread] objectWithID:cachedAnnotation.objectId];
if ([keyPaths[0] isEqualToString:@"isDeleted"]){
[coreDataAnnotation MR_deleteEntity];
[self deleteAnnotation:cachedAnnotation];
}
else{
coreDataAnnotation.lastModifiedDate = [self dateForAnnotation:annotation];
coreDataAnnotation.content = annotation.contents;
coreDataAnnotation.annotationJson = [self jsonStringForAnnotation:annotation];
}
[coreDataAnnotation.managedObjectContext MR_saveOnlySelfWithCompletion:nil];
annotation.dirty = NO;
}
}
}
-(BOOL)hasLoadedAnnotationsForPage:(NSUInteger)page{
BOOL hasAnnotationsForPage;
@synchronized(self){
hasAnnotationsForPage = (self.pageCache[@(page)] != nil);
}
return hasAnnotationsForPage;
}
- (NSArray *)annotationsForPage:(NSUInteger)page{
NSArray *annotationsForPage = nil;
@synchronized(self) {
NSArray *cachedAnnotationsForPage = [self pageCacheForPage:page];
annotationsForPage = [cachedAnnotationsForPage valueForKey:@"annotation"];
}
return annotationsForPage;
}
-(Annotation *)saveAnnotation:(PSPDFAnnotation *)annotation{
Annotation *result = [Annotation MR_createEntity];
result.packet = self.packet;
result.username = self.username;
result.page = @(annotation.page);
result.annotationType = @(annotation.type);
result.content = annotation.contents;
result.annotationJson = [self jsonStringForAnnotation:annotation];
result.lastModifiedDate = [self dateForAnnotation:annotation];
[result.managedObjectContext MR_saveOnlySelfAndWait];
annotation.dirty = NO;
return result;
}
-(void)cacheAnnotationToProperPage:(CachedAnnotation *)annotation{
NSMutableArray *pageAnnotations = [self pageCacheForPage:annotation.annotation.page];
[pageAnnotations addObject:annotation];
}
-(NSMutableArray *)pageCacheForPage:(NSUInteger)page{
NSMutableArray *pageAnnotations = nil;
if (self.pageCache[@(page)]){
pageAnnotations = self.pageCache[@(page)];
}
else{
//get core data annotations for page.
NSArray *coreDataAnnotations = [self coreDataAnnotationsForPage:page];
pageAnnotations = [NSMutableArray arrayWithCapacity:coreDataAnnotations.count];
//for each core data annotation, create the CacheAnnotation object and add it to pageAnnotations.
[coreDataAnnotations enumerateObjectsUsingBlock:^(Annotation *annotation, NSUInteger idx, BOOL *stop){
[pageAnnotations addObject:[CachedAnnotation cachedAnnotationWithCoreDataAnnotation:annotation]];
}];
self.pageCache[@(page)] = pageAnnotations;
}
return pageAnnotations;
}
-(CachedAnnotation *)cachedAnnotationForNativeAnnotation:(PSPDFAnnotation *)nativeAnnotation{
NSSet *annnotationsForNativeAnnotationPage = self.pageCache[@(nativeAnnotation.page)];
CachedAnnotation *cachedAnnotation = [[annnotationsForNativeAnnotationPage objectsPassingTest:^(CachedAnnotation *ca, BOOL *stop){
return (BOOL)(ca.annotation == nativeAnnotation);
}] anyObject];
return cachedAnnotation;
}
-(NSArray *)coreDataAnnotationsForPage:(NSUInteger)page{
NSFetchRequest *fetchAnnotationsForUserInPacketForPage = [Annotation
MR_requestAllWithPredicate:[NSPredicate
predicateWithFormat:@"packet == %@ AND username == %@ and page == %@",
self.packet,
self.username,
@(page)]];
return [Annotation MR_executeFetchRequest:fetchAnnotationsForUserInPacketForPage];
}
-(NSString *)jsonStringForAnnotation:(PSPDFAnnotation *)annotation{
NSError *error;
id jsonObject = [annotation externalRepresentationInFormat:PSPDFModelJSONFormat];
NSLog(@"json object: %@", jsonObject);
NSString *jsonString = [jsonObject JSONStringWithOptions:JKSerializeOptionNone error:&error];
if (error){
NSLog(@"%@", error);
}
return jsonString;
}
-(void)deleteAnnotation:(CachedAnnotation *)cachedAnnotation{
[self.pageCache[@(cachedAnnotation.annotation.page)] removeObject:cachedAnnotation];
}
-(NSDate *)dateForAnnotation:(PSPDFAnnotation *)annotation{
return (annotation.lastModified ? annotation.lastModified : annotation.creationDate);
}
-(PSPDFAnnotationType)supportedTypes{
return (PSPDFAnnotationTypeHighlight |
PSPDFAnnotationTypeInk |
PSPDFAnnotationTypeNote );
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment