Added lightweight generic annotations

Summary: public

Added lightweight genarics annotations to make the code more readable and help the compiler catch bugs.

Fixed some type bugs and improved bridge validation in a few places.

Reviewed By: javache

Differential Revision: D2600189

fb-gh-sync-id: f81e22f2cdc107bf8d0b15deec6d5b83aacc5b56
This commit is contained in:
Nick Lockwood 2015-11-03 14:45:46 -08:00 committed by facebook-github-bot-7
parent 31565781f2
commit c5b990f65f
78 changed files with 497 additions and 422 deletions

View File

@ -51,7 +51,7 @@
14D6D7291B2222EF001FB087 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14AADF041AC3DB95002390C9 /* libReact.a */; }; 14D6D7291B2222EF001FB087 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14AADF041AC3DB95002390C9 /* libReact.a */; };
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; }; 14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; };
3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; }; 3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; };
3D36915B1BDA8CBB007B22D8 /* uie_thumb_big.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D36915A1BDA8CBB007B22D8 /* uie_thumb_big.png */; settings = {ASSET_TAGS = (); }; }; 3D36915B1BDA8CBB007B22D8 /* uie_thumb_big.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D36915A1BDA8CBB007B22D8 /* uie_thumb_big.png */; };
3DB99D0C1BA0340600302749 /* UIExplorerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DB99D0B1BA0340600302749 /* UIExplorerIntegrationTests.m */; }; 3DB99D0C1BA0340600302749 /* UIExplorerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DB99D0B1BA0340600302749 /* UIExplorerIntegrationTests.m */; };
834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; }; 834C36EC1AF8DED70019C93C /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 834C36D21AF8DA610019C93C /* libRCTSettings.a */; };
83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; }; 83636F8F1B53F22C009F943E /* RCTUIManagerScenarioTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 83636F8E1B53F22C009F943E /* RCTUIManagerScenarioTests.m */; };
@ -1082,6 +1082,7 @@
"$(inherited)", "$(inherited)",
); );
GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
@ -1109,6 +1110,7 @@
WARNING_CFLAGS = ( WARNING_CFLAGS = (
"-Wextra", "-Wextra",
"-Wall", "-Wall",
"-Wincompatible-pointer-types",
); );
}; };
name = Debug; name = Debug;
@ -1139,6 +1141,7 @@
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
@ -1166,6 +1169,7 @@
WARNING_CFLAGS = ( WARNING_CFLAGS = (
"-Wextra", "-Wextra",
"-Wall", "-Wall",
"-Wincompatible-pointer-types",
); );
}; };
name = Release; name = Release;

View File

