mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-23 11:57:46 +08:00
[React Native] Update native error callback handling
Summary: This introduces a new `RCTResponseErrorBlock` block type that allows a bridge module writer to call it with an `NSError` instance rather than a dictionary.
This commit is contained in:
@@ -10,19 +10,20 @@
|
||||
#import <AdSupport/ASIdentifierManager.h>
|
||||
|
||||
#import "RCTAdSupport.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@implementation RCTAdSupport
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
RCT_EXPORT_METHOD(getAdvertisingId:(RCTResponseSenderBlock)callback
|
||||
withErrorCallback:(RCTResponseSenderBlock)errorCallback)
|
||||
withErrorCallback:(RCTResponseErrorBlock)errorCallback)
|
||||
{
|
||||
NSUUID *advertisingIdentifier = [ASIdentifierManager sharedManager].advertisingIdentifier;
|
||||
if (advertisingIdentifier) {
|
||||
callback(@[advertisingIdentifier.UUIDString]);
|
||||
} else {
|
||||
errorCallback(@[@"as_identifier_unavailable"]);
|
||||
errorCallback(RCTErrorWithMessage(@"Advertising identifier is unavailable."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#import "RCTImageLoader.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@implementation RCTCameraRollManager
|
||||
|
||||
@@ -23,21 +24,20 @@ RCT_EXPORT_MODULE()
|
||||
|
||||
RCT_EXPORT_METHOD(saveImageWithTag:(NSString *)imageTag
|
||||
successCallback:(RCTResponseSenderBlock)successCallback
|
||||
errorCallback:(RCTResponseSenderBlock)errorCallback)
|
||||
errorCallback:(RCTResponseErrorBlock)errorCallback)
|
||||
{
|
||||
[RCTImageLoader loadImageWithTag:imageTag callback:^(NSError *loadError, UIImage *loadedImage) {
|
||||
if (loadError) {
|
||||
errorCallback(@[[loadError localizedDescription]]);
|
||||
errorCallback(loadError);
|
||||
return;
|
||||
}
|
||||
[[RCTImageLoader assetsLibrary] writeImageToSavedPhotosAlbum:[loadedImage CGImage] metadata:nil completionBlock:^(NSURL *assetURL, NSError *saveError) {
|
||||
if (saveError) {
|
||||
NSString *errorMessage = [NSString stringWithFormat:@"Error saving cropped image: %@", saveError];
|
||||
RCTLogWarn(@"%@", errorMessage);
|
||||
errorCallback(@[errorMessage]);
|
||||
return;
|
||||
RCTLogWarn(@"Error saving cropped image: %@", saveError);
|
||||
errorCallback(saveError);
|
||||
} else {
|
||||
successCallback(@[[assetURL absoluteString]]);
|
||||
}
|
||||
successCallback(@[[assetURL absoluteString]]);
|
||||
}];
|
||||
}];
|
||||
}
|
||||
@@ -63,7 +63,7 @@ RCT_EXPORT_METHOD(saveImageWithTag:(NSString *)imageTag
|
||||
|
||||
RCT_EXPORT_METHOD(getPhotos:(NSDictionary *)params
|
||||
callback:(RCTResponseSenderBlock)callback
|
||||
errorCallback:(RCTResponseSenderBlock)errorCallback)
|
||||
errorCallback:(RCTResponseErrorBlock)errorCallback)
|
||||
{
|
||||
NSUInteger first = [params[@"first"] integerValue];
|
||||
NSString *afterCursor = params[@"after"];
|
||||
@@ -160,7 +160,7 @@ RCT_EXPORT_METHOD(getPhotos:(NSDictionary *)params
|
||||
if (error.code != ALAssetsLibraryAccessUserDeniedError) {
|
||||
RCTLogError(@"Failure while iterating through asset groups %@", error);
|
||||
}
|
||||
errorCallback(@[error.description]);
|
||||
errorCallback(error);
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,12 @@
|
||||
*/
|
||||
typedef void (^RCTResponseSenderBlock)(NSArray *response);
|
||||
|
||||
/**
|
||||
* The type of a block that is capable of sending an error response to a
|
||||
* bridged operation. Use this for returning error information to JS.
|
||||
*/
|
||||
typedef void (^RCTResponseErrorBlock)(NSError *error);
|
||||
|
||||
/**
|
||||
* Block that bridge modules use to resolve the JS promise waiting for a result.
|
||||
* Nil results are supported and are converted to JS's undefined value.
|
||||
|
||||
@@ -174,6 +174,22 @@ case _value: { \
|
||||
}
|
||||
} else if ([argumentName isEqualToString:@"RCTResponseSenderBlock"]) {
|
||||
addBlockArgument();
|
||||
} else if ([argumentName isEqualToString:@"RCTResponseErrorBlock"]) {
|
||||
RCT_ARG_BLOCK(
|
||||
|
||||
if (RCT_DEBUG && json && ![json isKindOfClass:[NSNumber class]]) {
|
||||
RCTLogError(@"Argument %tu (%@) of %@.%@ should be a number", index,
|
||||
json, RCTBridgeModuleNameForClass(_moduleClass), _JSMethodName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Marked as autoreleasing, because NSInvocation doesn't retain arguments
|
||||
__autoreleasing id value = (json ? ^(NSError *error) {
|
||||
[bridge _invokeAndProcessModule:@"BatchedBridge"
|
||||
method:@"invokeCallbackAndReturnFlushedQueue"
|
||||
arguments:@[json, @[RCTJSErrorFromNSError(error)]]];
|
||||
} : ^(__unused NSError *error) {});
|
||||
)
|
||||
} else if ([argumentName isEqualToString:@"RCTPromiseResolveBlock"]) {
|
||||
RCTAssert(i == numberOfArguments - 2,
|
||||
@"The RCTPromiseResolveBlock must be the second to last parameter in -[%@ %@]",
|
||||
|
||||
@@ -45,7 +45,6 @@ RCT_EXTERN BOOL RCTClassOverridesClassMethod(Class cls, SEL selector);
|
||||
RCT_EXTERN BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector);
|
||||
|
||||
// Creates a standardized error object
|
||||
// TODO(#6472857): create NSErrors and automatically convert them over the bridge.
|
||||
RCT_EXTERN NSDictionary *RCTMakeError(NSString *message, id toStringify, NSDictionary *extraData);
|
||||
RCT_EXTERN NSDictionary *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary *extraData);
|
||||
|
||||
@@ -55,7 +54,7 @@ RCT_EXTERN BOOL RCTRunningInTestEnvironment(void);
|
||||
// Return YES if image has an alpha component
|
||||
RCT_EXTERN BOOL RCTImageHasAlpha(CGImageRef image);
|
||||
|
||||
// Create an NSError in the NCTErrorDomain
|
||||
// Create an NSError in the RCTErrorDomain
|
||||
RCT_EXTERN NSError *RCTErrorWithMessage(NSString *message);
|
||||
|
||||
// Convert nil values to NSNull, and vice-versa
|
||||
|
||||
@@ -231,12 +231,11 @@ BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector)
|
||||
NSDictionary *RCTMakeError(NSString *message, id toStringify, NSDictionary *extraData)
|
||||
{
|
||||
if (toStringify) {
|
||||
message = [NSString stringWithFormat:@"%@%@", message, toStringify];
|
||||
}
|
||||
NSMutableDictionary *error = [@{@"message": message} mutableCopy];
|
||||
if (extraData) {
|
||||
[error addEntriesFromDictionary:extraData];
|
||||
message = [message stringByAppendingString:[toStringify description]];
|
||||
}
|
||||
|
||||
NSMutableDictionary *error = [NSMutableDictionary dictionaryWithDictionary:extraData];
|
||||
error[@"message"] = message;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user