Last active
December 14, 2015 14:59
-
-
Save jonnolen/5104724 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@interface PSPDFAnnotation (CustomTransformers) | |
+(NSValueTransformer *)boundingBoxTransformer; | |
+(NSValueTransformer *)rectsTransformer; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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