@ -19,7 +19,7 @@
CGPoint _endPoint; CGPoint _endPoint;
} }
- (instancetype)initWithArray:(NSArray *)array - (instancetype)initWithArray:(NSArray<NSNumber *> *)array
{ {
if ((self = [super initWithArray:array])) { if ((self = [super initWithArray:array])) {
if (array.count < 5) { if (array.count < 5) {

View File

@ -18,7 +18,7 @@
CGRect _rect; CGRect _rect;
} }
- (instancetype)initWithArray:(NSArray *)array - (instancetype)initWithArray:(NSArray<id /* imagesource + numbers */> *)array
{ {
if ((self = [super initWithArray:array])) { if ((self = [super initWithArray:array])) {
if (array.count < 6) { if (array.count < 6) {

View File

@ -21,7 +21,7 @@
CGFloat _radiusRatio; CGFloat _radiusRatio;
} }
- (instancetype)initWithArray:(NSArray *)array - (instancetype)initWithArray:(NSArray<NSNumber *> *)array
{ {
if ((self = [super initWithArray:array])) { if ((self = [super initWithArray:array])) {
if (array.count < 7) { if (array.count < 7) {

View File

@ -17,7 +17,7 @@
CGColorRef _color; CGColorRef _color;
} }
- (instancetype)initWithArray:(NSArray *)array - (instancetype)initWithArray:(NSArray<NSNumber *> *)array
{ {
if ((self = [super initWithArray:array])) { if ((self = [super initWithArray:array])) {
_color = CGColorRetain([RCTConvert CGColor:array offset:1]); _color = CGColorRetain([RCTConvert CGColor:array offset:1]);

View File

@ -62,7 +62,7 @@ RCT_EXPORT_METHOD(showActionSheetWithOptions:(NSDictionary *)options
} }
NSString *title = [RCTConvert NSString:options[@"title"]]; NSString *title = [RCTConvert NSString:options[@"title"]];
NSArray *buttons = [RCTConvert NSStringArray:options[@"options"]]; NSArray<NSString *> *buttons = [RCTConvert NSStringArray:options[@"options"]];
NSInteger destructiveButtonIndex = options[@"destructiveButtonIndex"] ? [RCTConvert NSInteger:options[@"destructiveButtonIndex"]] : -1; NSInteger destructiveButtonIndex = options[@"destructiveButtonIndex"] ? [RCTConvert NSInteger:options[@"destructiveButtonIndex"]] : -1;
NSInteger cancelButtonIndex = options[@"cancelButtonIndex"] ? [RCTConvert NSInteger:options[@"cancelButtonIndex"]] : -1; NSInteger cancelButtonIndex = options[@"cancelButtonIndex"] ? [RCTConvert NSInteger:options[@"cancelButtonIndex"]] : -1;
@ -151,7 +151,7 @@ RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options
return; return;
} }
NSMutableArray *items = [NSMutableArray array]; NSMutableArray<id /* NSString or NSURL */> *items = [NSMutableArray array];
NSString *message = [RCTConvert NSString:options[@"message"]]; NSString *message = [RCTConvert NSString:options[@"message"]];
if (message) { if (message) {
[items addObject:message]; [items addObject:message];

View File

@ -7,7 +7,17 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
#import <AssetsLibrary/AssetsLibrary.h>
#import "RCTBridgeModule.h" #import "RCTBridgeModule.h"
#import "RCTConvert.h"
@interface RCTConvert (ALAssetGroup)
+ (ALAssetsGroupType)ALAssetsGroupType:(id)json;
+ (ALAssetsFilter *)ALAssetsFilter:(id)json;
@end
@interface RCTCameraRollManager : NSObject <RCTBridgeModule> @interface RCTCameraRollManager : NSObject <RCTBridgeModule>

View File

@ -9,17 +9,70 @@
#import "RCTCameraRollManager.h" #import "RCTCameraRollManager.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <CoreLocation/CoreLocation.h> #import <CoreLocation/CoreLocation.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import "RCTAssetsLibraryImageLoader.h" #import "RCTAssetsLibraryImageLoader.h"
#import "RCTBridge.h" #import "RCTBridge.h"
#import "RCTConvert.h"
#import "RCTImageLoader.h" #import "RCTImageLoader.h"
#import "RCTLog.h" #import "RCTLog.h"
#import "RCTUtils.h" #import "RCTUtils.h"
@implementation RCTConvert (ALAssetGroup)
RCT_ENUM_CONVERTER(ALAssetsGroupType, (@{
// New values
@"album": @(ALAssetsGroupAlbum),
@"all": @(ALAssetsGroupAll),
@"event": @(ALAssetsGroupEvent),
@"faces": @(ALAssetsGroupFaces),
@"library": @(ALAssetsGroupLibrary),
@"photo-stream": @(ALAssetsGroupPhotoStream),
@"saved-photos": @(ALAssetsGroupSavedPhotos),
// Legacy values
@"Album": @(ALAssetsGroupAlbum),
@"All": @(ALAssetsGroupAll),
@"Event": @(ALAssetsGroupEvent),
@"Faces": @(ALAssetsGroupFaces),
@"Library": @(ALAssetsGroupLibrary),
@"PhotoStream": @(ALAssetsGroupPhotoStream),
@"SavedPhotos": @(ALAssetsGroupSavedPhotos),
}), ALAssetsGroupSavedPhotos, integerValue)
+ (ALAssetsFilter *)ALAssetsFilter:(id)json
{
static NSDictionary *options;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
options = @{
// New values
@"photos": [ALAssetsFilter allPhotos],
@"videos": [ALAssetsFilter allVideos],
@"all": [ALAssetsFilter allAssets],
// Legacy values
@"Photos": [ALAssetsFilter allPhotos],
@"Videos": [ALAssetsFilter allVideos],
@"All": [ALAssetsFilter allAssets],
};
});
ALAssetsFilter *filter = options[json ?: @"photos"];
if (!filter) {
RCTLogError(@"Invalid filter option: '%@'. Expected one of 'photos',"
"'videos' or 'all'.", json);
}
return filter ?: [ALAssetsFilter allPhotos];
}
@end
@implementation RCTCameraRollManager @implementation RCTCameraRollManager
RCT_EXPORT_MODULE() RCT_EXPORT_MODULE()
@ -49,7 +102,9 @@ RCT_EXPORT_METHOD(saveImageWithTag:(NSString *)imageTag
}]; }];
} }
- (void)callCallback:(RCTResponseSenderBlock)callback withAssets:(NSArray *)assets hasNextPage:(BOOL)hasNextPage - (void)callCallback:(RCTResponseSenderBlock)callback
withAssets:(NSArray<NSDictionary *> *)assets
hasNextPage:(BOOL)hasNextPage
{ {
if (!assets.count) { if (!assets.count) {
callback(@[@{ callback(@[@{
@ -72,45 +127,21 @@ RCT_EXPORT_METHOD(getPhotos:(NSDictionary *)params
callback:(RCTResponseSenderBlock)callback callback:(RCTResponseSenderBlock)callback
errorCallback:(RCTResponseErrorBlock)errorCallback) errorCallback:(RCTResponseErrorBlock)errorCallback)
{ {
NSUInteger first = [params[@"first"] integerValue]; NSUInteger first = [RCTConvert NSInteger:params[@"first"]];
NSString *afterCursor = params[@"after"]; NSString *afterCursor = [RCTConvert NSString:params[@"after"]];
NSString *groupTypesStr = params[@"groupTypes"]; NSString *groupName = [RCTConvert NSString:params[@"groupName"]];
NSString *groupName = params[@"groupName"]; ALAssetsFilter *assetType = [RCTConvert ALAssetsFilter:params[@"assetType"]];
NSString *assetType = params[@"assetType"]; ALAssetsGroupType groupTypes = [RCTConvert ALAssetsGroupType:params[@"groupTypes"]];
ALAssetsGroupType groupTypes;
if ([groupTypesStr isEqualToString:@"Album"]) {
groupTypes = ALAssetsGroupAlbum;
} else if ([groupTypesStr isEqualToString:@"All"]) {
groupTypes = ALAssetsGroupAll;
} else if ([groupTypesStr isEqualToString:@"Event"]) {
groupTypes = ALAssetsGroupEvent;
} else if ([groupTypesStr isEqualToString:@"Faces"]) {
groupTypes = ALAssetsGroupFaces;
} else if ([groupTypesStr isEqualToString:@"Library"]) {
groupTypes = ALAssetsGroupLibrary;
} else if ([groupTypesStr isEqualToString:@"PhotoStream"]) {
groupTypes = ALAssetsGroupPhotoStream;
} else {
groupTypes = ALAssetsGroupSavedPhotos;
}
BOOL __block foundAfter = NO; BOOL __block foundAfter = NO;
BOOL __block hasNextPage = NO; BOOL __block hasNextPage = NO;
BOOL __block calledCallback = NO; BOOL __block calledCallback = NO;
NSMutableArray *assets = [NSMutableArray new]; NSMutableArray<NSDictionary *> *assets = [NSMutableArray new];
[_bridge.assetsLibrary enumerateGroupsWithTypes:groupTypes usingBlock:^(ALAssetsGroup *group, BOOL *stopGroups) { [_bridge.assetsLibrary enumerateGroupsWithTypes:groupTypes usingBlock:^(ALAssetsGroup *group, BOOL *stopGroups) {
if (group && (groupName == nil || [groupName isEqualToString:[group valueForProperty:ALAssetsGroupPropertyName]])) { if (group && (groupName == nil || [groupName isEqualToString:[group valueForProperty:ALAssetsGroupPropertyName]])) {
if (assetType == nil || [assetType isEqualToString:@"Photos"]) { [group setAssetsFilter:assetType];
[group setAssetsFilter:ALAssetsFilter.allPhotos];
} else if ([assetType isEqualToString:@"Videos"]) {
[group setAssetsFilter:ALAssetsFilter.allVideos];
} else if ([assetType isEqualToString:@"All"]) {
[group setAssetsFilter:ALAssetsFilter.allAssets];
}
[group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stopAssets) { [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stopAssets) {
if (result) { if (result) {
NSString *uri = ((NSURL *)[result valueForProperty:ALAssetPropertyAssetURL]).absoluteString; NSString *uri = ((NSURL *)[result valueForProperty:ALAssetPropertyAssetURL]).absoluteString;

View File

@ -23,9 +23,9 @@
@implementation RCTImagePickerManager @implementation RCTImagePickerManager
{ {
NSMutableArray *_pickers; NSMutableArray<UIImagePickerController *> *_pickers;
NSMutableArray *_pickerCallbacks; NSMutableArray<RCTResponseSenderBlock> *_pickerCallbacks;
NSMutableArray *_pickerCancelCallbacks; NSMutableArray<RCTResponseSenderBlock> *_pickerCancelCallbacks;
} }
RCT_EXPORT_MODULE(ImagePickerIOS); RCT_EXPORT_MODULE(ImagePickerIOS);
@ -42,7 +42,7 @@ RCT_EXPORT_MODULE(ImagePickerIOS);
RCT_EXPORT_METHOD(canRecordVideos:(RCTResponseSenderBlock)callback) RCT_EXPORT_METHOD(canRecordVideos:(RCTResponseSenderBlock)callback)
{ {
NSArray *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera]; NSArray<NSString *> *availableMediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
callback(@[@([availableMediaTypes containsObject:(NSString *)kUTTypeMovie])]); callback(@[@([availableMediaTypes containsObject:(NSString *)kUTTypeMovie])]);
} }
@ -59,7 +59,7 @@ RCT_EXPORT_METHOD(openCameraDialog:(NSDictionary *)config
cancelCallback(@[@"Camera access is unavailable in an app extension"]); cancelCallback(@[@"Camera access is unavailable in an app extension"]);
return; return;
} }
UIWindow *keyWindow = RCTSharedApplication().keyWindow; UIWindow *keyWindow = RCTSharedApplication().keyWindow;
UIViewController *rootViewController = keyWindow.rootViewController; UIViewController *rootViewController = keyWindow.rootViewController;
@ -86,7 +86,7 @@ RCT_EXPORT_METHOD(openSelectDialog:(NSDictionary *)config
cancelCallback(@[@"Image picker is currently unavailable in an app extension"]); cancelCallback(@[@"Image picker is currently unavailable in an app extension"]);
return; return;
} }
UIWindow *keyWindow = RCTSharedApplication().keyWindow; UIWindow *keyWindow = RCTSharedApplication().keyWindow;
UIViewController *rootViewController = keyWindow.rootViewController; UIViewController *rootViewController = keyWindow.rootViewController;
@ -94,7 +94,7 @@ RCT_EXPORT_METHOD(openSelectDialog:(NSDictionary *)config
imagePicker.delegate = self; imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
NSMutableArray *allowedTypes = [NSMutableArray new]; NSMutableArray<NSString *> *allowedTypes = [NSMutableArray new];
if ([config[@"showImages"] boolValue]) { if ([config[@"showImages"] boolValue]) {
[allowedTypes addObject:(NSString *)kUTTypeImage]; [allowedTypes addObject:(NSString *)kUTTypeImage];
} }

View File

@ -100,7 +100,7 @@ static NSDictionary *RCTPositionError(RCTPositionErrorCode code, NSString *msg /
{ {
CLLocationManager *_locationManager; CLLocationManager *_locationManager;
NSDictionary *_lastLocationEvent; NSDictionary *_lastLocationEvent;
NSMutableArray *_pendingRequests; NSMutableArray<RCTLocationRequest *> *_pendingRequests;
BOOL _observingLocation; BOOL _observingLocation;
RCTLocationOptions _observerOptions; RCTLocationOptions _observerOptions;
} }
@ -249,7 +249,8 @@ RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options
#pragma mark - CLLocationManagerDelegate #pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations - (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations
{ {
// Create event // Create event
CLLocation *location = locations.lastObject; CLLocation *location = locations.lastObject;

View File

@ -42,8 +42,8 @@ RCT_EXPORT_MODULE()
if (imageCount > 1) { if (imageCount > 1) {
NSTimeInterval duration = 0; NSTimeInterval duration = 0;
NSMutableArray *delays = [NSMutableArray arrayWithCapacity:imageCount]; NSMutableArray<NSNumber *> *delays = [NSMutableArray arrayWithCapacity:imageCount];
NSMutableArray *images = [NSMutableArray arrayWithCapacity:imageCount]; NSMutableArray<id /* CGIMageRef */> *images = [NSMutableArray arrayWithCapacity:imageCount];
for (size_t i = 0; i < imageCount; i++) { for (size_t i = 0; i < imageCount; i++) {
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSource, i, NULL); CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSource, i, NULL);
@ -75,7 +75,7 @@ RCT_EXPORT_MODULE()
} }
CFRelease(imageSource); CFRelease(imageSource);
NSMutableArray *keyTimes = [NSMutableArray arrayWithCapacity:delays.count]; NSMutableArray<NSNumber *> *keyTimes = [NSMutableArray arrayWithCapacity:delays.count];
NSTimeInterval runningDuration = 0; NSTimeInterval runningDuration = 0;
for (NSNumber *delayNumber in delays) { for (NSNumber *delayNumber in delays) {
[keyTimes addObject:@(runningDuration / duration)]; [keyTimes addObject:@(runningDuration / duration)];

View File

@ -35,8 +35,8 @@
@implementation RCTImageLoader @implementation RCTImageLoader
{ {
NSArray *_loaders; NSArray<id<RCTImageURLLoader>> *_loaders;
NSArray *_decoders; NSArray<id<RCTImageDataDecoder>> *_decoders;
NSURLCache *_cache; NSURLCache *_cache;
} }
@ -47,14 +47,14 @@ RCT_EXPORT_MODULE()
- (void)setBridge:(RCTBridge *)bridge - (void)setBridge:(RCTBridge *)bridge
{ {
// Get image loaders and decoders // Get image loaders and decoders
NSMutableArray *loaders = [NSMutableArray array]; NSMutableArray<id<RCTImageURLLoader>> *loaders = [NSMutableArray array];
NSMutableArray *decoders = [NSMutableArray array]; NSMutableArray<id<RCTImageDataDecoder>> *decoders = [NSMutableArray array];
for (id<RCTBridgeModule> module in bridge.modules.allValues) { for (id<RCTBridgeModule> module in bridge.modules.allValues) {
if ([module conformsToProtocol:@protocol(RCTImageURLLoader)]) { if ([module conformsToProtocol:@protocol(RCTImageURLLoader)]) {
[loaders addObject:module]; [loaders addObject:(id<RCTImageURLLoader>)module];
} }
if ([module conformsToProtocol:@protocol(RCTImageDataDecoder)]) { if ([module conformsToProtocol:@protocol(RCTImageDataDecoder)]) {
[decoders addObject:module]; [decoders addObject:(id<RCTImageDataDecoder>)module];
} }
} }

View File

@ -47,7 +47,7 @@ RCT_EXPORT_MODULE()
- (BOOL)canHandleRequest:(NSURLRequest *)request - (BOOL)canHandleRequest:(NSURLRequest *)request
{ {
static NSSet *schemes = nil; static NSSet<NSString *> *schemes = nil;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
// technically, RCTHTTPRequestHandler can handle file:// as well, // technically, RCTHTTPRequestHandler can handle file:// as well,

View File

@ -37,7 +37,7 @@ typedef RCTURLRequestCancellationBlock (^RCTHTTPQueryResult)(NSError *error, NSD
@implementation RCTHTTPFormDataHelper @implementation RCTHTTPFormDataHelper
{ {
NSMutableArray *_parts; NSMutableArray<NSDictionary *> *_parts;
NSMutableData *_multipartBody; NSMutableData *_multipartBody;
RCTHTTPQueryResult _callback; RCTHTTPQueryResult _callback;
NSString *_boundary; NSString *_boundary;
@ -122,7 +122,7 @@ static NSString *RCTGenerateFormBoundary()
@implementation RCTNetworking @implementation RCTNetworking
{ {
NSMutableDictionary *_tasksByRequestID; NSMutableDictionary *_tasksByRequestID;
NSArray *_handlers; NSArray<id<RCTURLRequestHandler>> *_handlers;
} }
@synthesize bridge = _bridge; @synthesize bridge = _bridge;
@ -133,10 +133,10 @@ RCT_EXPORT_MODULE()
- (void)setBridge:(RCTBridge *)bridge - (void)setBridge:(RCTBridge *)bridge
{ {
// get handlers // get handlers
NSMutableArray *handlers = [NSMutableArray array]; NSMutableArray<id<RCTURLRequestHandler>> *handlers = [NSMutableArray array];
for (id<RCTBridgeModule> module in bridge.modules.allValues) { for (id<RCTBridgeModule> module in bridge.modules.allValues) {
if ([module conformsToProtocol:@protocol(RCTURLRequestHandler)]) { if ([module conformsToProtocol:@protocol(RCTURLRequestHandler)]) {
[handlers addObject:module]; [handlers addObject:(id<RCTURLRequestHandler>)module];
} }
} }

View File

@ -22,6 +22,8 @@
referenceDirectory:@FB_REFERENCE_IMAGE_DIR \ referenceDirectory:@FB_REFERENCE_IMAGE_DIR \
moduleProvider:(moduleProvider__)] moduleProvider:(moduleProvider__)]
@protocol RCTBridgeModule;
@interface RCTTestRunner : NSObject @interface RCTTestRunner : NSObject
@property (nonatomic, assign) BOOL recordMode; @property (nonatomic, assign) BOOL recordMode;
@ -37,7 +39,7 @@
*/ */
- (instancetype)initWithApp:(NSString *)app - (instancetype)initWithApp:(NSString *)app
referenceDirectory:(NSString *)referenceDirectory referenceDirectory:(NSString *)referenceDirectory
moduleProvider:(NSArray *(^)(void))block NS_DESIGNATED_INITIALIZER; moduleProvider:(NSArray<id<RCTBridgeModule>> *(^)(void))block NS_DESIGNATED_INITIALIZER;
/** /**
* Simplest runTest function simply mounts the specified JS module with no * Simplest runTest function simply mounts the specified JS module with no

View File

@ -126,7 +126,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
RCTSetLogFunction(RCTDefaultLogFunction); RCTSetLogFunction(RCTDefaultLogFunction);
NSArray *nonLayoutSubviews = [vc.view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id subview, NSDictionary *bindings) { NSArray<UIView *> *nonLayoutSubviews = [vc.view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id subview, NSDictionary *bindings) {
return ![NSStringFromClass([subview class]) isEqualToString:@"_UILayoutGuide"]; return ![NSStringFromClass([subview class]) isEqualToString:@"_UILayoutGuide"];
}]]; }]];
RCTAssert(nonLayoutSubviews.count == 0, @"There shouldn't be any other views: %@", nonLayoutSubviews); RCTAssert(nonLayoutSubviews.count == 0, @"There shouldn't be any other views: %@", nonLayoutSubviews);

View File

@ -80,7 +80,7 @@ static css_dim_t RCTMeasure(void *context, float width)
[self dirtyText]; [self dirtyText];
} }
- (NSDictionary *)processUpdatedProperties:(NSMutableSet *)applierBlocks - (NSDictionary *)processUpdatedProperties:(NSMutableSet<RCTApplierBlock> *)applierBlocks
parentProperties:(NSDictionary *)parentProperties parentProperties:(NSDictionary *)parentProperties
{ {
parentProperties = [super processUpdatedProperties:applierBlocks parentProperties = [super processUpdatedProperties:applierBlocks
@ -99,7 +99,7 @@ static css_dim_t RCTMeasure(void *context, float width)
} }
- (void)applyLayoutNode:(css_node_t *)node - (void)applyLayoutNode:(css_node_t *)node
viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame viewsWithNewFrame:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame
absolutePosition:(CGPoint)absolutePosition absolutePosition:(CGPoint)absolutePosition
{ {
[super applyLayoutNode:node viewsWithNewFrame:viewsWithNewFrame absolutePosition:absolutePosition]; [super applyLayoutNode:node viewsWithNewFrame:viewsWithNewFrame absolutePosition:absolutePosition];

View File

@ -16,7 +16,7 @@
@implementation RCTText @implementation RCTText
{ {
NSTextStorage *_textStorage; NSTextStorage *_textStorage;
NSMutableArray *_reactSubviews; NSMutableArray<UIView *> *_reactSubviews;
CAShapeLayer *_highlightLayer; CAShapeLayer *_highlightLayer;
} }
@ -62,7 +62,7 @@
[_reactSubviews removeObject:subview]; [_reactSubviews removeObject:subview];
} }
- (NSArray *)reactSubviews - (NSArray<UIView *> *)reactSubviews
{ {
return _reactSubviews; return _reactSubviews;
} }

View File

@ -17,7 +17,7 @@
@implementation RCTTextField @implementation RCTTextField
{ {
RCTEventDispatcher *_eventDispatcher; RCTEventDispatcher *_eventDispatcher;
NSMutableArray *_reactSubviews; NSMutableArray<UIView *> *_reactSubviews;
BOOL _jsRequestingFirstResponder; BOOL _jsRequestingFirstResponder;
NSInteger _nativeEventCount; NSInteger _nativeEventCount;
} }
@ -92,7 +92,7 @@ static void RCTUpdatePlaceholder(RCTTextField *self)
RCTUpdatePlaceholder(self); RCTUpdatePlaceholder(self);
} }
- (NSArray *)reactSubviews - (NSArray<UIView *> *)reactSubviews
{ {
// TODO: do we support subviews of textfield in React? // TODO: do we support subviews of textfield in React?
// In any case, we should have a better approach than manually // In any case, we should have a better approach than manually

View File

@ -65,7 +65,7 @@ RCT_EXPORT_SHADOW_PROPERTY(allowFontScaling, BOOL)
continue; continue;
} }
NSMutableArray *queue = [NSMutableArray arrayWithObject:rootView]; NSMutableArray<RCTShadowView *> *queue = [NSMutableArray arrayWithObject:rootView];
for (NSInteger i = 0; i < queue.count; i++) { for (NSInteger i = 0; i < queue.count; i++) {
RCTShadowView *shadowView = queue[i]; RCTShadowView *shadowView = queue[i];
RCTAssert([shadowView isTextDirty], @"Don't process any nodes that don't have dirty text"); RCTAssert([shadowView isTextDirty], @"Don't process any nodes that don't have dirty text");

View File

@ -60,11 +60,11 @@ extern NSString *const RCTSRHTTPResponseErrorKey;
@property (nonatomic, readonly, copy) NSString *protocol; @property (nonatomic, readonly, copy) NSString *protocol;
// Protocols should be an array of strings that turn into Sec-WebSocket-Protocol. // Protocols should be an array of strings that turn into Sec-WebSocket-Protocol.
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols NS_DESIGNATED_INITIALIZER; - (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithURLRequest:(NSURLRequest *)request; - (instancetype)initWithURLRequest:(NSURLRequest *)request;
// Some helper constructors. // Some helper constructors.
- (instancetype)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; - (instancetype)initWithURL:(NSURL *)url protocols:(NSArray<NSString *> *)protocols;
- (instancetype)initWithURL:(NSURL *)url; - (instancetype)initWithURL:(NSURL *)url;
// Delegate queue will be dispatch_main_queue by default. // Delegate queue will be dispatch_main_queue by default.

View File

@ -186,7 +186,7 @@ typedef void (^data_callback)(RCTSRWebSocket *webSocket, NSData *data);
dispatch_queue_t _delegateDispatchQueue; dispatch_queue_t _delegateDispatchQueue;
dispatch_queue_t _workQueue; dispatch_queue_t _workQueue;
NSMutableArray *_consumers; NSMutableArray<RCTSRIOConsumer *> *_consumers;
NSInputStream *_inputStream; NSInputStream *_inputStream;
NSOutputStream *_outputStream; NSOutputStream *_outputStream;
@ -228,12 +228,12 @@ typedef void (^data_callback)(RCTSRWebSocket *webSocket, NSData *data);
BOOL _isPumping; BOOL _isPumping;
NSMutableSet *_scheduledRunloops; NSMutableSet<NSArray *> *_scheduledRunloops;
// We use this to retain ourselves. // We use this to retain ourselves.
__strong RCTSRWebSocket *_selfRetain; __strong RCTSRWebSocket *_selfRetain;
NSArray *_requestedProtocols; NSArray<NSString *> *_requestedProtocols;
RCTSRIOConsumerPool *_consumerPool; RCTSRIOConsumerPool *_consumerPool;
} }
@ -244,7 +244,7 @@ static __strong NSData *CRLFCRLF;
CRLFCRLF = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4]; CRLFCRLF = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4];
} }
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; - (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols;
{ {
RCTAssertParam(request); RCTAssertParam(request);
@ -271,7 +271,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
return [self initWithURL:URL protocols:nil]; return [self initWithURL:URL protocols:nil];
} }
- (instancetype)initWithURL:(NSURL *)URL protocols:(NSArray *)protocols; - (instancetype)initWithURL:(NSURL *)URL protocols:(NSArray<NSString *> *)protocols;
{ {
NSURLRequest *request = URL ? [NSURLRequest requestWithURL:URL] : nil; NSURLRequest *request = URL ? [NSURLRequest requestWithURL:URL] : nil;
return [self initWithURLRequest:request protocols:protocols]; return [self initWithURLRequest:request protocols:protocols];
@ -1456,7 +1456,7 @@ static const size_t RCTSRFrameHeaderOverhead = 32;
@implementation RCTSRIOConsumerPool @implementation RCTSRIOConsumerPool
{ {
NSUInteger _poolSize; NSUInteger _poolSize;
NSMutableArray *_bufferedConsumers; NSMutableArray<RCTSRIOConsumer *> *_bufferedConsumers;
} }
- (instancetype)initWithBufferCapacity:(NSUInteger)poolSize; - (instancetype)initWithBufferCapacity:(NSUInteger)poolSize;

View File

@ -59,7 +59,7 @@ void RCTAddAssertFunction(RCTAssertFunction assertFunction)
static RCTAssertFunction RCTGetLocalAssertFunction() static RCTAssertFunction RCTGetLocalAssertFunction()
{ {
NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary; NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary;
NSArray *functionStack = threadDictionary[RCTAssertFunctionStack]; NSArray<RCTAssertFunction> *functionStack = threadDictionary[RCTAssertFunctionStack];
RCTAssertFunction assertFunction = functionStack.lastObject; RCTAssertFunction assertFunction = functionStack.lastObject;
if (assertFunction) { if (assertFunction) {
return assertFunction; return assertFunction;
@ -70,7 +70,7 @@ static RCTAssertFunction RCTGetLocalAssertFunction()
void RCTPerformBlockWithAssertFunction(void (^block)(void), RCTAssertFunction assertFunction) void RCTPerformBlockWithAssertFunction(void (^block)(void), RCTAssertFunction assertFunction)
{ {
NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary; NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary;
NSMutableArray *functionStack = threadDictionary[RCTAssertFunctionStack]; NSMutableArray<RCTAssertFunction> *functionStack = threadDictionary[RCTAssertFunctionStack];
if (!functionStack) { if (!functionStack) {
functionStack = [NSMutableArray new]; functionStack = [NSMutableArray new];
threadDictionary[RCTAssertFunctionStack] = functionStack; threadDictionary[RCTAssertFunctionStack] = functionStack;

View File

@ -11,6 +11,7 @@
#import "RCTAssert.h" #import "RCTAssert.h"
#import "RCTBridge.h" #import "RCTBridge.h"
#import "RCTBridgeMethod.h"
#import "RCTConvert.h" #import "RCTConvert.h"
#import "RCTContextExecutor.h" #import "RCTContextExecutor.h"
#import "RCTFrameUpdate.h" #import "RCTFrameUpdate.h"
@ -18,7 +19,6 @@
#import "RCTLog.h" #import "RCTLog.h"
#import "RCTModuleData.h" #import "RCTModuleData.h"
#import "RCTModuleMap.h" #import "RCTModuleMap.h"
#import "RCTBridgeMethod.h"
#import "RCTPerformanceLogger.h" #import "RCTPerformanceLogger.h"
#import "RCTProfile.h" #import "RCTProfile.h"
#import "RCTRedBox.h" #import "RCTRedBox.h"
@ -43,7 +43,7 @@ typedef NS_ENUM(NSUInteger, RCTBridgeFields) {
RCTBridgeFieldParamss, RCTBridgeFieldParamss,
}; };
RCT_EXTERN NSArray *RCTGetModuleClasses(void); RCT_EXTERN NSArray<Class> *RCTGetModuleClasses(void);
@interface RCTBridge () @interface RCTBridge ()
@ -64,11 +64,11 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
BOOL _valid; BOOL _valid;
BOOL _wasBatchActive; BOOL _wasBatchActive;
__weak id<RCTJavaScriptExecutor> _javaScriptExecutor; __weak id<RCTJavaScriptExecutor> _javaScriptExecutor;
NSMutableArray *_pendingCalls; NSMutableArray<NSArray *> *_pendingCalls;
NSMutableArray *_moduleDataByID; NSMutableArray<RCTModuleData *> *_moduleDataByID;
RCTModuleMap *_modulesByName; RCTModuleMap *_modulesByName;
CADisplayLink *_jsDisplayLink; CADisplayLink *_jsDisplayLink;
NSMutableSet *_frameUpdateObservers; NSMutableSet<RCTModuleData *> *_frameUpdateObservers;
} }
- (instancetype)initWithParentBridge:(RCTBridge *)bridge - (instancetype)initWithParentBridge:(RCTBridge *)bridge
@ -233,7 +233,7 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
// Register passed-in module instances // Register passed-in module instances
NSMutableDictionary *preregisteredModules = [NSMutableDictionary new]; NSMutableDictionary *preregisteredModules = [NSMutableDictionary new];
NSArray *extraModules = nil; NSArray<id<RCTBridgeModule>> *extraModules = nil;
if (self.delegate) { if (self.delegate) {
if ([self.delegate respondsToSelector:@selector(extraModulesForBridge:)]) { if ([self.delegate respondsToSelector:@selector(extraModulesForBridge:)]) {
extraModules = [self.delegate extraModulesForBridge:_parentBridge]; extraModules = [self.delegate extraModulesForBridge:_parentBridge];
@ -308,12 +308,11 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
- (NSString *)moduleConfig - (NSString *)moduleConfig
{ {
NSMutableArray *config = [NSMutableArray new]; NSMutableArray<NSArray *> *config = [NSMutableArray new];
for (RCTModuleData *moduleData in _moduleDataByID) { for (RCTModuleData *moduleData in _moduleDataByID) {
[config addObject:moduleData.config]; [config addObject:moduleData.config];
if ([moduleData.instance conformsToProtocol:@protocol(RCTFrameUpdateObserver)]) { if ([moduleData.instance conformsToProtocol:@protocol(RCTFrameUpdateObserver)]) {
[_frameUpdateObservers addObject:moduleData]; [_frameUpdateObservers addObject:moduleData];
id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)moduleData.instance; id<RCTFrameUpdateObserver> observer = (id<RCTFrameUpdateObserver>)moduleData.instance;
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
__weak typeof(_javaScriptExecutor) weakJavaScriptExecutor = _javaScriptExecutor; __weak typeof(_javaScriptExecutor) weakJavaScriptExecutor = _javaScriptExecutor;
@ -417,7 +416,7 @@ RCT_EXTERN NSArray *RCTGetModuleClasses(void);
_loading = NO; _loading = NO;
NSArray *stack = error.userInfo[@"stack"]; NSArray<NSDictionary *> *stack = error.userInfo[@"stack"];
if (stack) { if (stack) {
[self.redBox showErrorMessage:error.localizedDescription withStack:stack]; [self.redBox showErrorMessage:error.localizedDescription withStack:stack];
} else { } else {
@ -559,7 +558,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
*/ */
- (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args - (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args
{ {
NSArray *ids = [moduleDotMethod componentsSeparatedByString:@"."]; NSArray<NSString *> *ids = [moduleDotMethod componentsSeparatedByString:@"."];
[self _invokeAndProcessModule:@"BatchedBridge" [self _invokeAndProcessModule:@"BatchedBridge"
method:@"callFunctionReturnFlushedQueue" method:@"callFunctionReturnFlushedQueue"
@ -698,57 +697,45 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithBundleURL:(__unused NSURL *)bundleUR
} }
} }
- (void)handleBuffer:(id)buffer - (void)handleBuffer:(NSArray<NSArray *> *)buffer
{ {
NSArray *requestsArray = [RCTConvert NSArray:buffer]; NSArray<NSArray *> *requestsArray = [RCTConvert NSArrayArray:buffer];
#if RCT_DEBUG if (RCT_DEBUG && requestsArray.count <= RCTBridgeFieldParamss) {
RCTLogError(@"Buffer should contain at least %tu sub-arrays. Only found %tu",
if (![buffer isKindOfClass:[NSArray class]]) { RCTBridgeFieldParamss + 1, requestsArray.count);
RCTLogError(@"Buffer must be an instance of NSArray, got %@", NSStringFromClass([buffer class]));
return; return;
} }
for (NSUInteger fieldIndex = RCTBridgeFieldRequestModuleIDs; fieldIndex <= RCTBridgeFieldParamss; fieldIndex++) { NSArray<NSNumber *> *moduleIDs = requestsArray[RCTBridgeFieldRequestModuleIDs];
id field = requestsArray[fieldIndex]; NSArray<NSNumber *> *methodIDs = requestsArray[RCTBridgeFieldMethodIDs];
if (![field isKindOfClass:[NSArray class]]) { NSArray<NSArray *> *paramsArrays = requestsArray[RCTBridgeFieldParamss];
RCTLogError(@"Field at index %zd in buffer must be an instance of NSArray, got %@", fieldIndex, NSStringFromClass([field class]));
return;
}
}
#endif if (RCT_DEBUG && (moduleIDs.count != methodIDs.count || moduleIDs.count != paramsArrays.count)) {
RCTLogError(@"Invalid data message - all must be length: %zd", moduleIDs.count);
NSArray *moduleIDs = requestsArray[RCTBridgeFieldRequestModuleIDs];
NSArray *methodIDs = requestsArray[RCTBridgeFieldMethodIDs];
NSArray *paramsArrays = requestsArray[RCTBridgeFieldParamss];
NSUInteger numRequests = moduleIDs.count;
if (RCT_DEBUG && (numRequests != methodIDs.count || numRequests != paramsArrays.count)) {
RCTLogError(@"Invalid data message - all must be length: %zd", numRequests);
return; return;
} }
NSMapTable *buckets = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory NSMapTable *buckets = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory
valueOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsStrongMemory
capacity:_moduleDataByID.count]; capacity:_moduleDataByID.count];
for (NSUInteger i = 0; i < numRequests; i++) {
RCTModuleData *moduleData = _moduleDataByID[[moduleIDs[i] integerValue]]; [moduleIDs enumerateObjectsUsingBlock:^(NSNumber *moduleID, NSUInteger i, __unused BOOL *stop) {
RCTModuleData *moduleData = _moduleDataByID[moduleID.integerValue];
if (RCT_DEBUG) { if (RCT_DEBUG) {
// verify that class has been registered // verify that class has been registered
(void)_modulesByName[moduleData.name]; (void)_modulesByName[moduleData.name];
} }
id queue = [moduleData queue]; dispatch_queue_t queue = moduleData.queue;
NSMutableOrderedSet *set = [buckets objectForKey:queue]; NSMutableOrderedSet<NSNumber *> *set = [buckets objectForKey:queue];
if (!set) { if (!set) {
set = [NSMutableOrderedSet new]; set = [NSMutableOrderedSet new];
[buckets setObject:set forKey:queue]; [buckets setObject:set forKey:queue];
} }
[set addObject:@(i)]; [set addObject:@(i)];
} }];
for (id queue in buckets) { for (dispatch_queue_t queue in buckets) {
RCTProfileBeginFlowEvent(); RCTProfileBeginFlowEvent();
dispatch_block_t block = ^{ dispatch_block_t block = ^{

View File

@ -52,7 +52,7 @@ RCT_EXTERN NSString *const RCTDidCreateNativeModules;
* For this reason, the block should always return new module instances, and * For this reason, the block should always return new module instances, and
* module instances should not be shared between bridges. * module instances should not be shared between bridges.
*/ */
typedef NSArray *(^RCTBridgeModuleProviderBlock)(void); typedef NSArray<id<RCTBridgeModule>> *(^RCTBridgeModuleProviderBlock)(void);
/** /**
* This function returns the module name for a given class. * This function returns the module name for a given class.

View File

@ -39,9 +39,9 @@ NSString *const RCTDidCreateNativeModules = @"RCTDidCreateNativeModules";
@end @end
static NSMutableArray *RCTModuleClasses; static NSMutableArray<Class> *RCTModuleClasses;
NSArray *RCTGetModuleClasses(void); NSArray<Class> *RCTGetModuleClasses(void);
NSArray *RCTGetModuleClasses(void) NSArray<Class> *RCTGetModuleClasses(void)
{ {
return RCTModuleClasses; return RCTModuleClasses;
} }

View File

@ -10,6 +10,7 @@
typedef void (^RCTSourceLoadBlock)(NSError *error, NSData *source); typedef void (^RCTSourceLoadBlock)(NSError *error, NSData *source);
@class RCTBridge; @class RCTBridge;
@protocol RCTBridgeModule;
@protocol RCTBridgeDelegate <NSObject> @protocol RCTBridgeDelegate <NSObject>
@ -17,7 +18,7 @@ typedef void (^RCTSourceLoadBlock)(NSError *error, NSData *source);
@optional @optional
- (NSArray *)extraModulesForBridge:(RCTBridge *)bridge; - (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge;
- (void)loadSourceForBridge:(RCTBridge *)bridge withBlock:(RCTSourceLoadBlock)loadCallback; - (void)loadSourceForBridge:(RCTBridge *)bridge withBlock:(RCTSourceLoadBlock)loadCallback;
@end @end

View File

@ -12,6 +12,7 @@
#import "RCTDefines.h" #import "RCTDefines.h"
@class RCTBridge; @class RCTBridge;
@protocol RCTBridgeMethod;
/** /**
* The type of a block that is capable of sending a response to a bridged * The type of a block that is capable of sending a response to a bridged
@ -208,7 +209,8 @@ RCT_EXTERN void RCTRegisterModule(Class); \
* Like RCT_EXTERN_REMAP_METHOD, but allows setting a custom JavaScript name. * Like RCT_EXTERN_REMAP_METHOD, but allows setting a custom JavaScript name.
*/ */
#define RCT_EXTERN_REMAP_METHOD(js_name, method) \ #define RCT_EXTERN_REMAP_METHOD(js_name, method) \
+ (NSArray *)RCT_CONCAT(__rct_export__, RCT_CONCAT(js_name, RCT_CONCAT(__LINE__, __COUNTER__))) { \ + (NSArray<NSString *> *)RCT_CONCAT(__rct_export__, \
RCT_CONCAT(js_name, RCT_CONCAT(__LINE__, __COUNTER__))) { \
return @[@#js_name, @#method]; \ return @[@#js_name, @#method]; \
} }
@ -217,7 +219,7 @@ RCT_EXTERN void RCTRegisterModule(Class); \
* methods defined using the macros above. This method is called only once, * methods defined using the macros above. This method is called only once,
* before registration. * before registration.
*/ */
- (NSArray *)methodsToExport; - (NSArray<id<RCTBridgeMethod>> *)methodsToExport;
/** /**
* Injects constants into JS. These constants are made accessible via * Injects constants into JS. These constants are made accessible via

View File

@ -96,25 +96,28 @@ typedef NSURL RCTFileURL;
scaleMultiplier:(CGFloat)scaleMultiplier; scaleMultiplier:(CGFloat)scaleMultiplier;
typedef NSArray NSArrayArray; typedef NSArray NSArrayArray;
+ (NSArrayArray *)NSArrayArray:(id)json; + (NSArray<NSArray *> *)NSArrayArray:(id)json;
typedef NSArray NSStringArray; typedef NSArray NSStringArray;
+ (NSStringArray *)NSStringArray:(id)json; + (NSArray<NSString *> *)NSStringArray:(id)json;
typedef NSArray NSStringArrayArray;
+ (NSArray<NSArray<NSString *> *> *)NSStringArrayArray:(id)json;
typedef NSArray NSDictionaryArray; typedef NSArray NSDictionaryArray;
+ (NSDictionaryArray *)NSDictionaryArray:(id)json; + (NSArray<NSDictionary *> *)NSDictionaryArray:(id)json;
typedef NSArray NSURLArray; typedef NSArray NSURLArray;
+ (NSURLArray *)NSURLArray:(id)json; + (NSArray<NSURL *> *)NSURLArray:(id)json;
typedef NSArray RCTFileURLArray; typedef NSArray RCTFileURLArray;
+ (RCTFileURLArray *)RCTFileURLArray:(id)json; + (NSArray<NSURL *> *)RCTFileURLArray:(id)json;
typedef NSArray NSNumberArray; typedef NSArray NSNumberArray;
+ (NSNumberArray *)NSNumberArray:(id)json; + (NSArray<NSNumber *> *)NSNumberArray:(id)json;
typedef NSArray UIColorArray; typedef NSArray UIColorArray;
+ (UIColorArray *)UIColorArray:(id)json; + (NSArray<UIColor *> *)UIColorArray:(id)json;
typedef NSArray CGColorArray; typedef NSArray CGColorArray;
+ (CGColorArray *)CGColorArray:(id)json; + (CGColorArray *)CGColorArray:(id)json;
@ -223,7 +226,7 @@ RCT_CUSTOM_CONVERTER(type, type, [RCT_DEBUG ? [self NSNumber:json] : json getter
* This macro is used for creating converter functions for typed arrays. * This macro is used for creating converter functions for typed arrays.
*/ */
#define RCT_ARRAY_CONVERTER(type) \ #define RCT_ARRAY_CONVERTER(type) \
+ (NSArray *)type##Array:(id)json \ + (NSArray<type *> *)type##Array:(id)json \
{ \ { \
return RCTConvertArrayValue(@selector(type:), json); \ return RCTConvertArrayValue(@selector(type:), json); \
} }

View File

@ -711,6 +711,7 @@ RCT_ARRAY_CONVERTER(UIColor)
RCT_JSON_ARRAY_CONVERTER(NSArray) RCT_JSON_ARRAY_CONVERTER(NSArray)
RCT_JSON_ARRAY_CONVERTER(NSString) RCT_JSON_ARRAY_CONVERTER(NSString)
RCT_JSON_ARRAY_CONVERTER(NSStringArray)
RCT_JSON_ARRAY_CONVERTER(NSDictionary) RCT_JSON_ARRAY_CONVERTER(NSDictionary)
RCT_JSON_ARRAY_CONVERTER(NSNumber) RCT_JSON_ARRAY_CONVERTER(NSNumber)

View File

@ -209,7 +209,7 @@ RCT_EXPORT_MODULE()
- (void)dispatchEvent:(id<RCTEvent>)event - (void)dispatchEvent:(id<RCTEvent>)event
{ {
NSMutableArray *arguments = [NSMutableArray new]; NSMutableArray<id /* any JSON value */> *arguments = [NSMutableArray new];
if (event.viewTag) { if (event.viewTag) {
[arguments addObject:event.viewTag]; [arguments addObject:event.viewTag];
@ -221,8 +221,7 @@ RCT_EXPORT_MODULE()
[arguments addObject:event.body]; [arguments addObject:event.body];
} }
[_bridge enqueueJSCall:[[event class] moduleDotMethod] [_bridge enqueueJSCall:[[event class] moduleDotMethod] args:arguments];
args:arguments];
} }
- (dispatch_queue_t)methodQueue - (dispatch_queue_t)methodQueue

View File

@ -82,7 +82,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
NSDictionary *errorDetails = RCTJSONParse(rawText, nil); NSDictionary *errorDetails = RCTJSONParse(rawText, nil);
if ([errorDetails isKindOfClass:[NSDictionary class]] && if ([errorDetails isKindOfClass:[NSDictionary class]] &&
[errorDetails[@"errors"] isKindOfClass:[NSArray class]]) { [errorDetails[@"errors"] isKindOfClass:[NSArray class]]) {
NSMutableArray *fakeStack = [NSMutableArray new]; NSMutableArray<NSDictionary *> *fakeStack = [NSMutableArray new];
for (NSDictionary *err in errorDetails[@"errors"]) { for (NSDictionary *err in errorDetails[@"errors"]) {
[fakeStack addObject: @{ [fakeStack addObject: @{
@"methodName": err[@"description"] ?: @"", @"methodName": err[@"description"] ?: @"",

View File

@ -77,15 +77,15 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
@interface RCTKeyCommands () @interface RCTKeyCommands ()
@property (nonatomic, strong) NSMutableSet *commands; @property (nonatomic, strong) NSMutableSet<RCTKeyCommand *> *commands;
@end @end
@implementation UIResponder (RCTKeyCommands) @implementation UIResponder (RCTKeyCommands)
- (NSArray *)RCT_keyCommands - (NSArray<UIKeyCommand *> *)RCT_keyCommands
{ {
NSSet *commands = [RCTKeyCommands sharedInstance].commands; NSSet<RCTKeyCommand *> *commands = [RCTKeyCommands sharedInstance].commands;
return [[commands valueForKeyPath:@"keyCommand"] allObjects]; return [[commands valueForKeyPath:@"keyCommand"] allObjects];
} }

View File

@ -120,7 +120,7 @@ void RCTAddLogFunction(RCTLogFunction logFunction)
static RCTLogFunction RCTGetLocalLogFunction() static RCTLogFunction RCTGetLocalLogFunction()
{ {
NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary; NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary;
NSArray *functionStack = threadDictionary[RCTLogFunctionStack]; NSArray<RCTLogFunction> *functionStack = threadDictionary[RCTLogFunctionStack];
RCTLogFunction logFunction = functionStack.lastObject; RCTLogFunction logFunction = functionStack.lastObject;
if (logFunction) { if (logFunction) {
return logFunction; return logFunction;
@ -131,7 +131,7 @@ static RCTLogFunction RCTGetLocalLogFunction()
void RCTPerformBlockWithLogFunction(void (^block)(void), RCTLogFunction logFunction) void RCTPerformBlockWithLogFunction(void (^block)(void), RCTLogFunction logFunction)
{ {
NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary; NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary;
NSMutableArray *functionStack = threadDictionary[RCTLogFunctionStack]; NSMutableArray<RCTLogFunction> *functionStack = threadDictionary[RCTLogFunctionStack];
if (!functionStack) { if (!functionStack) {
functionStack = [NSMutableArray new]; functionStack = [NSMutableArray new];
threadDictionary[RCTLogFunctionStack] = functionStack; threadDictionary[RCTLogFunctionStack] = functionStack;
@ -216,8 +216,9 @@ void _RCTLogInternal(
// Log to red box // Log to red box
if ([UIApplication sharedApplication] && level >= RCTLOG_REDBOX_LEVEL) { if ([UIApplication sharedApplication] && level >= RCTLOG_REDBOX_LEVEL) {
NSArray *stackSymbols = [NSThread callStackSymbols]; NSArray<NSString *> *stackSymbols = [NSThread callStackSymbols];
NSMutableArray *stack = [NSMutableArray arrayWithCapacity:(stackSymbols.count - 1)]; NSMutableArray<NSDictionary *> *stack =
[NSMutableArray arrayWithCapacity:(stackSymbols.count - 1)];
[stackSymbols enumerateObjectsUsingBlock:^(NSString *frameSymbols, NSUInteger idx, __unused BOOL *stop) { [stackSymbols enumerateObjectsUsingBlock:^(NSString *frameSymbols, NSUInteger idx, __unused BOOL *stop) {
if (idx > 0) { // don't include the current frame if (idx > 0) { // don't include the current frame
NSString *address = [[frameSymbols componentsSeparatedByString:@"0x"][1] componentsSeparatedByString:@" "][0]; NSString *address = [[frameSymbols componentsSeparatedByString:@"0x"][1] componentsSeparatedByString:@" "][0];

View File

@ -11,6 +11,8 @@
#import "RCTJavaScriptExecutor.h" #import "RCTJavaScriptExecutor.h"
@protocol RCTBridgeMethod;
@interface RCTModuleData : NSObject @interface RCTModuleData : NSObject
@property (nonatomic, weak, readonly) id<RCTJavaScriptExecutor> javaScriptExecutor; @property (nonatomic, weak, readonly) id<RCTJavaScriptExecutor> javaScriptExecutor;
@ -19,7 +21,7 @@
@property (nonatomic, strong, readonly) Class moduleClass; @property (nonatomic, strong, readonly) Class moduleClass;
@property (nonatomic, copy, readonly) NSString *name; @property (nonatomic, copy, readonly) NSString *name;
@property (nonatomic, copy, readonly) NSArray *methods; @property (nonatomic, copy, readonly) NSArray<id<RCTBridgeMethod>> *methods;
@property (nonatomic, copy, readonly) NSArray *config; @property (nonatomic, copy, readonly) NSArray *config;
@property (nonatomic, strong) dispatch_queue_t queue; @property (nonatomic, strong) dispatch_queue_t queue;

View File

@ -17,10 +17,11 @@
@implementation RCTModuleData @implementation RCTModuleData
{ {
NSDictionary *_constants; NSDictionary *_constants;
NSArray *_methods;
NSString *_queueName; NSString *_queueName;
} }
@synthesize methods = _methods;
- (instancetype)initWithExecutor:(id<RCTJavaScriptExecutor>)javaScriptExecutor - (instancetype)initWithExecutor:(id<RCTJavaScriptExecutor>)javaScriptExecutor
moduleID:(NSNumber *)moduleID moduleID:(NSNumber *)moduleID
instance:(id<RCTBridgeModule>)instance instance:(id<RCTBridgeModule>)instance
@ -46,10 +47,10 @@
RCT_NOT_IMPLEMENTED(- (instancetype)init); RCT_NOT_IMPLEMENTED(- (instancetype)init);
- (NSArray *)methods - (NSArray<id<RCTBridgeMethod>> *)methods
{ {
if (!_methods) { if (!_methods) {
NSMutableArray *moduleMethods = [NSMutableArray new]; NSMutableArray<id<RCTBridgeMethod>> *moduleMethods = [NSMutableArray new];
if ([_instance respondsToSelector:@selector(methodsToExport)]) { if ([_instance respondsToSelector:@selector(methodsToExport)]) {
[moduleMethods addObjectsFromArray:[_instance methodsToExport]]; [moduleMethods addObjectsFromArray:[_instance methodsToExport]];
@ -63,11 +64,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
SEL selector = method_getName(method); SEL selector = method_getName(method);
if ([NSStringFromSelector(selector) hasPrefix:@"__rct_export__"]) { if ([NSStringFromSelector(selector) hasPrefix:@"__rct_export__"]) {
IMP imp = method_getImplementation(method); IMP imp = method_getImplementation(method);
NSArray *entries = ((NSArray *(*)(id, SEL))imp)(_moduleClass, selector); NSArray<NSString *> *entries =
((NSArray<NSString *> *(*)(id, SEL))imp)(_moduleClass, selector);
id<RCTBridgeMethod> moduleMethod = id<RCTBridgeMethod> moduleMethod =
[[RCTModuleMethod alloc] initWithObjCMethodName:entries[1] [[RCTModuleMethod alloc] initWithObjCMethodName:entries[1]
JSMethodName:entries[0] JSMethodName:entries[0]
moduleClass:_moduleClass]; moduleClass:_moduleClass];
[moduleMethods addObject:moduleMethod]; [moduleMethods addObject:moduleMethod];
} }
@ -86,8 +88,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init);
return (id)kCFNull; // Nothing to export return (id)kCFNull; // Nothing to export
} }
NSMutableArray *methods = self.methods.count ? [NSMutableArray new] : nil; NSMutableArray<NSString *> *methods = self.methods.count ? [NSMutableArray new] : nil;
NSMutableArray *asyncMethods = nil; NSMutableArray<NSNumber *> *asyncMethods = nil;
for (id<RCTBridgeMethod> method in self.methods) { for (id<RCTBridgeMethod> method in self.methods) {
if (method.functionType == RCTFunctionTypePromise) { if (method.functionType == RCTFunctionTypePromise) {
if (!asyncMethods) { if (!asyncMethods) {

View File

@ -69,7 +69,7 @@ extern BOOL RCTBridgeModuleClassIsRegistered(Class cls);
return [_modulesByName keyEnumerator]; return [_modulesByName keyEnumerator];
} }
- (NSArray *)allValues - (NSArray<id<RCTBridgeModule>> *)allValues
{ {
// don't perform validation in this case because we only want to error when // don't perform validation in this case because we only want to error when
// an invalid module is specifically requested // an invalid module is specifically requested

View File

@ -47,7 +47,7 @@ typedef BOOL (^RCTArgumentBlock)(RCTBridge *, NSUInteger, id);
{ {
Class _moduleClass; Class _moduleClass;
NSInvocation *_invocation; NSInvocation *_invocation;
NSArray *_argumentBlocks; NSArray<RCTArgumentBlock> *_argumentBlocks;
NSString *_objCMethodName; NSString *_objCMethodName;
SEL _selector; SEL _selector;
NSDictionary *_profileArgs; NSDictionary *_profileArgs;
@ -66,8 +66,8 @@ static void RCTLogArgumentError(RCTModuleMethod *method, NSUInteger index,
RCT_NOT_IMPLEMENTED(- (instancetype)init) RCT_NOT_IMPLEMENTED(- (instancetype)init)
void RCTParseObjCMethodName(NSString **, NSArray **); void RCTParseObjCMethodName(NSString **, NSArray<RCTMethodArgument *> **);
void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments) void RCTParseObjCMethodName(NSString **objCMethodName, NSArray<RCTMethodArgument *> **arguments)
{ {
static NSRegularExpression *typeNameRegex; static NSRegularExpression *typeNameRegex;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
@ -148,7 +148,7 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
- (void)processMethodSignature - (void)processMethodSignature
{ {
NSArray *arguments; NSArray<RCTMethodArgument *> *arguments;
NSString *objCMethodName = _objCMethodName; NSString *objCMethodName = _objCMethodName;
RCTParseObjCMethodName(&objCMethodName, &arguments); RCTParseObjCMethodName(&objCMethodName, &arguments);
@ -164,7 +164,8 @@ void RCTParseObjCMethodName(NSString **objCMethodName, NSArray **arguments)
// Process arguments // Process arguments
NSUInteger numberOfArguments = methodSignature.numberOfArguments; NSUInteger numberOfArguments = methodSignature.numberOfArguments;
NSMutableArray *argumentBlocks = [[NSMutableArray alloc] initWithCapacity:numberOfArguments - 2]; NSMutableArray<RCTArgumentBlock> *argumentBlocks =
[[NSMutableArray alloc] initWithCapacity:numberOfArguments - 2];
#define RCT_ARG_BLOCK(_logic) \ #define RCT_ARG_BLOCK(_logic) \
[argumentBlocks addObject:^(__unused RCTBridge *bridge, NSUInteger index, id json) { \ [argumentBlocks addObject:^(__unused RCTBridge *bridge, NSUInteger index, id json) { \

View File

@ -25,5 +25,5 @@ typedef NS_ENUM(NSUInteger, RCTPLTag) {
void RCTPerformanceLoggerStart(RCTPLTag tag); void RCTPerformanceLoggerStart(RCTPLTag tag);
void RCTPerformanceLoggerEnd(RCTPLTag tag); void RCTPerformanceLoggerEnd(RCTPLTag tag);
void RCTPerformanceLoggerSet(RCTPLTag tag, int64_t value); void RCTPerformanceLoggerSet(RCTPLTag tag, int64_t value);
NSArray *RCTPerformanceLoggerOutput(void); NSArray<NSNumber *> *RCTPerformanceLoggerOutput(void);
NSArray *RCTPerformanceLoggerLabels(void); NSArray *RCTPerformanceLoggerLabels(void);

View File

@ -36,7 +36,7 @@ void RCTPerformanceLoggerSet(RCTPLTag tag, int64_t value)
RCTPLData[tag][1] = value; RCTPLData[tag][1] = value;
} }
NSArray *RCTPerformanceLoggerOutput(void) NSArray<NSNumber *> *RCTPerformanceLoggerOutput(void)
{ {
return @[ return @[
@(RCTPLData[RCTPLScriptDownload][0]), @(RCTPLData[RCTPLScriptDownload][0]),

View File

@ -27,7 +27,7 @@
- (id)objectForKeyedSubscript:(NSNumber *)key; - (id)objectForKeyedSubscript:(NSNumber *)key;
@property (readonly, nonatomic) NSUInteger count; @property (readonly, nonatomic) NSUInteger count;
@property (readonly, nonatomic, copy) NSArray *allIndexes; @property (readonly, nonatomic, copy) NSArray<NSNumber *> *allIndexes;
@property (readonly, nonatomic, copy) NSArray *allObjects; @property (readonly, nonatomic, copy) NSArray *allObjects;
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSNumber *idx, BOOL *stop))block; - (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSNumber *idx, BOOL *stop))block;

View File

@ -79,7 +79,7 @@
return _storage.count; return _storage.count;
} }
- (NSArray *)allIndexes - (NSArray<NSNumber *> *)allIndexes
{ {
return _storage.allKeys; return _storage.allKeys;
} }

View File

@ -31,9 +31,9 @@
* These must be kept track of because `UIKit` destroys the touch targets * These must be kept track of because `UIKit` destroys the touch targets
* if touches are canceled, and we have no other way to recover this info. * if touches are canceled, and we have no other way to recover this info.
*/ */
NSMutableOrderedSet *_nativeTouches; NSMutableOrderedSet<UITouch *> *_nativeTouches;
NSMutableArray *_reactTouches; NSMutableArray<NSMutableDictionary *> *_reactTouches;
NSMutableArray *_touchViews; NSMutableArray<UIView *> *_touchViews;
BOOL _dispatchedInitialTouches; BOOL _dispatchedInitialTouches;
BOOL _recordingInteractionTiming; BOOL _recordingInteractionTiming;
@ -71,7 +71,7 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
#pragma mark - Bookkeeping for touch indices #pragma mark - Bookkeeping for touch indices
- (void)_recordNewTouches:(NSSet *)touches - (void)_recordNewTouches:(NSSet<UITouch *> *)touches
{ {
for (UITouch *touch in touches) { for (UITouch *touch in touches) {
@ -121,7 +121,7 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
} }
} }
- (void)_recordRemovedTouches:(NSSet *)touches - (void)_recordRemovedTouches:(NSSet<UITouch *> *)touches
{ {
for (UITouch *touch in touches) { for (UITouch *touch in touches) {
NSUInteger index = [_nativeTouches indexOfObject:touch]; NSUInteger index = [_nativeTouches indexOfObject:touch];
@ -163,12 +163,12 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
* (start/end/move/cancel) and the indices that represent "changed" `Touch`es * (start/end/move/cancel) and the indices that represent "changed" `Touch`es
* from that array. * from that array.
*/ */
- (void)_updateAndDispatchTouches:(NSSet *)touches - (void)_updateAndDispatchTouches:(NSSet<UITouch *> *)touches
eventName:(NSString *)eventName eventName:(NSString *)eventName
originatingTime:(__unused CFTimeInterval)originatingTime originatingTime:(__unused CFTimeInterval)originatingTime
{ {
// Update touches // Update touches
NSMutableArray *changedIndexes = [NSMutableArray new]; NSMutableArray<NSNumber *> *changedIndexes = [NSMutableArray new];
for (UITouch *touch in touches) { for (UITouch *touch in touches) {
NSInteger index = [_nativeTouches indexOfObject:touch]; NSInteger index = [_nativeTouches indexOfObject:touch];
if (index == NSNotFound) { if (index == NSNotFound) {
@ -185,7 +185,8 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
// Deep copy the touches because they will be accessed from another thread // Deep copy the touches because they will be accessed from another thread
// TODO: would it be safer to do this in the bridge or executor, rather than trusting caller? // TODO: would it be safer to do this in the bridge or executor, rather than trusting caller?
NSMutableArray *reactTouches = [[NSMutableArray alloc] initWithCapacity:_reactTouches.count]; NSMutableArray<NSDictionary *> *reactTouches =
[[NSMutableArray alloc] initWithCapacity:_reactTouches.count];
for (NSDictionary *touch in _reactTouches) { for (NSDictionary *touch in _reactTouches) {
[reactTouches addObject:[touch copy]]; [reactTouches addObject:[touch copy]];
} }
@ -197,7 +198,7 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
#pragma mark - Gesture Recognizer Delegate Callbacks #pragma mark - Gesture Recognizer Delegate Callbacks
static BOOL RCTAllTouchesAreCancelledOrEnded(NSSet *touches) static BOOL RCTAllTouchesAreCancelledOrEnded(NSSet<UITouch *> *touches)
{ {
for (UITouch *touch in touches) { for (UITouch *touch in touches) {
if (touch.phase == UITouchPhaseBegan || if (touch.phase == UITouchPhaseBegan ||
@ -209,7 +210,7 @@ static BOOL RCTAllTouchesAreCancelledOrEnded(NSSet *touches)
return YES; return YES;
} }
static BOOL RCTAnyTouchesChanged(NSSet *touches) static BOOL RCTAnyTouchesChanged(NSSet<UITouch *> *touches)
{ {
for (UITouch *touch in touches) { for (UITouch *touch in touches) {
if (touch.phase == UITouchPhaseBegan || if (touch.phase == UITouchPhaseBegan ||
@ -238,7 +239,7 @@ static BOOL RCTAnyTouchesChanged(NSSet *touches)
// dispatch the updates from the raw touch methods below. // dispatch the updates from the raw touch methods below.
} }
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{ {
[super touchesBegan:touches withEvent:event]; [super touchesBegan:touches withEvent:event];
@ -253,7 +254,7 @@ static BOOL RCTAnyTouchesChanged(NSSet *touches)
} }
} }
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{ {
[super touchesMoved:touches withEvent:event]; [super touchesMoved:touches withEvent:event];
@ -263,7 +264,7 @@ static BOOL RCTAnyTouchesChanged(NSSet *touches)
} }
} }
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{ {
[super touchesEnded:touches withEvent:event]; [super touchesEnded:touches withEvent:event];
@ -279,7 +280,7 @@ static BOOL RCTAnyTouchesChanged(NSSet *touches)
[self _recordRemovedTouches:touches]; [self _recordRemovedTouches:touches];
} }
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{ {
[super touchesCancelled:touches withEvent:event]; [super touchesCancelled:touches withEvent:event];

View File

@ -60,7 +60,11 @@ RCT_EXTERN UIApplication *RCTSharedApplication(void);
// Return a UIAlertView initialized with the given values // Return a UIAlertView initialized with the given values
// or nil if running in an app extension // or nil if running in an app extension
RCT_EXTERN UIAlertView *RCTAlertView(NSString *title, NSString *message, id delegate, NSString *cancelButtonTitle, NSArray *otherButtonTitles); RCT_EXTERN UIAlertView *RCTAlertView(NSString *title,
NSString *message,
id delegate,
NSString *cancelButtonTitle,
NSArray<NSString *> *otherButtonTitles);
// Return YES if image has an alpha component // Return YES if image has an alpha component
RCT_EXTERN BOOL RCTImageHasAlpha(CGImageRef image); RCT_EXTERN BOOL RCTImageHasAlpha(CGImageRef image);

View File

@ -24,7 +24,7 @@
NSString *RCTJSONStringify(id jsonObject, NSError **error) NSString *RCTJSONStringify(id jsonObject, NSError **error)
{ {
static SEL JSONKitSelector = NULL; static SEL JSONKitSelector = NULL;
static NSSet *collectionTypes; static NSSet<Class> *collectionTypes;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
SEL selector = NSSelectorFromString(@"JSONStringWithOptions:error:"); SEL selector = NSSelectorFromString(@"JSONStringWithOptions:error:");
@ -121,7 +121,7 @@ id RCTJSONParseMutable(NSString *jsonString, NSError **error)
id RCTJSONClean(id object) id RCTJSONClean(id object)
{ {
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
static NSSet *validLeafTypes; static NSSet<Class> *validLeafTypes;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
validLeafTypes = [[NSSet alloc] initWithArray:@[ validLeafTypes = [[NSSet alloc] initWithArray:@[
[NSString class], [NSString class],
@ -301,7 +301,7 @@ NSDictionary *RCTMakeError(NSString *message, id toStringify, NSDictionary *extr
NSDictionary *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary *extraData) NSDictionary *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary *extraData)
{ {
id error = RCTMakeError(message, toStringify, extraData); NSDictionary *error = RCTMakeError(message, toStringify, extraData);
RCTLogError(@"\nError: %@", error); RCTLogError(@"\nError: %@", error);
return error; return error;
} }
@ -310,9 +310,9 @@ NSDictionary *RCTMakeAndLogError(NSString *message, id toStringify, NSDictionary
NSDictionary *RCTJSErrorFromNSError(NSError *error) NSDictionary *RCTJSErrorFromNSError(NSError *error)
{ {
NSString *errorMessage; NSString *errorMessage;
NSArray *stackTrace = [NSThread callStackSymbols]; NSArray<NSString *> *stackTrace = [NSThread callStackSymbols];
NSMutableDictionary *errorInfo = NSMutableDictionary *errorInfo =
[NSMutableDictionary dictionaryWithObject:stackTrace forKey:@"nativeStackIOS"]; [NSMutableDictionary dictionaryWithObject:stackTrace forKey:@"nativeStackIOS"];
if (error) { if (error) {
errorMessage = error.localizedDescription ?: @"Unknown error from a native module"; errorMessage = error.localizedDescription ?: @"Unknown error from a native module";
@ -351,7 +351,11 @@ id RCTSharedApplication(void)
return [[UIApplication class] performSelector:@selector(sharedApplication)]; return [[UIApplication class] performSelector:@selector(sharedApplication)];
} }
id RCTAlertView(NSString *title, NSString *message, id delegate, NSString *cancelButtonTitle, NSArray *otherButtonTitles) id RCTAlertView(NSString *title,
NSString *message,
id delegate,
NSString *cancelButtonTitle,
NSArray<NSString *> *otherButtonTitles)
{ {
if (RCTRunningInAppExtension()) { if (RCTRunningInAppExtension()) {
RCTLogError(@"RCTAlertView is unavailable when running in an app extension"); RCTLogError(@"RCTAlertView is unavailable when running in an app extension");
@ -366,8 +370,7 @@ id RCTAlertView(NSString *title, NSString *message, id delegate, NSString *cance
[alertView addButtonWithTitle:cancelButtonTitle]; [alertView addButtonWithTitle:cancelButtonTitle];
alertView.cancelButtonIndex = 0; alertView.cancelButtonIndex = 0;
} }
for (NSString *buttonTitle in otherButtonTitles) for (NSString *buttonTitle in otherButtonTitles) {
{
[alertView addButtonWithTitle:buttonTitle]; [alertView addButtonWithTitle:buttonTitle];
} }
return alertView; return alertView;

View File

@ -93,7 +93,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)init)
// Private bridge interface to allow middle-batch calls // Private bridge interface to allow middle-batch calls
@interface RCTBridge (RCTContextExecutor) @interface RCTBridge (RCTContextExecutor)
- (void)handleBuffer:(NSArray *)buffer batchEnded:(BOOL)hasEnded; - (void)handleBuffer:(NSArray<NSArray *> *)buffer batchEnded:(BOOL)hasEnded;
@end @end
@ -345,7 +345,7 @@ static void RCTInstallJSCProfiler(RCTBridge *bridge, JSContextRef context)
[strongSelf _addNativeHook:RCTNoop withName:"noop"]; [strongSelf _addNativeHook:RCTNoop withName:"noop"];
__weak RCTBridge *bridge = strongSelf->_bridge; __weak RCTBridge *bridge = strongSelf->_bridge;
strongSelf->_context.context[@"nativeFlushQueueImmediate"] = ^(NSArray *calls){ strongSelf->_context.context[@"nativeFlushQueueImmediate"] = ^(NSArray<NSArray *> *calls){
if (!weakSelf.valid || !calls) { if (!weakSelf.valid || !calls) {
return; return;
} }

View File

@ -10,6 +10,7 @@
#import "RCTAlertManager.h" #import "RCTAlertManager.h"
#import "RCTAssert.h" #import "RCTAssert.h"
#import "RCTConvert.h"
#import "RCTLog.h" #import "RCTLog.h"
#import "RCTUtils.h" #import "RCTUtils.h"
@ -19,10 +20,10 @@
@implementation RCTAlertManager @implementation RCTAlertManager
{ {
NSMutableArray *_alerts; NSMutableArray<UIAlertView *> *_alerts;
NSMutableArray *_alertControllers; NSMutableArray<UIAlertController *> *_alertControllers;
NSMutableArray *_alertCallbacks; NSMutableArray<RCTResponseSenderBlock> *_alertCallbacks;
NSMutableArray *_alertButtonKeys; NSMutableArray<NSArray<NSString *> *> *_alertButtonKeys;
} }
RCT_EXPORT_MODULE() RCT_EXPORT_MODULE()
@ -70,10 +71,10 @@ RCT_EXPORT_MODULE()
RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
callback:(RCTResponseSenderBlock)callback) callback:(RCTResponseSenderBlock)callback)
{ {
NSString *title = args[@"title"]; NSString *title = [RCTConvert NSString:args[@"title"]];
NSString *message = args[@"message"]; NSString *message = [RCTConvert NSString:args[@"message"]];
NSString *type = args[@"type"]; NSString *type = [RCTConvert NSString:args[@"type"]];
NSArray *buttons = args[@"buttons"]; NSDictionaryArray *buttons = [RCTConvert NSDictionaryArray:args[@"buttons"]];
BOOL allowsTextInput = [type isEqual:@"plain-text"]; BOOL allowsTextInput = [type isEqual:@"plain-text"];
if (!title && !message) { if (!title && !message) {
@ -95,9 +96,11 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
} }
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0 #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
if ([UIAlertController class] == nil) { if ([UIAlertController class] == nil) {
UIAlertView *alertView = RCTAlertView(title, nil, self, nil, nil); UIAlertView *alertView = RCTAlertView(title, nil, self, nil, nil);
NSMutableArray *buttonKeys = [[NSMutableArray alloc] initWithCapacity:buttons.count]; NSMutableArray<NSString *> *buttonKeys = [[NSMutableArray alloc] initWithCapacity:buttons.count];
if (allowsTextInput) { if (allowsTextInput) {
alertView.alertViewStyle = UIAlertViewStylePlainTextInput; alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
@ -126,8 +129,11 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
[_alertButtonKeys addObject:buttonKeys]; [_alertButtonKeys addObject:buttonKeys];
[alertView show]; [alertView show];
} else } else
#endif #endif
{ {
UIAlertController *alertController = UIAlertController *alertController =
[UIAlertController alertControllerWithTitle:title [UIAlertController alertControllerWithTitle:title
@ -152,7 +158,7 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
UITextField *textField = allowsTextInput ? alertController.textFields.firstObject : nil; UITextField *textField = allowsTextInput ? alertController.textFields.firstObject : nil;
[alertController addAction:[UIAlertAction actionWithTitle:buttonTitle [alertController addAction:[UIAlertAction actionWithTitle:buttonTitle
style:buttonStyle style:buttonStyle
handler:^(UIAlertAction *action) { handler:^(__unused UIAlertAction *action) {
if (callback) { if (callback) {
if (allowsTextInput) { if (allowsTextInput) {
callback(@[buttonKey, textField.text]); callback(@[buttonKey, textField.text]);
@ -175,17 +181,14 @@ RCT_EXPORT_METHOD(alertWithArgs:(NSDictionary *)args
RCTAssert(index != NSNotFound, @"Dismissed alert was not recognised"); RCTAssert(index != NSNotFound, @"Dismissed alert was not recognised");
RCTResponseSenderBlock callback = _alertCallbacks[index]; RCTResponseSenderBlock callback = _alertCallbacks[index];
NSArray *buttonKeys = _alertButtonKeys[index]; NSArray<NSString *> *buttonKeys = _alertButtonKeys[index];
NSArray *args;
if (alertView.alertViewStyle == UIAlertViewStylePlainTextInput) { if (alertView.alertViewStyle == UIAlertViewStylePlainTextInput) {
args = @[buttonKeys[buttonIndex], [alertView textFieldAtIndex:0].text]; callback(@[buttonKeys[buttonIndex], [alertView textFieldAtIndex:0].text]);
} else { } else {
args = @[buttonKeys[buttonIndex]]; callback(@[buttonKeys[buttonIndex]]);
} }
callback(args);
[_alerts removeObjectAtIndex:index]; [_alerts removeObjectAtIndex:index];
[_alertCallbacks removeObjectAtIndex:index]; [_alertCallbacks removeObjectAtIndex:index];
[_alertButtonKeys removeObjectAtIndex:index]; [_alertButtonKeys removeObjectAtIndex:index];

View File

@ -27,11 +27,8 @@
@property (nonatomic, readonly, getter=isValid) BOOL valid; @property (nonatomic, readonly, getter=isValid) BOOL valid;
- (void)multiGet:(NSArray *)keys callback:(RCTResponseSenderBlock)callback; // Clear the RCTAsyncLocalStorage data from native code
- (void)multiSet:(NSArray *)kvPairs callback:(RCTResponseSenderBlock)callback; - (void)clearAllData;
- (void)multiRemove:(NSArray *)keys callback:(RCTResponseSenderBlock)callback;
- (void)clear:(RCTResponseSenderBlock)callback;
- (void)getAllKeys:(RCTResponseSenderBlock)callback;
// For clearing data when the bridge may not exist, e.g. when logging out. // For clearing data when the bridge may not exist, e.g. when logging out.
+ (void)clearAllData; + (void)clearAllData;

View File

@ -14,6 +14,7 @@
#import <CommonCrypto/CommonCryptor.h> #import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonDigest.h> #import <CommonCrypto/CommonDigest.h>
#import "RCTConvert.h"
#import "RCTLog.h" #import "RCTLog.h"
#import "RCTUtils.h" #import "RCTUtils.h"
@ -23,7 +24,7 @@ static const NSUInteger RCTInlineValueThreshold = 100;
#pragma mark - Static helper functions #pragma mark - Static helper functions
static id RCTErrorForKey(NSString *key) static NSDictionary *RCTErrorForKey(NSString *key)
{ {
if (![key isKindOfClass:[NSString class]]) { if (![key isKindOfClass:[NSString class]]) {
return RCTMakeAndLogError(@"Invalid key - must be a string. Key: ", key, @{@"key": key}); return RCTMakeAndLogError(@"Invalid key - must be a string. Key: ", key, @{@"key": key});
@ -34,7 +35,7 @@ static id RCTErrorForKey(NSString *key)
} }
} }
static void RCTAppendError(id error, NSMutableArray **errors) static void RCTAppendError(NSDictionary *error, NSMutableArray<NSDictionary *> **errors)
{ {
if (error && errors) { if (error && errors) {
if (!*errors) { if (!*errors) {
@ -44,7 +45,7 @@ static void RCTAppendError(id error, NSMutableArray **errors)
} }
} }
static id RCTReadFile(NSString *filePath, NSString *key, NSDictionary **errorOut) static NSString *RCTReadFile(NSString *filePath, NSString *key, NSDictionary **errorOut)
{ {
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSError *error; NSError *error;
@ -148,6 +149,14 @@ RCT_EXPORT_MODULE()
return RCTGetMethodQueue(); return RCTGetMethodQueue();
} }
- (void)clearAllData
{
dispatch_async(RCTGetMethodQueue(), ^{
_manifest = [NSMutableDictionary new];
RCTDeleteStorageDirectory();
});
}
+ (void)clearAllData + (void)clearAllData
{ {
dispatch_async(RCTGetMethodQueue(), ^{ dispatch_async(RCTGetMethodQueue(), ^{
@ -181,7 +190,7 @@ RCT_EXPORT_MODULE()
return [RCTGetStorageDirectory() stringByAppendingPathComponent:safeFileName]; return [RCTGetStorageDirectory() stringByAppendingPathComponent:safeFileName];
} }
- (id)_ensureSetup - (NSDictionary *)_ensureSetup
{ {
RCTAssertThread(RCTGetMethodQueue(), @"Must be executed on storage thread"); RCTAssertThread(RCTGetMethodQueue(), @"Must be executed on storage thread");
@ -199,7 +208,7 @@ RCT_EXPORT_MODULE()
if (!_haveSetup) { if (!_haveSetup) {
NSDictionary *errorOut; NSDictionary *errorOut;
NSString *serialized = RCTReadFile(RCTGetManifestFilePath(), nil, &errorOut); NSString *serialized = RCTReadFile(RCTGetManifestFilePath(), nil, &errorOut);
_manifest = serialized ? [RCTJSONParse(serialized, &error) mutableCopy] : [NSMutableDictionary new]; _manifest = serialized ? RCTJSONParseMutable(serialized, &error) : [NSMutableDictionary new];
if (error) { if (error) {
RCTLogWarn(@"Failed to parse manifest - creating new one.\n\n%@", error); RCTLogWarn(@"Failed to parse manifest - creating new one.\n\n%@", error);
_manifest = [NSMutableDictionary new]; _manifest = [NSMutableDictionary new];
@ -209,12 +218,12 @@ RCT_EXPORT_MODULE()
return nil; return nil;
} }
- (id)_writeManifest:(NSMutableArray **)errors - (NSDictionary *)_writeManifest:(NSMutableArray<NSDictionary *> **)errors
{ {
NSError *error; NSError *error;
NSString *serialized = RCTJSONStringify(_manifest, &error); NSString *serialized = RCTJSONStringify(_manifest, &error);
[serialized writeToFile:RCTGetManifestFilePath() atomically:YES encoding:NSUTF8StringEncoding error:&error]; [serialized writeToFile:RCTGetManifestFilePath() atomically:YES encoding:NSUTF8StringEncoding error:&error];
id errorOut; NSDictionary *errorOut;
if (error) { if (error) {
errorOut = RCTMakeError(@"Failed to write manifest file.", error, nil); errorOut = RCTMakeError(@"Failed to write manifest file.", error, nil);
RCTAppendError(errorOut, errors); RCTAppendError(errorOut, errors);
@ -222,20 +231,21 @@ RCT_EXPORT_MODULE()
return errorOut; return errorOut;
} }
- (id)_appendItemForKey:(NSString *)key toArray:(NSMutableArray *)result - (NSDictionary *)_appendItemForKey:(NSString *)key
toArray:(NSMutableArray<NSArray<NSString *> *> *)result
{ {
id errorOut = RCTErrorForKey(key); NSDictionary *errorOut = RCTErrorForKey(key);
if (errorOut) { if (errorOut) {
return errorOut; return errorOut;
} }
id value = [self _getValueForKey:key errorOut:&errorOut]; NSString *value = [self _getValueForKey:key errorOut:&errorOut];
[result addObject:@[key, RCTNullIfNil(value)]]; // Insert null if missing or failure. [result addObject:@[key, RCTNullIfNil(value)]]; // Insert null if missing or failure.
return errorOut; return errorOut;
} }
- (NSString *)_getValueForKey:(NSString *)key errorOut:(NSDictionary **)errorOut - (NSString *)_getValueForKey:(NSString *)key errorOut:(NSDictionary **)errorOut
{ {
id value = _manifest[key]; // nil means missing, null means there is a data file, anything else is an inline value. id value = _manifest[key]; // nil means missing, null means there is a data file, else: NSString
if (value == (id)kCFNull) { if (value == (id)kCFNull) {
NSString *filePath = [self _filePathForKey:key]; NSString *filePath = [self _filePathForKey:key];
value = RCTReadFile(filePath, key, errorOut); value = RCTReadFile(filePath, key, errorOut);
@ -243,16 +253,13 @@ RCT_EXPORT_MODULE()
return value; return value;
} }
- (id)_writeEntry:(NSArray *)entry - (NSDictionary *)_writeEntry:(NSArray<NSString *> *)entry
{ {
if (![entry isKindOfClass:[NSArray class]] || entry.count != 2) { if (entry.count != 2) {
return RCTMakeAndLogError(@"Entries must be arrays of the form [key: string, value: string], got: ", entry, nil); return RCTMakeAndLogError(@"Entries must be arrays of the form [key: string, value: string], got: ", entry, nil);
} }
if (![entry[1] isKindOfClass:[NSString class]]) {
return RCTMakeAndLogError(@"Values must be strings, got: ", entry[1], @{@"key": entry[0]});
}
NSString *key = entry[0]; NSString *key = entry[0];
id errorOut = RCTErrorForKey(key); NSDictionary *errorOut = RCTErrorForKey(key);
if (errorOut) { if (errorOut) {
return errorOut; return errorOut;
} }
@ -278,66 +285,63 @@ RCT_EXPORT_MODULE()
#pragma mark - Exported JS Functions #pragma mark - Exported JS Functions
RCT_EXPORT_METHOD(multiGet:(NSArray *)keys RCT_EXPORT_METHOD(multiGet:(NSStringArray *)keys
callback:(RCTResponseSenderBlock)callback) callback:(RCTResponseSenderBlock)callback)
{ {
if (!callback) { NSDictionary *errorOut = [self _ensureSetup];
RCTLogError(@"Called getItem without a callback.");
return;
}
id errorOut = [self _ensureSetup];
if (errorOut) { if (errorOut) {
callback(@[@[errorOut], (id)kCFNull]); callback(@[@[errorOut], (id)kCFNull]);
return; return;
} }
NSMutableArray *errors; NSMutableArray<NSDictionary *> *errors;
NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:keys.count]; NSMutableArray<NSArray<NSString *> *> *result = [[NSMutableArray alloc] initWithCapacity:keys.count];
for (NSString *key in keys) { for (NSString *key in keys) {
id keyError = [self _appendItemForKey:key toArray:result]; NSDictionary *keyError = [self _appendItemForKey:key toArray:result];
RCTAppendError(keyError, &errors); RCTAppendError(keyError, &errors);
} }
callback(@[RCTNullIfNil(errors), result]); callback(@[RCTNullIfNil(errors), result]);
} }
RCT_EXPORT_METHOD(multiSet:(NSArray *)kvPairs RCT_EXPORT_METHOD(multiSet:(NSStringArrayArray *)kvPairs
callback:(RCTResponseSenderBlock)callback) callback:(RCTResponseSenderBlock)callback)
{ {
id errorOut = [self _ensureSetup]; NSDictionary *errorOut = [self _ensureSetup];
if (errorOut) { if (errorOut) {
callback(@[@[errorOut]]); callback(@[@[errorOut]]);
return; return;
} }
NSMutableArray *errors; NSMutableArray<NSDictionary *> *errors;
for (NSArray *entry in kvPairs) { for (NSArray<NSString *> *entry in kvPairs) {
id keyError = [self _writeEntry:entry]; NSDictionary *keyError = [self _writeEntry:entry];
RCTAppendError(keyError, &errors); RCTAppendError(keyError, &errors);
} }
[self _writeManifest:&errors]; [self _writeManifest:&errors];
if (callback) { callback(@[RCTNullIfNil(errors)]);
callback(@[RCTNullIfNil(errors)]);
}
} }
RCT_EXPORT_METHOD(multiMerge:(NSArray *)kvPairs RCT_EXPORT_METHOD(multiMerge:(NSStringArrayArray *)kvPairs
callback:(RCTResponseSenderBlock)callback) callback:(RCTResponseSenderBlock)callback)
{ {
id errorOut = [self _ensureSetup]; NSDictionary *errorOut = [self _ensureSetup];
if (errorOut) { if (errorOut) {
callback(@[@[errorOut]]); callback(@[@[errorOut]]);
return; return;
} }
NSMutableArray *errors; NSMutableArray<NSDictionary *> *errors;
for (__strong NSArray *entry in kvPairs) { for (__strong NSArray<NSString *> *entry in kvPairs) {
id keyError; NSDictionary *keyError;
NSString *value = [self _getValueForKey:entry[0] errorOut:&keyError]; NSString *value = [self _getValueForKey:entry[0] errorOut:&keyError];
if (keyError) { if (keyError) {
RCTAppendError(keyError, &errors); RCTAppendError(keyError, &errors);
} else { } else {
if (value) { if (value) {
NSMutableDictionary *mergedVal = [RCTJSONParseMutable(value, &keyError) mutableCopy]; NSError *jsonError;
RCTMergeRecursive(mergedVal, RCTJSONParse(entry[1], &keyError)); NSMutableDictionary *mergedVal = RCTJSONParseMutable(value, &jsonError);
entry = @[entry[0], RCTJSONStringify(mergedVal, &keyError)]; RCTMergeRecursive(mergedVal, RCTJSONParse(entry[1], &jsonError));
entry = @[entry[0], RCTNullIfNil(RCTJSONStringify(mergedVal, NULL))];
if (jsonError) {
keyError = RCTJSErrorFromNSError(jsonError);
}
} }
if (!keyError) { if (!keyError) {
keyError = [self _writeEntry:entry]; keyError = [self _writeEntry:entry];
@ -346,22 +350,20 @@ RCT_EXPORT_METHOD(multiMerge:(NSArray *)kvPairs
} }
} }
[self _writeManifest:&errors]; [self _writeManifest:&errors];
if (callback) { callback(@[RCTNullIfNil(errors)]);
callback(@[RCTNullIfNil(errors)]);
}
} }
RCT_EXPORT_METHOD(multiRemove:(NSArray *)keys RCT_EXPORT_METHOD(multiRemove:(NSStringArray *)keys
callback:(RCTResponseSenderBlock)callback) callback:(RCTResponseSenderBlock)callback)
{ {
id errorOut = [self _ensureSetup]; NSDictionary *errorOut = [self _ensureSetup];
if (errorOut) { if (errorOut) {
callback(@[@[errorOut]]); callback(@[@[errorOut]]);
return; return;
} }
NSMutableArray *errors; NSMutableArray<NSDictionary *> *errors;
for (NSString *key in keys) { for (NSString *key in keys) {
id keyError = RCTErrorForKey(key); NSDictionary *keyError = RCTErrorForKey(key);
if (!keyError) { if (!keyError) {
NSString *filePath = [self _filePathForKey:key]; NSString *filePath = [self _filePathForKey:key];
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil]; [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
@ -370,23 +372,19 @@ RCT_EXPORT_METHOD(multiRemove:(NSArray *)keys
RCTAppendError(keyError, &errors); RCTAppendError(keyError, &errors);
} }
[self _writeManifest:&errors]; [self _writeManifest:&errors];
if (callback) { callback(@[RCTNullIfNil(errors)]);
callback(@[RCTNullIfNil(errors)]);
}
} }
RCT_EXPORT_METHOD(clear:(RCTResponseSenderBlock)callback) RCT_EXPORT_METHOD(clear:(RCTResponseSenderBlock)callback)
{ {
_manifest = [NSMutableDictionary new]; _manifest = [NSMutableDictionary new];
NSError *error = RCTDeleteStorageDirectory(); NSError *error = RCTDeleteStorageDirectory();
if (callback) { callback(@[RCTNullIfNil(error)]);
callback(@[RCTNullIfNil(error)]);
}
} }
RCT_EXPORT_METHOD(getAllKeys:(RCTResponseSenderBlock)callback) RCT_EXPORT_METHOD(getAllKeys:(RCTResponseSenderBlock)callback)
{ {
id errorOut = [self _ensureSetup]; NSDictionary *errorOut = [self _ensureSetup];
if (errorOut) { if (errorOut) {
callback(@[errorOut, (id)kCFNull]); callback(@[errorOut, (id)kCFNull]);
} else { } else {

View File

@ -138,8 +138,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
NSURLSessionDataTask *_updateTask; NSURLSessionDataTask *_updateTask;
NSURL *_liveReloadURL; NSURL *_liveReloadURL;
BOOL _jsLoaded; BOOL _jsLoaded;
NSArray *_presentedItems; NSArray<RCTDevMenuItem *> *_presentedItems;
NSMutableArray *_extraMenuItems; NSMutableArray<RCTDevMenuItem *> *_extraMenuItems;
} }
@synthesize bridge = _bridge; @synthesize bridge = _bridge;
@ -375,9 +375,9 @@ RCT_EXPORT_MODULE()
[self settingsDidChange]; [self settingsDidChange];
} }
- (NSArray *)menuItems - (NSArray<RCTDevMenuItem *> *)menuItems
{ {
NSMutableArray *items = [NSMutableArray new]; NSMutableArray<RCTDevMenuItem *> *items = [NSMutableArray new];
// Add built-in items // Add built-in items
@ -435,7 +435,7 @@ RCT_EXPORT_METHOD(show)
actionSheet.title = @"React Native: Development"; actionSheet.title = @"React Native: Development";
actionSheet.delegate = self; actionSheet.delegate = self;
NSArray *items = [self menuItems]; NSArray<RCTDevMenuItem *> *items = [self menuItems];
for (RCTDevMenuItem *item in items) { for (RCTDevMenuItem *item in items) {
switch (item.type) { switch (item.type) {
case RCTDevMenuTypeButton: { case RCTDevMenuTypeButton: {

View File

@ -15,13 +15,14 @@
// NOTE: Remove these three methods and the @optional directive after updating the codebase to use only the three below // NOTE: Remove these three methods and the @optional directive after updating the codebase to use only the three below
@optional @optional
- (void)handleSoftJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack;
- (void)handleFatalJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack;
- (void)updateJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack;
- (void)handleSoftJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack exceptionId:(NSNumber *)exceptionId; - (void)handleSoftJSExceptionWithMessage:(NSString *)message stack:(NSArray<NSDictionary *> *)stack;
- (void)handleFatalJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack exceptionId:(NSNumber *)exceptionId; - (void)handleFatalJSExceptionWithMessage:(NSString *)message stack:(NSArray<NSDictionary *> *)stack;
- (void)updateJSExceptionWithMessage:(NSString *)message stack:(NSArray *)stack exceptionId:(NSNumber *)exceptionId; - (void)updateJSExceptionWithMessage:(NSString *)message stack:(NSArray<NSDictionary *> *)stack;
- (void)handleSoftJSExceptionWithMessage:(NSString *)message stack:(NSArray<NSDictionary *> *)stack exceptionId:(NSNumber *)exceptionId;
- (void)handleFatalJSExceptionWithMessage:(NSString *)message stack:(NSArray<NSDictionary *> *)stack exceptionId:(NSNumber *)exceptionId;
- (void)updateJSExceptionWithMessage:(NSString *)message stack:(NSArray<NSDictionary *> *)stack exceptionId:(NSNumber *)exceptionId;
@end @end

View File

@ -9,6 +9,7 @@
#import "RCTExceptionsManager.h" #import "RCTExceptionsManager.h"
#import "RCTConvert.h"
#import "RCTDefines.h" #import "RCTDefines.h"
#import "RCTLog.h" #import "RCTLog.h"
#import "RCTRedBox.h" #import "RCTRedBox.h"
@ -39,7 +40,7 @@ RCT_EXPORT_MODULE()
} }
RCT_EXPORT_METHOD(reportSoftException:(NSString *)message RCT_EXPORT_METHOD(reportSoftException:(NSString *)message
stack:(NSArray *)stack stack:(NSDictionaryArray *)stack
exceptionId:(nonnull NSNumber *)exceptionId) exceptionId:(nonnull NSNumber *)exceptionId)
{ {
// TODO(#7070533): report a soft error to the server // TODO(#7070533): report a soft error to the server
@ -55,7 +56,7 @@ RCT_EXPORT_METHOD(reportSoftException:(NSString *)message
} }
RCT_EXPORT_METHOD(reportFatalException:(NSString *)message RCT_EXPORT_METHOD(reportFatalException:(NSString *)message
stack:(NSArray *)stack stack:(NSDictionaryArray *)stack
exceptionId:(nonnull NSNumber *)exceptionId) exceptionId:(nonnull NSNumber *)exceptionId)
{ {
if (_delegate) { if (_delegate) {
@ -98,7 +99,7 @@ RCT_EXPORT_METHOD(reportFatalException:(NSString *)message
} }
RCT_EXPORT_METHOD(updateExceptionMessage:(NSString *)message RCT_EXPORT_METHOD(updateExceptionMessage:(NSString *)message
stack:(NSArray *)stack stack:(NSDictionaryArray *)stack
exceptionId:(nonnull NSNumber *)exceptionId) exceptionId:(nonnull NSNumber *)exceptionId)
{ {
if (_delegate) { if (_delegate) {
@ -115,7 +116,7 @@ RCT_EXPORT_METHOD(updateExceptionMessage:(NSString *)message
// Deprecated. Use reportFatalException directly instead. // Deprecated. Use reportFatalException directly instead.
RCT_EXPORT_METHOD(reportUnhandledException:(NSString *)message RCT_EXPORT_METHOD(reportUnhandledException:(NSString *)message
stack:(NSArray *)stack) stack:(NSDictionaryArray *)stack)
{ {
[self reportFatalException:message stack:stack exceptionId:@-1]; [self reportFatalException:message stack:stack exceptionId:@-1];
} }

View File

@ -17,8 +17,8 @@
- (void)showError:(NSError *)error; - (void)showError:(NSError *)error;
- (void)showErrorMessage:(NSString *)message; - (void)showErrorMessage:(NSString *)message;
- (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details; - (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details;
- (void)showErrorMessage:(NSString *)message withStack:(NSArray *)stack; - (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack;
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray *)stack; - (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack;
- (void)dismiss; - (void)dismiss;

View File

@ -23,7 +23,7 @@
{ {
UITableView *_stackTraceTableView; UITableView *_stackTraceTableView;
NSString *_lastErrorMessage; NSString *_lastErrorMessage;
NSArray *_lastStackTrace; NSArray<NSDictionary *> *_lastStackTrace;
} }
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
@ -103,7 +103,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
[[[NSURLSession sharedSession] dataTaskWithRequest:request] resume]; [[[NSURLSession sharedSession] dataTaskWithRequest:request] resume];
} }
- (void)showErrorMessage:(NSString *)message withStack:(NSArray *)stack showIfHidden:(BOOL)shouldShow - (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack showIfHidden:(BOOL)shouldShow
{ {
if ((self.hidden && shouldShow) || (!self.hidden && [_lastErrorMessage isEqualToString:message])) { if ((self.hidden && shouldShow) || (!self.hidden && [_lastErrorMessage isEqualToString:message])) {
_lastStackTrace = stack; _lastStackTrace = stack;
@ -225,7 +225,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
#pragma mark - Key commands #pragma mark - Key commands
- (NSArray *)keyCommands - (NSArray<UIKeyCommand *> *)keyCommands
{ {
// NOTE: We could use RCTKeyCommands for this, but since // NOTE: We could use RCTKeyCommands for this, but since
// we control this window, we can use the standard, non-hacky // we control this window, we can use the standard, non-hacky
@ -281,17 +281,17 @@ RCT_EXPORT_MODULE()
[self showErrorMessage:combinedMessage]; [self showErrorMessage:combinedMessage];
} }
- (void)showErrorMessage:(NSString *)message withStack:(NSArray *)stack - (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack
{ {
[self showErrorMessage:message withStack:stack showIfHidden:YES]; [self showErrorMessage:message withStack:stack showIfHidden:YES];
} }
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray *)stack - (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack
{ {
[self showErrorMessage:message withStack:stack showIfHidden:NO]; [self showErrorMessage:message withStack:stack showIfHidden:NO];
} }
- (void)showErrorMessage:(NSString *)message withStack:(NSArray *)stack showIfHidden:(BOOL)shouldShow - (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack showIfHidden:(BOOL)shouldShow
{ {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
if (!_window) { if (!_window) {
@ -332,9 +332,9 @@ RCT_EXPORT_MODULE()
- (void)showError:(NSError *)message {} - (void)showError:(NSError *)message {}
- (void)showErrorMessage:(NSString *)message {} - (void)showErrorMessage:(NSString *)message {}
- (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details {} - (void)showErrorMessage:(NSString *)message withDetails:(NSString *)details {}
- (void)showErrorMessage:(NSString *)message withStack:(NSArray *)stack {} - (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack {}
- (void)updateErrorMessage:(NSString *)message withStack:(NSArray *)stack {} - (void)updateErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack {}
- (void)showErrorMessage:(NSString *)message withStack:(NSArray *)stack showIfHidden:(BOOL)shouldShow {} - (void)showErrorMessage:(NSString *)message withStack:(NSArray<NSDictionary *> *)stack showIfHidden:(BOOL)shouldShow {}
- (void)dismiss {} - (void)dismiss {}
@end @end

View File

@ -145,7 +145,7 @@ RCT_EXPORT_MODULE()
- (void)didUpdateFrame:(__unused RCTFrameUpdate *)update - (void)didUpdateFrame:(__unused RCTFrameUpdate *)update
{ {
NSMutableArray *timersToCall = [NSMutableArray new]; NSMutableArray<NSNumber *> *timersToCall = [NSMutableArray new];
for (RCTTimer *timer in _timers.allObjects) { for (RCTTimer *timer in _timers.allObjects) {
if ([timer updateFoundNeedsJSUpdate]) { if ([timer updateFoundNeedsJSUpdate]) {
[timersToCall addObject:timer.callbackID]; [timersToCall addObject:timer.callbackID];

View File

@ -191,8 +191,8 @@ static UIViewAnimationOptions UIViewAnimationOptionsFromRCTAnimationType(RCTAnim
dispatch_queue_t _shadowQueue; dispatch_queue_t _shadowQueue;
// Root views are only mutated on the shadow queue // Root views are only mutated on the shadow queue
NSMutableSet *_rootViewTags; NSMutableSet<NSNumber *> *_rootViewTags;
NSMutableArray *_pendingUIBlocks; NSMutableArray<dispatch_block_t> *_pendingUIBlocks;
// Animation // Animation
RCTLayoutAnimation *_nextLayoutAnimation; // RCT thread only RCTLayoutAnimation *_nextLayoutAnimation; // RCT thread only
@ -201,7 +201,7 @@ static UIViewAnimationOptions UIViewAnimationOptionsFromRCTAnimationType(RCTAnim
// Keyed by viewName // Keyed by viewName
NSDictionary *_componentDataByName; NSDictionary *_componentDataByName;
NSMutableSet *_bridgeTransactionListeners; NSMutableSet<id<RCTComponent>> *_bridgeTransactionListeners;
} }
@synthesize bridge = _bridge; @synthesize bridge = _bridge;
@ -396,7 +396,8 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
/** /**
* Unregisters views from registries * Unregisters views from registries
*/ */
- (void)_purgeChildren:(NSArray *)children fromRegistry:(RCTSparseArray *)registry - (void)_purgeChildren:(NSArray<id<RCTComponent>> *)children
fromRegistry:(RCTSparseArray *)registry
{ {
for (id<RCTComponent> child in children) { for (id<RCTComponent> child in children) {
RCTTraverseViewNodes(registry[child.reactTag], ^(id<RCTComponent> subview) { RCTTraverseViewNodes(registry[child.reactTag], ^(id<RCTComponent> subview) {
@ -442,7 +443,7 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
{ {
RCTAssert(![NSThread isMainThread], @"Should be called on shadow thread"); RCTAssert(![NSThread isMainThread], @"Should be called on shadow thread");
NSMutableSet *viewsWithNewFrames = [NSMutableSet setWithCapacity:1]; NSMutableSet<RCTShadowView *> *viewsWithNewFrames = [NSMutableSet setWithCapacity:1];
// This is nuanced. In the JS thread, we create a new update buffer // This is nuanced. In the JS thread, we create a new update buffer
// `frameTags`/`frames` that is created/mutated in the JS thread. We access // `frameTags`/`frames` that is created/mutated in the JS thread. We access
@ -452,10 +453,14 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
[rootShadowView collectRootUpdatedFrames:viewsWithNewFrames]; [rootShadowView collectRootUpdatedFrames:viewsWithNewFrames];
// Parallel arrays are built and then handed off to main thread // Parallel arrays are built and then handed off to main thread
NSMutableArray *frameReactTags = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count]; NSMutableArray<NSNumber *> *frameReactTags =
NSMutableArray *frames = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count]; [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count];
NSMutableArray *areNew = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count]; NSMutableArray<NSValue *> *frames =
NSMutableArray *parentsAreNew = [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count]; [NSMutableArray arrayWithCapacity:viewsWithNewFrames.count];
NSMutableArray<NSNumber *> *areNew =
[NSMutableArray arrayWithCapacity:viewsWithNewFrames.count];
NSMutableArray<NSNumber *> *parentsAreNew =
[NSMutableArray arrayWithCapacity:viewsWithNewFrames.count];
for (RCTShadowView *shadowView in viewsWithNewFrames) { for (RCTShadowView *shadowView in viewsWithNewFrames) {
[frameReactTags addObject:shadowView.reactTag]; [frameReactTags addObject:shadowView.reactTag];
@ -473,7 +478,7 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
// reactSetFrame: has been called. Note that if reactSetFrame: is not called, // reactSetFrame: has been called. Note that if reactSetFrame: is not called,
// these won't be called either, so this is not a suitable place to update // these won't be called either, so this is not a suitable place to update
// properties that aren't related to layout. // properties that aren't related to layout.
NSMutableArray *updateBlocks = [NSMutableArray new]; NSMutableArray<RCTViewManagerUIBlock> *updateBlocks = [NSMutableArray new];
for (RCTShadowView *shadowView in viewsWithNewFrames) { for (RCTShadowView *shadowView in viewsWithNewFrames) {
RCTViewManager *manager = [_componentDataByName[shadowView.viewName] manager]; RCTViewManager *manager = [_componentDataByName[shadowView.viewName] manager];
RCTViewManagerUIBlock block = [manager uiBlockToAmendWithShadowView:shadowView]; RCTViewManagerUIBlock block = [manager uiBlockToAmendWithShadowView:shadowView];
@ -583,7 +588,7 @@ extern NSString *RCTBridgeModuleNameForClass(Class cls);
- (void)_amendPendingUIBlocksWithStylePropagationUpdateForRootView:(RCTShadowView *)topView - (void)_amendPendingUIBlocksWithStylePropagationUpdateForRootView:(RCTShadowView *)topView
{ {
NSMutableSet *applierBlocks = [NSMutableSet setWithCapacity:1]; NSMutableSet<RCTApplierBlock> *applierBlocks = [NSMutableSet setWithCapacity:1];
[topView collectUpdatedProperties:applierBlocks parentProperties:@{}]; [topView collectUpdatedProperties:applierBlocks parentProperties:@{}];
if (applierBlocks.count) { if (applierBlocks.count) {
@ -605,7 +610,7 @@ RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(nonnull NSNumber *)containe
RCTAssert(container != nil, @"container view (for ID %@) not found", containerID); RCTAssert(container != nil, @"container view (for ID %@) not found", containerID);
NSUInteger subviewsCount = [container reactSubviews].count; NSUInteger subviewsCount = [container reactSubviews].count;
NSMutableArray *indices = [[NSMutableArray alloc] initWithCapacity:subviewsCount]; NSMutableArray<NSNumber *> *indices = [[NSMutableArray alloc] initWithCapacity:subviewsCount];
for (NSUInteger childIndex = 0; childIndex < subviewsCount; childIndex++) { for (NSUInteger childIndex = 0; childIndex < subviewsCount; childIndex++) {
[indices addObject:@(childIndex)]; [indices addObject:@(childIndex)];
} }
@ -624,8 +629,8 @@ RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(nonnull NSNumber *)containe
* *
* @returns Array of removed items. * @returns Array of removed items.
*/ */
- (NSArray *)_childrenToRemoveFromContainer:(id<RCTComponent>)container - (NSArray<id<RCTComponent>> *)_childrenToRemoveFromContainer:(id<RCTComponent>)container
atIndices:(NSArray *)atIndices atIndices:(NSArray<NSNumber *> *)atIndices
{ {
// If there are no indices to move or the container has no subviews don't bother // If there are no indices to move or the container has no subviews don't bother
// We support parents with nil subviews so long as they're all nil so this allows for this behavior // We support parents with nil subviews so long as they're all nil so this allows for this behavior
@ -633,7 +638,7 @@ RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(nonnull NSNumber *)containe
return nil; return nil;
} }
// Construction of removed children must be done "up front", before indices are disturbed by removals. // Construction of removed children must be done "up front", before indices are disturbed by removals.
NSMutableArray *removedChildren = [NSMutableArray arrayWithCapacity:atIndices.count]; NSMutableArray<id<RCTComponent>> *removedChildren = [NSMutableArray arrayWithCapacity:atIndices.count];
RCTAssert(container != nil, @"container view (for ID %@) not found", container); RCTAssert(container != nil, @"container view (for ID %@) not found", container);
for (NSNumber *indexNumber in atIndices) { for (NSNumber *indexNumber in atIndices) {
NSUInteger index = indexNumber.unsignedIntegerValue; NSUInteger index = indexNumber.unsignedIntegerValue;
@ -648,9 +653,10 @@ RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID:(nonnull NSNumber *)containe
return removedChildren; return removedChildren;
} }
- (void)_removeChildren:(NSArray *)children fromContainer:(id<RCTComponent>)container - (void)_removeChildren:(NSArray<id<RCTComponent>> *)children
fromContainer:(id<RCTComponent>)container
{ {
for (id removedChild in children) { for (id<RCTComponent> removedChild in children) {
[container removeReactSubview:removedChild]; [container removeReactSubview:removedChild];
} }
} }
@ -659,14 +665,14 @@ RCT_EXPORT_METHOD(removeRootView:(nonnull NSNumber *)rootReactTag)
{ {
RCTShadowView *rootShadowView = _shadowViewRegistry[rootReactTag]; RCTShadowView *rootShadowView = _shadowViewRegistry[rootReactTag];
RCTAssert(rootShadowView.superview == nil, @"root view cannot have superview (ID %@)", rootReactTag); RCTAssert(rootShadowView.superview == nil, @"root view cannot have superview (ID %@)", rootReactTag);
[self _purgeChildren:rootShadowView.reactSubviews fromRegistry:_shadowViewRegistry]; [self _purgeChildren:(NSArray<id<RCTComponent>> *)rootShadowView.reactSubviews fromRegistry:_shadowViewRegistry];
_shadowViewRegistry[rootReactTag] = nil; _shadowViewRegistry[rootReactTag] = nil;
[_rootViewTags removeObject:rootReactTag]; [_rootViewTags removeObject:rootReactTag];
[self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){ [self addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry){
RCTAssertMainThread(); RCTAssertMainThread();
UIView *rootView = viewRegistry[rootReactTag]; UIView *rootView = viewRegistry[rootReactTag];
[uiManager _purgeChildren:rootView.reactSubviews fromRegistry:viewRegistry]; [uiManager _purgeChildren:(NSArray<id<RCTComponent>> *)rootView.reactSubviews fromRegistry:viewRegistry];
viewRegistry[rootReactTag] = nil; viewRegistry[rootReactTag] = nil;
[[NSNotificationCenter defaultCenter] postNotificationName:RCTUIManagerDidRemoveRootViewNotification [[NSNotificationCenter defaultCenter] postNotificationName:RCTUIManagerDidRemoveRootViewNotification
@ -675,7 +681,8 @@ RCT_EXPORT_METHOD(removeRootView:(nonnull NSNumber *)rootReactTag)
}]; }];
} }
RCT_EXPORT_METHOD(replaceExistingNonRootView:(nonnull NSNumber *)reactTag withView:(nonnull NSNumber *)newReactTag) RCT_EXPORT_METHOD(replaceExistingNonRootView:(nonnull NSNumber *)reactTag
withView:(nonnull NSNumber *)newReactTag)
{ {
RCTShadowView *shadowView = _shadowViewRegistry[reactTag]; RCTShadowView *shadowView = _shadowViewRegistry[reactTag];
RCTAssert(shadowView != nil, @"shadowView (for ID %@) not found", reactTag); RCTAssert(shadowView != nil, @"shadowView (for ID %@) not found", reactTag);
@ -685,8 +692,8 @@ RCT_EXPORT_METHOD(replaceExistingNonRootView:(nonnull NSNumber *)reactTag withVi
NSUInteger indexOfView = [superShadowView.reactSubviews indexOfObject:shadowView]; NSUInteger indexOfView = [superShadowView.reactSubviews indexOfObject:shadowView];
RCTAssert(indexOfView != NSNotFound, @"View's superview doesn't claim it as subview (id %@)", reactTag); RCTAssert(indexOfView != NSNotFound, @"View's superview doesn't claim it as subview (id %@)", reactTag);
NSArray *removeAtIndices = @[@(indexOfView)]; NSArray<NSNumber *> *removeAtIndices = @[@(indexOfView)];
NSArray *addTags = @[newReactTag]; NSArray<NSNumber *> *addTags = @[newReactTag];
[self manageChildren:superShadowView.reactTag [self manageChildren:superShadowView.reactTag
moveFromIndices:nil moveFromIndices:nil
moveToIndices:nil moveToIndices:nil
@ -696,11 +703,11 @@ RCT_EXPORT_METHOD(replaceExistingNonRootView:(nonnull NSNumber *)reactTag withVi
} }
RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerReactTag RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerReactTag
moveFromIndices:(NSArray *)moveFromIndices moveFromIndices:(NSNumberArray *)moveFromIndices
moveToIndices:(NSArray *)moveToIndices moveToIndices:(NSNumberArray *)moveToIndices
addChildReactTags:(NSArray *)addChildReactTags addChildReactTags:(NSNumberArray *)addChildReactTags
addAtIndices:(NSArray *)addAtIndices addAtIndices:(NSNumberArray *)addAtIndices
removeAtIndices:(NSArray *)removeAtIndices) removeAtIndices:(NSNumberArray *)removeAtIndices)
{ {
[self _manageChildren:containerReactTag [self _manageChildren:containerReactTag
moveFromIndices:moveFromIndices moveFromIndices:moveFromIndices
@ -722,11 +729,11 @@ RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerReactTag
} }
- (void)_manageChildren:(NSNumber *)containerReactTag - (void)_manageChildren:(NSNumber *)containerReactTag
moveFromIndices:(NSArray *)moveFromIndices moveFromIndices:(NSArray<NSNumber *> *)moveFromIndices
moveToIndices:(NSArray *)moveToIndices moveToIndices:(NSArray<NSNumber *> *)moveToIndices
addChildReactTags:(NSArray *)addChildReactTags addChildReactTags:(NSArray<NSNumber *> *)addChildReactTags
addAtIndices:(NSArray *)addAtIndices addAtIndices:(NSArray<NSNumber *> *)addAtIndices
removeAtIndices:(NSArray *)removeAtIndices removeAtIndices:(NSArray<NSNumber *> *)removeAtIndices
registry:(RCTSparseArray *)registry registry:(RCTSparseArray *)registry
{ {
id<RCTComponent> container = registry[containerReactTag]; id<RCTComponent> container = registry[containerReactTag];
@ -734,8 +741,10 @@ RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerReactTag
RCTAssert(addChildReactTags.count == addAtIndices.count, @"there should be at least one React child to add"); RCTAssert(addChildReactTags.count == addAtIndices.count, @"there should be at least one React child to add");
// Removes (both permanent and temporary moves) are using "before" indices // Removes (both permanent and temporary moves) are using "before" indices
NSArray *permanentlyRemovedChildren = [self _childrenToRemoveFromContainer:container atIndices:removeAtIndices]; NSArray<id<RCTComponent>> *permanentlyRemovedChildren =
NSArray *temporarilyRemovedChildren = [self _childrenToRemoveFromContainer:container atIndices:moveFromIndices]; [self _childrenToRemoveFromContainer:container atIndices:removeAtIndices];
NSArray<id<RCTComponent>> *temporarilyRemovedChildren =
[self _childrenToRemoveFromContainer:container atIndices:moveFromIndices];
[self _removeChildren:permanentlyRemovedChildren fromContainer:container]; [self _removeChildren:permanentlyRemovedChildren fromContainer:container];
[self _removeChildren:temporarilyRemovedChildren fromContainer:container]; [self _removeChildren:temporarilyRemovedChildren fromContainer:container];
@ -749,15 +758,17 @@ RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerReactTag
destinationsToChildrenToAdd[moveToIndices[index]] = temporarilyRemovedChildren[index]; destinationsToChildrenToAdd[moveToIndices[index]] = temporarilyRemovedChildren[index];
} }
for (NSInteger index = 0, length = addAtIndices.count; index < length; index++) { for (NSInteger index = 0, length = addAtIndices.count; index < length; index++) {
id view = registry[addChildReactTags[index]]; id<RCTComponent> view = registry[addChildReactTags[index]];
if (view) { if (view) {
destinationsToChildrenToAdd[addAtIndices[index]] = view; destinationsToChildrenToAdd[addAtIndices[index]] = view;
} }
} }
NSArray *sortedIndices = [destinationsToChildrenToAdd.allKeys sortedArrayUsingSelector:@selector(compare:)]; NSArray<NSNumber *> *sortedIndices =
[destinationsToChildrenToAdd.allKeys sortedArrayUsingSelector:@selector(compare:)];
for (NSNumber *reactIndex in sortedIndices) { for (NSNumber *reactIndex in sortedIndices) {
[container insertReactSubview:destinationsToChildrenToAdd[reactIndex] atIndex:reactIndex.integerValue]; [container insertReactSubview:destinationsToChildrenToAdd[reactIndex]
atIndex:reactIndex.integerValue];
} }
} }
@ -894,7 +905,7 @@ RCT_EXPORT_METHOD(findSubviewIn:(nonnull NSNumber *)reactTag atPoint:(CGPoint)po
// First copy the previous blocks into a temporary variable, then reset the // First copy the previous blocks into a temporary variable, then reset the
// pending blocks to a new array. This guards against mutation while // pending blocks to a new array. This guards against mutation while
// processing the pending blocks in another thread. // processing the pending blocks in another thread.
NSArray *previousPendingUIBlocks = _pendingUIBlocks; NSArray<dispatch_block_t> *previousPendingUIBlocks = _pendingUIBlocks;
_pendingUIBlocks = [NSMutableArray new]; _pendingUIBlocks = [NSMutableArray new];
if (previousPendingUIBlocks.count) { if (previousPendingUIBlocks.count) {
@ -1036,8 +1047,9 @@ RCT_EXPORT_METHOD(measureViewsInRect:(CGRect)rect
RCTLogError(@"Attempting to measure view that does not exist (tag #%@)", reactTag); RCTLogError(@"Attempting to measure view that does not exist (tag #%@)", reactTag);
return; return;
} }
NSArray *childShadowViews = [shadowView reactSubviews]; NSArray<RCTShadowView *> *childShadowViews = [shadowView reactSubviews];
NSMutableArray *results = [[NSMutableArray alloc] initWithCapacity:childShadowViews.count]; NSMutableArray<NSDictionary *> *results =
[[NSMutableArray alloc] initWithCapacity:childShadowViews.count];
[childShadowViews enumerateObjectsUsingBlock: [childShadowViews enumerateObjectsUsingBlock:
^(RCTShadowView *childShadowView, NSUInteger idx, __unused BOOL *stop) { ^(RCTShadowView *childShadowView, NSUInteger idx, __unused BOOL *stop) {

View File

@ -424,7 +424,7 @@ RCT_EXPORT_MODULE()
_remaining = nil; _remaining = nil;
} }
NSArray *lines = [log componentsSeparatedByString:@"\n"]; NSArray<NSString *> *lines = [log componentsSeparatedByString:@"\n"];
if (lines.count == 1) { // no newlines if (lines.count == 1) { // no newlines
_remaining = log; _remaining = log;
return; return;

View File

@ -336,10 +336,11 @@ NSString *RCTProfileEnd(RCTBridge *bridge)
} }
} }
static NSMutableArray *RCTProfileGetThreadEvents(void) static NSMutableArray<NSArray *> *RCTProfileGetThreadEvents(void)
{ {
static NSString *const RCTProfileThreadEventsKey = @"RCTProfileThreadEventsKey"; static NSString *const RCTProfileThreadEventsKey = @"RCTProfileThreadEventsKey";
NSMutableArray *threadEvents = [NSThread currentThread].threadDictionary[RCTProfileThreadEventsKey]; NSMutableArray<NSArray *> *threadEvents =
[NSThread currentThread].threadDictionary[RCTProfileThreadEventsKey];
if (!threadEvents) { if (!threadEvents) {
threadEvents = [NSMutableArray new]; threadEvents = [NSMutableArray new];
[NSThread currentThread].threadDictionary[RCTProfileThreadEventsKey] = threadEvents; [NSThread currentThread].threadDictionary[RCTProfileThreadEventsKey] = threadEvents;
@ -377,7 +378,7 @@ void RCTProfileEndEvent(
return; return;
} }
NSMutableArray *events = RCTProfileGetThreadEvents(); NSMutableArray<NSArray *> *events = RCTProfileGetThreadEvents();
NSArray *event = events.lastObject; NSArray *event = events.lastObject;
[events removeLastObject]; [events removeLastObject];

View File

@ -27,7 +27,7 @@ typedef void (^RCTBubblingEventBlock)(NSDictionary *body);
- (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex; - (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex;
- (void)removeReactSubview:(id<RCTComponent>)subview; - (void)removeReactSubview:(id<RCTComponent>)subview;
- (NSArray *)reactSubviews; - (NSArray<id<RCTComponent>> *)reactSubviews;
- (id<RCTComponent>)reactSuperview; - (id<RCTComponent>)reactSuperview;
- (NSNumber *)reactTagAtPoint:(CGPoint)point; - (NSNumber *)reactTagAtPoint:(CGPoint)point;

View File

@ -100,7 +100,8 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
SEL selector = NSSelectorFromString([NSString stringWithFormat:@"propConfig%@_%@", shadowView ? @"Shadow" : @"", name]); SEL selector = NSSelectorFromString([NSString stringWithFormat:@"propConfig%@_%@", shadowView ? @"Shadow" : @"", name]);
Class managerClass = [_manager class]; Class managerClass = [_manager class];
if ([managerClass respondsToSelector:selector]) { if ([managerClass respondsToSelector:selector]) {
NSArray *typeAndKeyPath = ((NSArray *(*)(id, SEL))objc_msgSend)(managerClass, selector); NSArray<NSString *> *typeAndKeyPath =
((NSArray<NSString *> *(*)(id, SEL))objc_msgSend)(managerClass, selector);
type = NSSelectorFromString([typeAndKeyPath[0] stringByAppendingString:@":"]); type = NSSelectorFromString([typeAndKeyPath[0] stringByAppendingString:@":"]);
keyPath = typeAndKeyPath.count > 1 ? typeAndKeyPath[1] : nil; keyPath = typeAndKeyPath.count > 1 ? typeAndKeyPath[1] : nil;
} else { } else {
@ -125,7 +126,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
// Disect keypath // Disect keypath
NSString *key = name; NSString *key = name;
NSArray *parts = [keyPath componentsSeparatedByString:@"."]; NSArray<NSString *> *parts = [keyPath componentsSeparatedByString:@"."];
if (parts) { if (parts) {
key = parts.lastObject; key = parts.lastObject;
parts = [parts subarrayWithRange:(NSRange){0, parts.count - 1}]; parts = [parts subarrayWithRange:(NSRange){0, parts.count - 1}];
@ -312,9 +313,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
{ {
Class managerClass = [_manager class]; Class managerClass = [_manager class];
NSMutableArray *directEvents = [NSMutableArray new]; NSMutableArray<NSString *> *directEvents = [NSMutableArray new];
if (RCTClassOverridesInstanceMethod(managerClass, @selector(customDirectEventTypes))) { if (RCTClassOverridesInstanceMethod(managerClass, @selector(customDirectEventTypes))) {
NSArray *events = [_manager customDirectEventTypes]; NSArray<NSString *> *events = [_manager customDirectEventTypes];
if (RCT_DEBUG) { if (RCT_DEBUG) {
RCTAssert(!events || [events isKindOfClass:[NSArray class]], RCTAssert(!events || [events isKindOfClass:[NSArray class]],
@"customDirectEventTypes must return an array, but %@ returned %@", @"customDirectEventTypes must return an array, but %@ returned %@",
@ -325,9 +326,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
} }
} }
NSMutableArray *bubblingEvents = [NSMutableArray new]; NSMutableArray<NSString *> *bubblingEvents = [NSMutableArray new];
if (RCTClassOverridesInstanceMethod(managerClass, @selector(customBubblingEventTypes))) { if (RCTClassOverridesInstanceMethod(managerClass, @selector(customBubblingEventTypes))) {
NSArray *events = [_manager customBubblingEventTypes]; NSArray<NSString *> *events = [_manager customBubblingEventTypes];
if (RCT_DEBUG) { if (RCT_DEBUG) {
RCTAssert(!events || [events isKindOfClass:[NSArray class]], RCTAssert(!events || [events isKindOfClass:[NSArray class]],
@"customBubblingEventTypes must return an array, but %@ returned %@", @"customBubblingEventTypes must return an array, but %@ returned %@",
@ -349,7 +350,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
NSRange nameRange = [methodName rangeOfString:@"_"]; NSRange nameRange = [methodName rangeOfString:@"_"];
if (nameRange.length) { if (nameRange.length) {
NSString *name = [methodName substringFromIndex:nameRange.location + 1]; NSString *name = [methodName substringFromIndex:nameRange.location + 1];
NSString *type = ((NSArray *(*)(id, SEL))objc_msgSend)(managerClass, selector)[0]; NSString *type = ((NSArray<NSString *> *(*)(id, SEL))objc_msgSend)(managerClass, selector)[0];
if (RCT_DEBUG && propTypes[name] && ![propTypes[name] isEqualToString:type]) { if (RCT_DEBUG && propTypes[name] && ![propTypes[name] isEqualToString:type]) {
RCTLogError(@"Property '%@' of component '%@' redefined from '%@' " RCTLogError(@"Property '%@' of component '%@' redefined from '%@' "
"to '%@'", name, _name, propTypes[name], type); "to '%@'", name, _name, propTypes[name], type);

View File

@ -25,7 +25,7 @@ extern const CGFloat RCTMapZoomBoundBuffer;
@property (nonatomic, assign) CGFloat maxDelta; @property (nonatomic, assign) CGFloat maxDelta;
@property (nonatomic, assign) UIEdgeInsets legalLabelInsets; @property (nonatomic, assign) UIEdgeInsets legalLabelInsets;
@property (nonatomic, strong) NSTimer *regionChangeObserveTimer; @property (nonatomic, strong) NSTimer *regionChangeObserveTimer;
@property (nonatomic, strong) NSMutableArray *annotationIds; @property (nonatomic, copy) NSArray<NSString *> *annotationIds;
@property (nonatomic, copy) RCTBubblingEventBlock onChange; @property (nonatomic, copy) RCTBubblingEventBlock onChange;
@property (nonatomic, copy) RCTBubblingEventBlock onPress; @property (nonatomic, copy) RCTBubblingEventBlock onPress;

View File

@ -109,9 +109,9 @@ const CGFloat RCTMapZoomBoundBuffer = 0.01;
- (void)setAnnotations:(RCTPointAnnotationArray *)annotations - (void)setAnnotations:(RCTPointAnnotationArray *)annotations
{ {
NSMutableArray *newAnnotationIds = [NSMutableArray new]; NSMutableArray<NSString *> *newAnnotationIds = [NSMutableArray new];
NSMutableArray *annotationsToDelete = [NSMutableArray new]; NSMutableArray<RCTPointAnnotation *> *annotationsToDelete = [NSMutableArray new];
NSMutableArray *annotationsToAdd = [NSMutableArray new]; NSMutableArray<RCTPointAnnotation *> *annotationsToAdd = [NSMutableArray new];
for (RCTPointAnnotation *annotation in annotations) { for (RCTPointAnnotation *annotation in annotations) {
if (![annotation isKindOfClass:[RCTPointAnnotation class]]) { if (![annotation isKindOfClass:[RCTPointAnnotation class]]) {
@ -138,19 +138,19 @@ const CGFloat RCTMapZoomBoundBuffer = 0.01;
} }
if (annotationsToDelete.count) { if (annotationsToDelete.count) {
[self removeAnnotations:annotationsToDelete]; [self removeAnnotations:(NSArray<id<MKAnnotation>> *)annotationsToDelete];
} }
if (annotationsToAdd.count) { if (annotationsToAdd.count) {
[self addAnnotations:annotationsToAdd]; [self addAnnotations:(NSArray<id<MKAnnotation>> *)annotationsToAdd];
} }
NSMutableArray *newIds = [NSMutableArray new]; NSMutableArray<NSString *> *newIds = [NSMutableArray new];
for (RCTPointAnnotation *anno in self.annotations) { for (RCTPointAnnotation *annotation in self.annotations) {
if ([anno isKindOfClass:[MKUserLocation class]]) { if ([annotation isKindOfClass:[MKUserLocation class]]) {
continue; continue;
} }
[newIds addObject:anno.identifier]; [newIds addObject:annotation.identifier];
} }
self.annotationIds = newIds; self.annotationIds = newIds;
} }

View File

@ -51,18 +51,18 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:coder)
} }
} }
- (NSArray *)reactSubviews - (NSArray<UIView<RCTComponent> *> *)reactSubviews
{ {
return [NSArray arrayWithObjects:_modalViewController.view, nil]; return _modalViewController.view ? @[_modalViewController.view] : @[];
} }
- (void)insertReactSubview:(UIView *)subview atIndex:(__unused NSInteger)atIndex - (void)insertReactSubview:(UIView<RCTComponent> *)subview atIndex:(__unused NSInteger)atIndex
{ {
[subview addGestureRecognizer:_touchHandler]; [subview addGestureRecognizer:_touchHandler];
_modalViewController.view = subview; _modalViewController.view = subview;
} }
- (void)removeReactSubview:(UIView *)subview - (void)removeReactSubview:(UIView<RCTComponent> *)subview
{ {
RCTAssert(subview == _modalViewController.view, @"Cannot remove view other than modal view"); RCTAssert(subview == _modalViewController.view, @"Cannot remove view other than modal view");
_modalViewController.view = nil; _modalViewController.view = nil;

View File

@ -200,8 +200,8 @@ NSInteger kNeverProgressed = -10000;
// Previous views are only mainted in order to detect incorrect // Previous views are only mainted in order to detect incorrect
// addition/removal of views below the `requestedTopOfStack` // addition/removal of views below the `requestedTopOfStack`
@property (nonatomic, copy, readwrite) NSArray *previousViews; @property (nonatomic, copy, readwrite) NSArray<RCTNavItem *> *previousViews;
@property (nonatomic, readwrite, strong) NSMutableArray *currentViews; @property (nonatomic, readwrite, strong) NSMutableArray<RCTNavItem *> *currentViews;
@property (nonatomic, readwrite, strong) RCTNavigationController *navigationController; @property (nonatomic, readwrite, strong) RCTNavigationController *navigationController;
/** /**
* Display link is used to get high frequency sample rate during * Display link is used to get high frequency sample rate during
@ -400,7 +400,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
* `requestedTopOfStack` changes, there had better be enough subviews present * `requestedTopOfStack` changes, there had better be enough subviews present
* to satisfy the push/pop. * to satisfy the push/pop.
*/ */
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex - (void)insertReactSubview:(RCTNavItem *)view atIndex:(NSInteger)atIndex
{ {
RCTAssert([view isKindOfClass:[RCTNavItem class]], @"RCTNavigator only accepts RCTNavItem subviews"); RCTAssert([view isKindOfClass:[RCTNavItem class]], @"RCTNavigator only accepts RCTNavItem subviews");
RCTAssert( RCTAssert(
@ -410,7 +410,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
[_currentViews insertObject:view atIndex:atIndex]; [_currentViews insertObject:view atIndex:atIndex];
} }
- (NSArray *)reactSubviews - (NSArray<RCTNavItem *> *)reactSubviews
{ {
return _currentViews; return _currentViews;
} }
@ -422,7 +422,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
_navigationController.view.frame = self.bounds; _navigationController.view.frame = self.bounds;
} }
- (void)removeReactSubview:(UIView *)subview - (void)removeReactSubview:(RCTNavItem *)subview
{ {
if (_currentViews.count <= 0 || subview == _currentViews[0]) { if (_currentViews.count <= 0 || subview == _currentViews[0]) {
RCTLogError(@"Attempting to remove invalid RCT subview of RCTNavigator"); RCTLogError(@"Attempting to remove invalid RCT subview of RCTNavigator");

View File

@ -9,6 +9,12 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import "UIView+React.h"
@interface RCTPicker : UIPickerView @interface RCTPicker : UIPickerView
@property (nonatomic, copy) NSArray<NSDictionary *> *items;
@property (nonatomic, assign) NSInteger selectedIndex;
@property (nonatomic, copy) RCTBubblingEventBlock onChange;
@end @end

View File

@ -10,14 +10,8 @@
#import "RCTPicker.h" #import "RCTPicker.h"
#import "RCTUtils.h" #import "RCTUtils.h"
#import "UIView+React.h"
@interface RCTPicker() <UIPickerViewDataSource, UIPickerViewDelegate> @interface RCTPicker() <UIPickerViewDataSource, UIPickerViewDelegate>
@property (nonatomic, copy) NSArray *items;
@property (nonatomic, assign) NSInteger selectedIndex;
@property (nonatomic, copy) RCTBubblingEventBlock onChange;
@end @end
@implementation RCTPicker @implementation RCTPicker
@ -33,7 +27,7 @@
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
- (void)setItems:(NSArray *)items - (void)setItems:(NSArray<NSDictionary *> *)items
{ {
_items = [items copy]; _items = [items copy];
[self setNeedsLayout]; [self setNeedsLayout];

View File

@ -117,7 +117,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (RCTScrollEvent *)coalesceWithEvent:(RCTScrollEvent *)newEvent - (RCTScrollEvent *)coalesceWithEvent:(RCTScrollEvent *)newEvent
{ {
NSArray *updatedChildFrames = [_userData[@"updatedChildFrames"] arrayByAddingObjectsFromArray:newEvent->_userData[@"updatedChildFrames"]]; NSArray<NSDictionary *> *updatedChildFrames = [_userData[@"updatedChildFrames"] arrayByAddingObjectsFromArray:newEvent->_userData[@"updatedChildFrames"]];
if (updatedChildFrames) { if (updatedChildFrames) {
NSMutableDictionary *userData = [newEvent->_userData mutableCopy]; NSMutableDictionary *userData = [newEvent->_userData mutableCopy];
@ -360,7 +360,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
RCTCustomScrollView *_scrollView; RCTCustomScrollView *_scrollView;
UIView *_contentView; UIView *_contentView;
NSTimeInterval _lastScrollDispatchTime; NSTimeInterval _lastScrollDispatchTime;
NSMutableArray *_cachedChildFrames; NSMutableArray<NSValue *> *_cachedChildFrames;
BOOL _allowNextScrollNoMatterWhat; BOOL _allowNextScrollNoMatterWhat;
CGRect _lastClippedToRect; CGRect _lastClippedToRect;
} }
@ -412,7 +412,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
[subview removeFromSuperview]; [subview removeFromSuperview];
} }
- (NSArray *)reactSubviews - (NSArray<UIView<RCTComponent> *> *)reactSubviews
{ {
return _contentView ? @[_contentView] : @[]; return _contentView ? @[_contentView] : @[];
} }
@ -564,7 +564,7 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove)
(_scrollEventThrottle > 0 && _scrollEventThrottle < (now - _lastScrollDispatchTime))) { (_scrollEventThrottle > 0 && _scrollEventThrottle < (now - _lastScrollDispatchTime))) {
// Calculate changed frames // Calculate changed frames
NSArray *childFrames = [self calculateChildFramesData]; NSArray<NSDictionary *> *childFrames = [self calculateChildFramesData];
// Dispatch event // Dispatch event
[_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove [_eventDispatcher sendScrollEventWithType:RCTScrollEventTypeMove
@ -579,9 +579,9 @@ RCT_SCROLL_EVENT_HANDLER(scrollViewDidZoom, RCTScrollEventTypeMove)
RCT_FORWARD_SCROLL_EVENT(scrollViewDidScroll:scrollView); RCT_FORWARD_SCROLL_EVENT(scrollViewDidScroll:scrollView);
} }
- (NSArray *)calculateChildFramesData - (NSArray<NSDictionary *> *)calculateChildFramesData
{ {
NSMutableArray *updatedChildFrames = [NSMutableArray new]; NSMutableArray<NSDictionary *> *updatedChildFrames = [NSMutableArray new];
[[_contentView reactSubviews] enumerateObjectsUsingBlock: [[_contentView reactSubviews] enumerateObjectsUsingBlock:
^(UIView *subview, NSUInteger idx, __unused BOOL *stop) { ^(UIView *subview, NSUInteger idx, __unused BOOL *stop) {

View File

@ -16,7 +16,7 @@
@interface RCTScrollView (Private) @interface RCTScrollView (Private)
- (NSArray *)calculateChildFramesData; - (NSArray<NSDictionary *> *)calculateChildFramesData;
@end @end
@ -83,13 +83,13 @@ RCT_EXPORT_METHOD(getContentSize:(nonnull NSNumber *)reactTag
{ {
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
UIView *view = viewRegistry[reactTag]; RCTScrollView *view = viewRegistry[reactTag];
if (!view) { if (!view || ![view isKindOfClass:[RCTScrollView class]]) {
RCTLogError(@"Cannot find view with tag #%@", reactTag); RCTLogError(@"Cannot find RCTScrollView with tag #%@", reactTag);
return; return;
} }
CGSize size = ((RCTScrollView *)view).scrollView.contentSize; CGSize size = view.scrollView.contentSize;
callback(@[@{ callback(@[@{
@"width" : @(size.width), @"width" : @(size.width),
@"height" : @(size.height) @"height" : @(size.height)
@ -102,20 +102,20 @@ RCT_EXPORT_METHOD(calculateChildFrames:(nonnull NSNumber *)reactTag
{ {
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) { [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
UIView *view = viewRegistry[reactTag]; RCTScrollView *view = viewRegistry[reactTag];
if (!view) { if (!view || ![view isKindOfClass:[RCTScrollView class]]) {
RCTLogError(@"Cannot find view with tag #%@", reactTag); RCTLogError(@"Cannot find RCTScrollView with tag #%@", reactTag);
return; return;
} }
NSArray *childFrames = [((RCTScrollView *)view) calculateChildFramesData]; NSArray<NSDictionary *> *childFrames = [view calculateChildFramesData];
if (childFrames) { if (childFrames) {
callback(@[childFrames]); callback(@[childFrames]);
} }
}]; }];
} }
- (NSArray *)customDirectEventTypes - (NSArray<NSString *> *)customDirectEventTypes
{ {
return @[ return @[
@"scrollBeginDrag", @"scrollBeginDrag",

View File

@ -13,7 +13,7 @@
@interface RCTSegmentedControl : UISegmentedControl @interface RCTSegmentedControl : UISegmentedControl
@property (nonatomic, copy) NSArray *values; @property (nonatomic, copy) NSArray<NSString *> *values;
@property (nonatomic, assign) NSInteger selectedIndex; @property (nonatomic, assign) NSInteger selectedIndex;
@property (nonatomic, copy) RCTBubblingEventBlock onChange; @property (nonatomic, copy) RCTBubblingEventBlock onChange;

View File

@ -25,7 +25,7 @@
return self; return self;
} }
- (void)setValues:(NSArray *)values - (void)setValues:(NSArray<NSString *> *)values
{ {
_values = [values copy]; _values = [values copy];
[self removeAllSegments]; [self removeAllSegments];

View File

@ -35,6 +35,9 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *viewRegistry);
*/ */
@interface RCTShadowView : NSObject <RCTComponent> @interface RCTShadowView : NSObject <RCTComponent>
- (NSArray<RCTShadowView *> *)reactSubviews;
- (RCTShadowView *)reactSuperview;
@property (nonatomic, weak, readonly) RCTShadowView *superview; @property (nonatomic, weak, readonly) RCTShadowView *superview;
@property (nonatomic, assign, readonly) css_node_t *cssNode; @property (nonatomic, assign, readonly) css_node_t *cssNode;
@property (nonatomic, copy) NSString *viewName; @property (nonatomic, copy) NSString *viewName;
@ -120,27 +123,27 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *viewRegistry);
* The applierBlocks set contains RCTApplierBlock functions that must be applied * The applierBlocks set contains RCTApplierBlock functions that must be applied
* on the main thread in order to update the view. * on the main thread in order to update the view.
*/ */
- (void)collectUpdatedProperties:(NSMutableSet *)applierBlocks - (void)collectUpdatedProperties:(NSMutableSet<RCTApplierBlock> *)applierBlocks
parentProperties:(NSDictionary *)parentProperties; parentProperties:(NSDictionary *)parentProperties;
/** /**
* Process the updated properties and apply them to view. Shadow view classes * Process the updated properties and apply them to view. Shadow view classes
* that add additional propagating properties should override this method. * that add additional propagating properties should override this method.
*/ */
- (NSDictionary *)processUpdatedProperties:(NSMutableSet *)applierBlocks - (NSDictionary *)processUpdatedProperties:(NSMutableSet<RCTApplierBlock> *)applierBlocks
parentProperties:(NSDictionary *)parentProperties NS_REQUIRES_SUPER; parentProperties:(NSDictionary *)parentProperties NS_REQUIRES_SUPER;
/** /**
* Calculate all views whose frame needs updating after layout has been calculated. * Calculate all views whose frame needs updating after layout has been calculated.
* The viewsWithNewFrame set contains the reactTags of the views that need updating. * The viewsWithNewFrame set contains the reactTags of the views that need updating.
*/ */
- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame; - (void)collectRootUpdatedFrames:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame;
/** /**
* Recursively apply layout to children. * Recursively apply layout to children.
*/ */
- (void)applyLayoutNode:(css_node_t *)node - (void)applyLayoutNode:(css_node_t *)node
viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame viewsWithNewFrame:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame
absolutePosition:(CGPoint)absolutePosition NS_REQUIRES_SUPER; absolutePosition:(CGPoint)absolutePosition NS_REQUIRES_SUPER;
/** /**

View File

@ -36,7 +36,7 @@ typedef NS_ENUM(unsigned int, meta_prop_t) {
RCTUpdateLifecycle _propagationLifecycle; RCTUpdateLifecycle _propagationLifecycle;
RCTUpdateLifecycle _textLifecycle; RCTUpdateLifecycle _textLifecycle;
NSDictionary *_lastParentProperties; NSDictionary *_lastParentProperties;
NSMutableArray *_reactSubviews; NSMutableArray<RCTShadowView *> *_reactSubviews;
BOOL _recomputePadding; BOOL _recomputePadding;
BOOL _recomputeMargin; BOOL _recomputeMargin;
BOOL _recomputeBorder; BOOL _recomputeBorder;
@ -123,7 +123,7 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
// You'll notice that this is the same width we calculated for the parent view because we've taken its position into account. // You'll notice that this is the same width we calculated for the parent view because we've taken its position into account.
- (void)applyLayoutNode:(css_node_t *)node - (void)applyLayoutNode:(css_node_t *)node
viewsWithNewFrame:(NSMutableSet *)viewsWithNewFrame viewsWithNewFrame:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame
absolutePosition:(CGPoint)absolutePosition absolutePosition:(CGPoint)absolutePosition
{ {
if (!node->layout.should_update) { if (!node->layout.should_update) {
@ -171,7 +171,7 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
} }
} }
- (NSDictionary *)processUpdatedProperties:(NSMutableSet *)applierBlocks - (NSDictionary *)processUpdatedProperties:(NSMutableSet<RCTApplierBlock> *)applierBlocks
parentProperties:(NSDictionary *)parentProperties parentProperties:(NSDictionary *)parentProperties
{ {
// TODO: we always refresh all propagated properties when propagation is // TODO: we always refresh all propagated properties when propagation is
@ -201,7 +201,7 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
return parentProperties; return parentProperties;
} }
- (void)collectUpdatedProperties:(NSMutableSet *)applierBlocks - (void)collectUpdatedProperties:(NSMutableSet<RCTApplierBlock> *)applierBlocks
parentProperties:(NSDictionary *)parentProperties parentProperties:(NSDictionary *)parentProperties
{ {
if (_propagationLifecycle == RCTUpdateLifecycleComputed && [parentProperties isEqualToDictionary:_lastParentProperties]) { if (_propagationLifecycle == RCTUpdateLifecycleComputed && [parentProperties isEqualToDictionary:_lastParentProperties]) {
@ -234,7 +234,7 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
} }
} }
- (void)collectRootUpdatedFrames:(NSMutableSet *)viewsWithNewFrame - (void)collectRootUpdatedFrames:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame
{ {
RCTAssert(RCTIsReactRootView(self.reactTag), RCTAssert(RCTIsReactRootView(self.reactTag),
@"The method has been called on a view with react tag %@, which is not a root view", self.reactTag); @"The method has been called on a view with react tag %@, which is not a root view", self.reactTag);
@ -367,7 +367,7 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
_cssNode->children_count = (int)_reactSubviews.count; _cssNode->children_count = (int)_reactSubviews.count;
} }
- (NSArray *)reactSubviews - (NSArray<RCTShadowView *> *)reactSubviews
{ {
return _reactSubviews; return _reactSubviews;
} }

View File

@ -26,7 +26,7 @@
{ {
BOOL _tabsChanged; BOOL _tabsChanged;
UITabBarController *_tabController; UITabBarController *_tabController;
NSMutableArray *_tabViews; NSMutableArray<RCTTabBarItem *> *_tabViews;
} }
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
@ -52,12 +52,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
_tabController.delegate = nil; _tabController.delegate = nil;
} }
- (NSArray *)reactSubviews - (NSArray<RCTTabBarItem *> *)reactSubviews
{ {
return _tabViews; return _tabViews;
} }
- (void)insertReactSubview:(UIView *)view atIndex:(NSInteger)atIndex - (void)insertReactSubview:(RCTTabBarItem *)view atIndex:(NSInteger)atIndex
{ {
if (![view isKindOfClass:[RCTTabBarItem class]]) { if (![view isKindOfClass:[RCTTabBarItem class]]) {
RCTLogError(@"subview should be of type RCTTabBarItem"); RCTLogError(@"subview should be of type RCTTabBarItem");
@ -67,7 +67,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
_tabsChanged = YES; _tabsChanged = YES;
} }
- (void)removeReactSubview:(UIView *)subview - (void)removeReactSubview:(RCTTabBarItem *)subview
{ {
if (_tabViews.count == 0) { if (_tabViews.count == 0) {
RCTLogError(@"should have at least one view to remove a subview"); RCTLogError(@"should have at least one view to remove a subview");
@ -92,7 +92,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
if (_tabsChanged) { if (_tabsChanged) {
NSMutableArray *viewControllers = [NSMutableArray array]; NSMutableArray<UIViewController *> *viewControllers = [NSMutableArray array];
for (RCTTabBarItem *tab in [self reactSubviews]) { for (RCTTabBarItem *tab in [self reactSubviews]) {
UIViewController *controller = tab.reactViewController; UIViewController *controller = tab.reactViewController;
if (!controller) { if (!controller) {
@ -105,7 +105,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
_tabsChanged = NO; _tabsChanged = NO;
} }
[[self reactSubviews] enumerateObjectsUsingBlock: [_tabViews enumerateObjectsUsingBlock:
^(RCTTabBarItem *tab, NSUInteger index, __unused BOOL *stop) { ^(RCTTabBarItem *tab, NSUInteger index, __unused BOOL *stop) {
UIViewController *controller = _tabController.viewControllers[index]; UIViewController *controller = _tabController.viewControllers[index];
controller.tabBarItem = tab.barItem; controller.tabBarItem = tab.barItem;
@ -148,7 +148,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder)
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{ {
NSUInteger index = [tabBarController.viewControllers indexOfObject:viewController]; NSUInteger index = [tabBarController.viewControllers indexOfObject:viewController];
RCTTabBarItem *tab = [self reactSubviews][index]; RCTTabBarItem *tab = _tabViews[index];
if (tab.onPress) tab.onPress(nil); if (tab.onPress) tab.onPress(nil);
return NO; return NO;
} }

View File

@ -92,7 +92,7 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view)
@implementation RCTView @implementation RCTView
{ {
NSMutableArray *_reactSubviews; NSMutableArray<UIView<RCTComponent> *> *_reactSubviews;
UIColor *_backgroundColor; UIColor *_backgroundColor;
} }
@ -413,7 +413,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused)
[subview removeFromSuperview]; [subview removeFromSuperview];
} }
- (NSArray *)reactSubviews - (NSArray<UIView<RCTComponent> *> *)reactSubviews
{ {
// The _reactSubviews array is only used when we have hidden // The _reactSubviews array is only used when we have hidden
// offscreen views. If _reactSubviews is nil, we can assume // offscreen views. If _reactSubviews is nil, we can assume

View File

@ -70,7 +70,7 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *v
* Note that this method is not inherited when you subclass a view module, and * Note that this method is not inherited when you subclass a view module, and
* you should not call [super customBubblingEventTypes] when overriding it. * you should not call [super customBubblingEventTypes] when overriding it.
*/ */
- (NSArray *)customBubblingEventTypes; - (NSArray<NSString *> *)customBubblingEventTypes;
/** /**
* DEPRECATED: declare properties of type RCTDirectEventBlock instead * DEPRECATED: declare properties of type RCTDirectEventBlock instead
@ -83,7 +83,7 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *v
* Note that this method is not inherited when you subclass a view module, and * Note that this method is not inherited when you subclass a view module, and
* you should not call [super customDirectEventTypes] when overriding it. * you should not call [super customDirectEventTypes] when overriding it.
*/ */
- (NSArray *)customDirectEventTypes; - (NSArray<NSString *> *)customDirectEventTypes;
/** /**
* Called to notify manager that layout has finished, in case any calculated * Called to notify manager that layout has finished, in case any calculated
@ -103,13 +103,13 @@ typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *v
* This handles the simple case, where JS and native property names match. * This handles the simple case, where JS and native property names match.
*/ */
#define RCT_EXPORT_VIEW_PROPERTY(name, type) \ #define RCT_EXPORT_VIEW_PROPERTY(name, type) \
+ (NSArray *)propConfig_##name { return @[@#type]; } + (NSArray<NSString *> *)propConfig_##name { return @[@#type]; }
/** /**
* This macro maps a named property to an arbitrary key path in the view. * This macro maps a named property to an arbitrary key path in the view.
*/ */
#define RCT_REMAP_VIEW_PROPERTY(name, keyPath, type) \ #define RCT_REMAP_VIEW_PROPERTY(name, keyPath, type) \
+ (NSArray *)propConfig_##name { return @[@#type, @#keyPath]; } + (NSArray<NSString *> *)propConfig_##name { return @[@#type, @#keyPath]; }
/** /**
* This macro can be used when you need to provide custom logic for setting * This macro can be used when you need to provide custom logic for setting
@ -124,6 +124,6 @@ RCT_REMAP_VIEW_PROPERTY(name, __custom__, type) \
* This macro is used to map properties to the shadow view, instead of the view. * This macro is used to map properties to the shadow view, instead of the view.
*/ */
#define RCT_EXPORT_SHADOW_PROPERTY(name, type) \ #define RCT_EXPORT_SHADOW_PROPERTY(name, type) \
+ (NSArray *)propConfigShadow_##name { return @[@#type]; } + (NSArray<NSString *> *)propConfigShadow_##name { return @[@#type]; }
@end @end

View File

@ -69,7 +69,7 @@ RCT_EXPORT_MODULE()
return [RCTShadowView new]; return [RCTShadowView new];
} }
- (NSArray *)customBubblingEventTypes - (NSArray<NSString *> *)customBubblingEventTypes
{ {
return @[ return @[
@ -90,7 +90,7 @@ RCT_EXPORT_MODULE()
]; ];
} }
- (NSArray *)customDirectEventTypes - (NSArray<NSString *> *)customDirectEventTypes
{ {
return @[]; return @[];
} }

View File

@ -15,6 +15,9 @@
@interface UIView (React) <RCTComponent> @interface UIView (React) <RCTComponent>
- (NSArray<UIView<RCTComponent> *> *)reactSubviews;
- (UIView<RCTComponent> *)reactSuperview;
/** /**
* Used by the UIIManager to set the view frame. * Used by the UIIManager to set the view frame.
* May be overriden to disable animation, etc. * May be overriden to disable animation, etc.

View File

@ -51,12 +51,12 @@
[subview removeFromSuperview]; [subview removeFromSuperview];
} }
- (NSArray *)reactSubviews - (NSArray<UIView<RCTComponent> *> *)reactSubviews
{ {
return self.subviews; return self.subviews;
} }
- (UIView *)reactSuperview - (UIView<RCTComponent> *)reactSuperview
{ {
return self.superview; return self.superview;
} }