257 lines
10 KiB
Objective-C
257 lines
10 KiB
Objective-C
/**
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
#import <QuartzCore/QuartzCore.h>
|
|
#import <UIKit/UIKit.h>
|
|
|
|
#import "Layout.h"
|
|
#import "RCTAnimationType.h"
|
|
#import "RCTLog.h"
|
|
#import "RCTPointerEvents.h"
|
|
|
|
/**
|
|
* This class provides a collection of conversion functions for mapping
|
|
* JSON objects to native types and classes. These are useful when writing
|
|
* custom RCTViewManager setter methods.
|
|
*/
|
|
@interface RCTConvert : NSObject
|
|
|
|
+ (BOOL)BOOL:(id)json;
|
|
+ (double)double:(id)json;
|
|
+ (float)float:(id)json;
|
|
+ (int)int:(id)json;
|
|
|
|
+ (int64_t)int64_t:(id)json;
|
|
+ (uint64_t)uint64_t:(id)json;
|
|
|
|
+ (NSInteger)NSInteger:(id)json;
|
|
+ (NSUInteger)NSUInteger:(id)json;
|
|
|
|
+ (NSArray *)NSArray:(id)json;
|
|
+ (NSDictionary *)NSDictionary:(id)json;
|
|
+ (NSString *)NSString:(id)json;
|
|
+ (NSNumber *)NSNumber:(id)json;
|
|
|
|
+ (NSURL *)NSURL:(id)json;
|
|
+ (NSURLRequest *)NSURLRequest:(id)json;
|
|
|
|
+ (NSDate *)NSDate:(id)json;
|
|
+ (NSTimeZone *)NSTimeZone:(id)json;
|
|
+ (NSTimeInterval)NSTimeInterval:(id)json;
|
|
|
|
+ (NSTextAlignment)NSTextAlignment:(id)json;
|
|
+ (NSWritingDirection)NSWritingDirection:(id)json;
|
|
+ (UITextAutocapitalizationType)UITextAutocapitalizationType:(id)json;
|
|
+ (UITextFieldViewMode)UITextFieldViewMode:(id)json;
|
|
+ (UIScrollViewKeyboardDismissMode)UIScrollViewKeyboardDismissMode:(id)json;
|
|
+ (UIKeyboardType)UIKeyboardType:(id)json;
|
|
|
|
+ (UIViewContentMode)UIViewContentMode:(id)json;
|
|
+ (UIBarStyle)UIBarStyle:(id)json;
|
|
|
|
+ (CGFloat)CGFloat:(id)json;
|
|
+ (CGPoint)CGPoint:(id)json;
|
|
+ (CGSize)CGSize:(id)json;
|
|
+ (CGRect)CGRect:(id)json;
|
|
+ (UIEdgeInsets)UIEdgeInsets:(id)json;
|
|
|
|
+ (CGLineCap)CGLineCap:(id)json;
|
|
+ (CGLineJoin)CGLineJoin:(id)json;
|
|
|
|
+ (CATransform3D)CATransform3D:(id)json;
|
|
+ (CGAffineTransform)CGAffineTransform:(id)json;
|
|
|
|
+ (UIColor *)UIColor:(id)json;
|
|
+ (CGColorRef)CGColor:(id)json;
|
|
|
|
+ (UIImage *)UIImage:(id)json;
|
|
+ (CGImageRef)CGImage:(id)json;
|
|
|
|
+ (UIFont *)UIFont:(UIFont *)font withSize:(id)json;
|
|
+ (UIFont *)UIFont:(UIFont *)font withWeight:(id)json;
|
|
+ (UIFont *)UIFont:(UIFont *)font withStyle:(id)json;
|
|
+ (UIFont *)UIFont:(UIFont *)font withFamily:(id)json;
|
|
+ (UIFont *)UIFont:(UIFont *)font withFamily:(id)family
|
|
size:(id)size weight:(id)weight style:(id)style;
|
|
|
|
+ (NSArray *)NSStringArray:(id)json;
|
|
+ (NSArray *)NSDictionaryArray:(id)json;
|
|
+ (NSArray *)NSURLArray:(id)json;
|
|
+ (NSArray *)NSNumberArray:(id)json;
|
|
+ (NSArray *)UIColorArray:(id)json;
|
|
+ (NSArray *)CGColorArray:(id)json;
|
|
|
|
+ (BOOL)css_overflow:(id)json;
|
|
+ (css_flex_direction_t)css_flex_direction_t:(id)json;
|
|
+ (css_justify_t)css_justify_t:(id)json;
|
|
+ (css_align_t)css_align_t:(id)json;
|
|
+ (css_position_type_t)css_position_type_t:(id)json;
|
|
+ (css_wrap_type_t)css_wrap_type_t:(id)json;
|
|
|
|
+ (RCTPointerEvents)RCTPointerEvents:(id)json;
|
|
+ (RCTAnimationType)RCTAnimationType:(id)json;
|
|
|
|
@end
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* This function will attempt to set a property using a json value by first
|
|
* inferring the correct type from all available information, and then
|
|
* applying an appropriate conversion method. If the property does not
|
|
* exist, or the type cannot be inferred, the function will return NO.
|
|
*/
|
|
BOOL RCTSetProperty(id target, NSString *keyPath, SEL type, id json);
|
|
|
|
/**
|
|
* This function attempts to copy a property from the source object to the
|
|
* destination object using KVC. If the property does not exist, or cannot
|
|
* be set, it will do nothing and return NO.
|
|
*/
|
|
BOOL RCTCopyProperty(id target, id source, NSString *keyPath);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* This macro is used for creating converter functions with arbitrary logic.
|
|
*/
|
|
#define RCT_CONVERTER_CUSTOM(type, name, code) \
|
|
+ (type)name:(id)json \
|
|
{ \
|
|
if (json == [NSNull null]) { \
|
|
json = nil; \
|
|
} \
|
|
@try { \
|
|
return code; \
|
|
} \
|
|
@catch (__unused NSException *e) { \
|
|
RCTLogError(@"JSON value '%@' of type '%@' cannot be converted to '%s'", \
|
|
json, [json class], #type); \
|
|
json = nil; \
|
|
return code; \
|
|
} \
|
|
}
|
|
|
|
/**
|
|
* This macro is used for creating simple converter functions that just call
|
|
* the specified getter method on the json value.
|
|
*/
|
|
#define RCT_CONVERTER(type, name, getter) \
|
|
RCT_CONVERTER_CUSTOM(type, name, [json getter])
|
|
|
|
/**
|
|
* This macro is similar to RCT_CONVERTER, but specifically geared towards
|
|
* numeric types. It will handle string input correctly, and provides more
|
|
* detailed error reporting if a wrong value is passed in.
|
|
*/
|
|
#define RCT_NUMBER_CONVERTER(type, getter) \
|
|
RCT_CONVERTER_CUSTOM(type, type, [[self NSNumber:json] getter])
|
|
|
|
/**
|
|
* This macro is used for creating converters for enum types.
|
|
*/
|
|
#define RCT_ENUM_CONVERTER(type, values, default, getter) \
|
|
+ (type)type:(id)json \
|
|
{ \
|
|
static NSDictionary *mapping; \
|
|
static dispatch_once_t onceToken; \
|
|
dispatch_once(&onceToken, ^{ \
|
|
mapping = values; \
|
|
}); \
|
|
if (!json || json == [NSNull null]) { \
|
|
return default; \
|
|
} \
|
|
if ([json isKindOfClass:[NSNumber class]]) { \
|
|
if ([[mapping allValues] containsObject:json] || [json getter] == default) { \
|
|
return [json getter]; \
|
|
} \
|
|
RCTLogError(@"Invalid %s '%@'. should be one of: %@", #type, json, [mapping allValues]); \
|
|
return default; \
|
|
} \
|
|
if (![json isKindOfClass:[NSString class]]) { \
|
|
RCTLogError(@"Expected NSNumber or NSString for %s, received %@: %@", #type, [json class], json); \
|
|
} \
|
|
id value = mapping[json]; \
|
|
if(!value && [json description].length > 0) { \
|
|
RCTLogError(@"Invalid %s '%@'. should be one of: %@", #type, json, [mapping allKeys]); \
|
|
} \
|
|
return value ? [value getter] : default; \
|
|
}
|
|
|
|
/**
|
|
* This macro is used for creating converter functions for structs that consist
|
|
* of a number of CGFloat properties, such as CGPoint, CGRect, etc.
|
|
*/
|
|
#define RCT_CGSTRUCT_CONVERTER(type, values, _aliases) \
|
|
+ (type)type:(id)json \
|
|
{ \
|
|
@try { \
|
|
static NSArray *fields; \
|
|
static NSUInteger count; \
|
|
static dispatch_once_t onceToken; \
|
|
dispatch_once(&onceToken, ^{ \
|
|
fields = values; \
|
|
count = [fields count]; \
|
|
}); \
|
|
type result; \
|
|
if ([json isKindOfClass:[NSArray class]]) { \
|
|
if ([json count] != count) { \
|
|
RCTLogError(@"Expected array with count %zd, but count is %zd: %@", count, [json count], json); \
|
|
} else { \
|
|
for (NSUInteger i = 0; i < count; i++) { \
|
|
((CGFloat *)&result)[i] = [self CGFloat:json[i]]; \
|
|
} \
|
|
} \
|
|
} else if ([json isKindOfClass:[NSDictionary class]]) { \
|
|
NSDictionary *aliases = _aliases; \
|
|
if (aliases.count) { \
|
|
json = [json mutableCopy]; \
|
|
for (NSString *alias in aliases) { \
|
|
NSString *key = aliases[alias]; \
|
|
NSNumber *number = json[key]; \
|
|
if (number) { \
|
|
((NSMutableDictionary *)json)[key] = number; \
|
|
} \
|
|
} \
|
|
} \
|
|
for (NSUInteger i = 0; i < count; i++) { \
|
|
((CGFloat *)&result)[i] = [self CGFloat:json[fields[i]]]; \
|
|
} \
|
|
} else if (json && json != [NSNull null]) { \
|
|
RCTLogError(@"Expected NSArray or NSDictionary for %s, received %@: %@", #type, [json class], json); \
|
|
} \
|
|
return result; \
|
|
} \
|
|
@catch (__unused NSException *e) { \
|
|
RCTLogError(@"JSON value '%@' cannot be converted to '%s'", json, #type); \
|
|
type result; \
|
|
return result; \
|
|
} \
|
|
}
|
|
|
|
/**
|
|
* This macro is used for creating converter functions for typed arrays.
|
|
*/
|
|
#define RCT_ARRAY_CONVERTER(type) \
|
|
+ (NSArray *)type##Array:(id)json \
|
|
{ \
|
|
NSMutableArray *values = [[NSMutableArray alloc] init]; \
|
|
for (id jsonValue in [self NSArray:json]) { \
|
|
id value = [self type:jsonValue]; \
|
|
if (value) { \
|
|
[values addObject:value]; \
|
|
} \
|
|
} \
|
|
return values; \
|
|
}
|