From 274c9f713dffca79e710a3f19f68c3a16ac88528 Mon Sep 17 00:00:00 2001 From: Rad Azzouz Date: Wed, 24 Jul 2019 12:21:20 -0400 Subject: [PATCH 1/2] Improve error handline for annotation manipulations functions --- .../Converters/RCTConvert+PSPDFAnnotation.h | 2 +- .../Converters/RCTConvert+PSPDFAnnotation.m | 8 +- ios/RCTPSPDFKit/RCTPSPDFKitView.h | 10 +-- ios/RCTPSPDFKit/RCTPSPDFKitView.m | 82 +++++++++---------- ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m | 27 +++--- samples/Catalog/Catalog.ios.js | 70 +++++++++++++--- 6 files changed, 127 insertions(+), 72 deletions(-) diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.h b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.h index 300d02cb..d208c9c8 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.h +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.h @@ -13,7 +13,7 @@ @interface RCTConvert (PSPDFAnnotation) -+ (NSArray *)instantJSONFromAnnotations:(NSArray *) annotations; ++ (NSArray *)instantJSONFromAnnotations:(NSArray *) annotations error:(NSError **)error; + (PSPDFAnnotationType)annotationTypeFromInstantJSONType:(NSString *)type; @end diff --git a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.m b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.m index 920111bb..6e1222b2 100644 --- a/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.m +++ b/ios/RCTPSPDFKit/Converters/RCTConvert+PSPDFAnnotation.m @@ -11,13 +11,13 @@ @implementation RCTConvert (PSPDFAnnotation) -+ (NSArray *)instantJSONFromAnnotations:(NSArray *) annotations { ++ (NSArray *)instantJSONFromAnnotations:(NSArray *) annotations error:(NSError **)error { NSMutableArray *annotationsJSON = [NSMutableArray new]; for (PSPDFAnnotation *annotation in annotations) { NSDictionary *uuidDict = @{@"uuid" : annotation.uuid}; - NSData *annotationData = [annotation generateInstantJSONWithError:NULL]; + NSData *annotationData = [annotation generateInstantJSONWithError:error]; if (annotationData) { - NSMutableDictionary *annotationDictionary = [[NSJSONSerialization JSONObjectWithData:annotationData options:kNilOptions error:NULL] mutableCopy]; + NSMutableDictionary *annotationDictionary = [[NSJSONSerialization JSONObjectWithData:annotationData options:kNilOptions error:error] mutableCopy]; [annotationDictionary addEntriesFromDictionary:uuidDict]; if (annotationDictionary) { [annotationsJSON addObject:annotationDictionary]; @@ -27,7 +27,7 @@ @implementation RCTConvert (PSPDFAnnotation) [annotationsJSON addObject:uuidDict]; } } - + return [annotationsJSON copy]; } diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitView.h b/ios/RCTPSPDFKit/RCTPSPDFKitView.h index 00ab8a09..85fe2b87 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitView.h +++ b/ios/RCTPSPDFKit/RCTPSPDFKitView.h @@ -36,14 +36,14 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)exitCurrentlyActiveMode; /// Document -- (BOOL)saveCurrentDocument; +- (BOOL)saveCurrentDocumentWithError:(NSError *_Nullable *)error; /// Anotations -- (NSDictionary *> *)getAnnotations:(PSPDFPageIndex)pageIndex type:(PSPDFAnnotationType)type; -- (BOOL)addAnnotation:(id)jsonAnnotation; +- (NSDictionary *> *)getAnnotations:(PSPDFPageIndex)pageIndex type:(PSPDFAnnotationType)type error:(NSError *_Nullable *)error; +- (BOOL)addAnnotation:(id)jsonAnnotation error:(NSError *_Nullable *)error; - (BOOL)removeAnnotationWithUUID:(NSString *)annotationUUID; -- (NSDictionary *> *)getAllUnsavedAnnotations; -- (BOOL)addAnnotations:(NSString *)jsonAnnotations; +- (NSDictionary *> *)getAllUnsavedAnnotationsWithError:(NSError *_Nullable *)error; +- (BOOL)addAnnotations:(NSString *)jsonAnnotations error:(NSError *_Nullable *)error; /// Forms - (NSDictionary *)getFormFieldValue:(NSString *)fullyQualifiedName; diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitView.m b/ios/RCTPSPDFKit/RCTPSPDFKitView.m index 6378e840..03f4d243 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitView.m +++ b/ios/RCTPSPDFKit/RCTPSPDFKitView.m @@ -29,12 +29,12 @@ - (instancetype)initWithFrame:(CGRect)frame { _pdfController.delegate = self; _pdfController.annotationToolbarController.delegate = self; _closeButton = [[UIBarButtonItem alloc] initWithImage:[PSPDFKit imageNamed:@"x"] style:UIBarButtonItemStylePlain target:self action:@selector(closeButtonPressed:)]; - + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationChangedNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationsAddedNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(annotationChangedNotification:) name:PSPDFAnnotationsRemovedNotification object:nil]; } - + return self; } @@ -48,27 +48,27 @@ - (void)didMoveToWindow { if (controller == nil || self.window == nil || self.topController != nil) { return; } - + if (self.pdfController.configuration.useParentNavigationBar || self.hideNavigationBar) { self.topController = self.pdfController; - + } else { self.topController = [[PSPDFNavigationController alloc] initWithRootViewController:self.pdfController];; } - + UIView *topControllerView = self.topController.view; topControllerView.translatesAutoresizingMaskIntoConstraints = NO; - + [self addSubview:topControllerView]; [controller addChildViewController:self.topController]; [self.topController didMoveToParentViewController:controller]; - + [NSLayoutConstraint activateConstraints: @[[topControllerView.topAnchor constraintEqualToAnchor:self.topAnchor], [topControllerView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], [topControllerView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], [topControllerView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor], - ]]; + ]]; } - (void)destroyViewControllerRelationship { @@ -81,7 +81,7 @@ - (void)destroyViewControllerRelationship { - (void)closeButtonPressed:(nullable id)sender { if (self.onCloseButtonPressed) { self.onCloseButtonPressed(@{}); - + } else { // try to be smart and pop if we are not displayed modally. BOOL shouldDismiss = YES; @@ -119,8 +119,8 @@ - (BOOL)exitCurrentlyActiveMode { return [self.pdfController.annotationToolbarController hideToolbarAnimated:YES]; } -- (BOOL)saveCurrentDocument { - return [self.pdfController.document saveWithOptions:nil error:NULL]; +- (BOOL)saveCurrentDocumentWithError:(NSError *_Nullable *)error { + return [self.pdfController.document saveWithOptions:nil error:error]; } #pragma mark - PSPDFDocumentDelegate @@ -161,7 +161,7 @@ - (void)pdfViewController:(PSPDFViewController *)pdfController willBeginDisplayi } - (void)pdfViewController:(PSPDFViewController *)pdfController didChangeDocument:(nullable PSPDFDocument *)document { - VALIDATE_DOCUMENT(document) + VALIDATE_DOCUMENT(document) } #pragma mark - PSPDFFlexibleToolbarContainerDelegate @@ -180,21 +180,21 @@ - (void)flexibleToolbarContainerDidHide:(PSPDFFlexibleToolbarContainer *)contain #pragma mark - Instant JSON -- (NSDictionary *> *)getAnnotations:(PSPDFPageIndex)pageIndex type:(PSPDFAnnotationType)type { +- (NSDictionary *> *)getAnnotations:(PSPDFPageIndex)pageIndex type:(PSPDFAnnotationType)type error:(NSError *_Nullable *)error { PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, nil); - + NSArray *annotations = [document annotationsForPageAtIndex:pageIndex type:type]; - NSArray *annotationsJSON = [RCTConvert instantJSONFromAnnotations:annotations]; + NSArray *annotationsJSON = [RCTConvert instantJSONFromAnnotations:annotations error:error]; return @{@"annotations" : annotationsJSON}; } -- (BOOL)addAnnotation:(id)jsonAnnotation { +- (BOOL)addAnnotation:(id)jsonAnnotation error:(NSError *_Nullable *)error { NSData *data; if ([jsonAnnotation isKindOfClass:NSString.class]) { data = [jsonAnnotation dataUsingEncoding:NSUTF8StringEncoding]; } else if ([jsonAnnotation isKindOfClass:NSDictionary.class]) { - data = [NSJSONSerialization dataWithJSONObject:jsonAnnotation options:0 error:nil]; + data = [NSJSONSerialization dataWithJSONObject:jsonAnnotation options:0 error:error]; } else { NSLog(@"Invalid JSON Annotation."); return NO; @@ -203,17 +203,17 @@ - (BOOL)addAnnotation:(id)jsonAnnotation { PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, NO) PSPDFDocumentProvider *documentProvider = document.documentProviders.firstObject; - + BOOL success = NO; if (data) { - PSPDFAnnotation *annotation = [PSPDFAnnotation annotationFromInstantJSON:data documentProvider:documentProvider error:NULL]; + PSPDFAnnotation *annotation = [PSPDFAnnotation annotationFromInstantJSON:data documentProvider:documentProvider error:error]; success = [document addAnnotations:@[annotation] options:nil]; } - + if (!success) { NSLog(@"Failed to add annotation."); } - + return success; } @@ -221,7 +221,7 @@ - (BOOL)removeAnnotationWithUUID:(NSString *)annotationUUID { PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, NO) BOOL success = NO; - + NSArray *allAnnotations = [[document allAnnotationsOfType:PSPDFAnnotationTypeAll].allValues valueForKeyPath:@"@unionOfArrays.self"]; for (PSPDFAnnotation *annotation in allAnnotations) { // Remove the annotation if the uuids match. @@ -237,22 +237,22 @@ - (BOOL)removeAnnotationWithUUID:(NSString *)annotationUUID { return success; } -- (NSDictionary *> *)getAllUnsavedAnnotations { +- (NSDictionary *> *)getAllUnsavedAnnotationsWithError:(NSError *_Nullable *)error { PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, nil) - + PSPDFDocumentProvider *documentProvider = document.documentProviders.firstObject; - NSData *data = [document generateInstantJSONFromDocumentProvider:documentProvider error:NULL]; - NSDictionary *annotationsJSON = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:NULL]; + NSData *data = [document generateInstantJSONFromDocumentProvider:documentProvider error:error]; + NSDictionary *annotationsJSON = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:error]; return annotationsJSON; } -- (BOOL)addAnnotations:(id)jsonAnnotations { +- (BOOL)addAnnotations:(id)jsonAnnotations error:(NSError *_Nullable *)error { NSData *data; if ([jsonAnnotations isKindOfClass:NSString.class]) { data = [jsonAnnotations dataUsingEncoding:NSUTF8StringEncoding]; } else if ([jsonAnnotations isKindOfClass:NSDictionary.class]) { - data = [NSJSONSerialization dataWithJSONObject:jsonAnnotations options:0 error:nil]; + data = [NSJSONSerialization dataWithJSONObject:jsonAnnotations options:0 error:error]; } else { NSLog(@"Invalid JSON Annotations."); return NO; @@ -262,11 +262,11 @@ - (BOOL)addAnnotations:(id)jsonAnnotations { PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, NO) PSPDFDocumentProvider *documentProvider = document.documentProviders.firstObject; - BOOL success = [document applyInstantJSONFromDataProvider:dataContainerProvider toDocumentProvider:documentProvider lenient:NO error:NULL]; + BOOL success = [document applyInstantJSONFromDataProvider:dataContainerProvider toDocumentProvider:documentProvider lenient:NO error:error]; if (!success) { NSLog(@"Failed to add annotations."); } - + [self.pdfController reloadPageAtIndex:self.pdfController.pageIndex animated:NO]; return success; } @@ -278,7 +278,7 @@ - (BOOL)addAnnotations:(id)jsonAnnotations { NSLog(@"Invalid fully qualified name."); return nil; } - + PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document, nil) @@ -288,7 +288,7 @@ - (BOOL)addAnnotations:(id)jsonAnnotations { return @{@"value": formFieldValue ?: [NSNull new]}; } } - + return @{@"error": @"Failed to get the form field value."}; } @@ -297,7 +297,7 @@ - (void)setFormFieldValue:(NSString *)value fullyQualifiedName:(NSString *)fully NSLog(@"Invalid fully qualified name."); return; } - + PSPDFDocument *document = self.pdfController.document; VALIDATE_DOCUMENT(document) @@ -338,7 +338,7 @@ - (void)annotationChangedNotification:(NSNotification *)notification { } return; } - + NSString *name = notification.name; NSString *change; if ([name isEqualToString:PSPDFAnnotationChangedNotification]) { @@ -348,8 +348,8 @@ - (void)annotationChangedNotification:(NSNotification *)notification { } else if ([name isEqualToString:PSPDFAnnotationsRemovedNotification]) { change = @"removed"; } - - NSArray *annotationsJSON = [RCTConvert instantJSONFromAnnotations:annotations]; + + NSArray *annotationsJSON = [RCTConvert instantJSONFromAnnotations:annotations error:NULL]; if (self.onAnnotationsChanged) { self.onAnnotationsChanged(@{@"change" : change, @"annotations" : annotationsJSON}); } @@ -365,7 +365,7 @@ - (void)setLeftBarButtonItems:(nullable NSArray *)items forViewMode [leftItems addObject:barButtonItem]; } } - + if (viewMode.length) { [self.pdfController.navigationItem setLeftBarButtonItems:[leftItems copy] forViewMode:[RCTConvert PSPDFViewMode:viewMode] animated:animated]; } else { @@ -381,7 +381,7 @@ - (void)setRightBarButtonItems:(nullable NSArray *)items forViewMod [rightItems addObject:barButtonItem]; } } - + if (viewMode.length) { [self.pdfController.navigationItem setRightBarButtonItems:[rightItems copy] forViewMode:[RCTConvert PSPDFViewMode:viewMode] animated:animated]; } else { @@ -396,7 +396,7 @@ - (void)setRightBarButtonItems:(nullable NSArray *)items forViewMod } else { items = [self.pdfController.navigationItem leftBarButtonItems]; } - + return [self buttonItemsStringFromUIBarButtonItems:items]; } @@ -407,7 +407,7 @@ - (void)setRightBarButtonItems:(nullable NSArray *)items forViewMod } else { items = [self.pdfController.navigationItem rightBarButtonItems]; } - + return [self buttonItemsStringFromUIBarButtonItems:items]; } @@ -435,7 +435,7 @@ - (void)onStateChangedForPDFViewController:(PSPDFViewController *)pdfController @"annotationEditingActive" : @(hasSelectedAnnotations), @"textSelectionActive" : @(hasSelectedText), @"formEditingActive" : @(isFormEditingActive) - }); + }); } } diff --git a/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m b/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m index 58e2177d..2638d841 100644 --- a/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m +++ b/ios/RCTPSPDFKit/RCTPSPDFKitViewManager.m @@ -27,7 +27,7 @@ @implementation RCTPSPDFKitViewManager if (json) { view.pdfController.document = [RCTConvert PSPDFDocument:json]; view.pdfController.document.delegate = (id)view; - + // The author name may be set before the document exists. We set it again here when the document exists. if (view.annotationAuthorName) { view.pdfController.document.defaultAnnotationUsername = view.annotationAuthorName; @@ -134,11 +134,12 @@ @implementation RCTPSPDFKitViewManager RCT_EXPORT_METHOD(saveCurrentDocument:(nonnull NSNumber *)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; - BOOL success = [component saveCurrentDocument]; + NSError *error; + BOOL success = [component saveCurrentDocumentWithError:&error]; if (success) { resolve(@(success)); } else { - reject(@"error", @"Failed to save document.", nil); + reject(@"error", @"Failed to save document.", error); } }); } @@ -146,11 +147,12 @@ @implementation RCTPSPDFKitViewManager RCT_REMAP_METHOD(getAnnotations, getAnnotations:(nonnull NSNumber *)pageIndex type:(NSString *)type reactTag:(nonnull NSNumber *)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; - NSDictionary *annotations = [component getAnnotations:(PSPDFPageIndex)pageIndex.integerValue type:[RCTConvert annotationTypeFromInstantJSONType:type]]; + NSError *error; + NSDictionary *annotations = [component getAnnotations:(PSPDFPageIndex)pageIndex.integerValue type:[RCTConvert annotationTypeFromInstantJSONType:type] error:&error]; if (annotations) { resolve(annotations); } else { - reject(@"error", @"Failed to get annotations.", nil); + reject(@"error", @"Failed to get annotations.", error); } }); } @@ -158,11 +160,12 @@ @implementation RCTPSPDFKitViewManager RCT_EXPORT_METHOD(addAnnotation:(id)jsonAnnotation reactTag:(nonnull NSNumber *)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; - BOOL success = [component addAnnotation:jsonAnnotation]; + NSError *error; + BOOL success = [component addAnnotation:jsonAnnotation error:&error]; if (success) { resolve(@(success)); } else { - reject(@"error", @"Failed to add annotation.", nil); + reject(@"error", @"Failed to add annotation.", error); } }); } @@ -182,11 +185,12 @@ @implementation RCTPSPDFKitViewManager RCT_EXPORT_METHOD(getAllUnsavedAnnotations:(nonnull NSNumber *)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; - NSDictionary *annotations = [component getAllUnsavedAnnotations]; + NSError *error; + NSDictionary *annotations = [component getAllUnsavedAnnotationsWithError:&error]; if (annotations) { resolve(annotations); } else { - reject(@"error", @"Failed to get annotations.", nil); + reject(@"error", @"Failed to get annotations.", error); } }); } @@ -194,11 +198,12 @@ @implementation RCTPSPDFKitViewManager RCT_EXPORT_METHOD(addAnnotations:(id)jsonAnnotations reactTag:(nonnull NSNumber *)reactTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(), ^{ RCTPSPDFKitView *component = (RCTPSPDFKitView *)[self.bridge.uiManager viewForReactTag:reactTag]; - BOOL success = [component addAnnotations:jsonAnnotations]; + NSError *error; + BOOL success = [component addAnnotations:jsonAnnotations error:&error]; if (success) { resolve(@(success)); } else { - reject(@"error", @"Failed to add annotations.", nil); + reject(@"error", @"Failed to add annotations.", error); } }); } diff --git a/samples/Catalog/Catalog.ios.js b/samples/Catalog/Catalog.ios.js index a9a60730..9999fecf 100644 --- a/samples/Catalog/Catalog.ios.js +++ b/samples/Catalog/Catalog.ios.js @@ -556,7 +556,18 @@ class ProgrammaticAnnotations extends Component { type: "pspdfkit/ink", v: 1 }; - this.refs.pdfView.addAnnotation(annotationJSON); + this.refs.pdfView + .addAnnotation(annotationJSON) + .then(result => { + if (result) { + alert("Annotation was successfully added."); + } else { + alert("Failed to add annotation."); + } + }) + .catch(error => { + alert(JSON.stringify(error)); + }); }} title="addAnnotation" /> @@ -570,7 +581,18 @@ class ProgrammaticAnnotations extends Component { "pspdfkit/ink" ); const firstInkAnnotation = inkAnnotations["annotations"][0]; - this.refs.pdfView.removeAnnotation(firstInkAnnotation); + this.refs.pdfView + .removeAnnotation(firstInkAnnotation) + .then(result => { + if (result) { + alert("Annotation was successfully removed."); + } else { + alert("Failed to remove annotation."); + } + }) + .catch(error => { + alert(JSON.stringify(error)); + }); }} title="removeAnnotation" /> @@ -705,7 +727,18 @@ class ProgrammaticAnnotations extends Component { ], format: "https://pspdfkit.com/instant-json/v1" }; - this.refs.pdfView.addAnnotations(annotationsJSON); + this.refs.pdfView + .addAnnotations(annotationsJSON) + .then(result => { + if (result) { + alert("Annotations were successfully added."); + } else { + alert("Failed to add annotations."); + } + }) + .catch(error => { + alert(JSON.stringify(error)); + }); }} title="addAnnotations" /> @@ -714,11 +747,18 @@ class ProgrammaticAnnotations extends Component {