Skip to content

Commit

Permalink
feat(iOS): Obj-C convenience accessors on CAPPluginCall (#4309)
Browse files Browse the repository at this point in the history
  • Loading branch information
ikeith authored Mar 9, 2021
1 parent ed8ec45 commit e3657d7
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 29 deletions.
4 changes: 4 additions & 0 deletions ios/Capacitor/Capacitor.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
623D691D254C7462002D01D1 /* CAPInstanceConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 623D691B254C7462002D01D1 /* CAPInstanceConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
623D691E254C7462002D01D1 /* CAPInstanceConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 623D691C254C7462002D01D1 /* CAPInstanceConfiguration.m */; };
625AF1ED258963C700869675 /* WebViewAssetHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 625AF1EC258963C700869675 /* WebViewAssetHandler.swift */; };
6263686025F6EC0100576C1C /* PluginCallAccessorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6263685F25F6EC0100576C1C /* PluginCallAccessorTests.m */; };
62959B162524DA7800A3D7F1 /* CAPPluginCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959AE22524DA7700A3D7F1 /* CAPPluginCall.h */; settings = {ATTRIBUTES = (Public, ); }; };
62959B172524DA7800A3D7F1 /* JSExport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62959AE32524DA7700A3D7F1 /* JSExport.swift */; };
62959B192524DA7800A3D7F1 /* CAPBridgedPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 62959AE52524DA7700A3D7F1 /* CAPBridgedPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -153,6 +154,7 @@
623D691B254C7462002D01D1 /* CAPInstanceConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CAPInstanceConfiguration.h; sourceTree = "<group>"; };
623D691C254C7462002D01D1 /* CAPInstanceConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CAPInstanceConfiguration.m; sourceTree = "<group>"; };
625AF1EC258963C700869675 /* WebViewAssetHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebViewAssetHandler.swift; sourceTree = "<group>"; };
6263685F25F6EC0100576C1C /* PluginCallAccessorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PluginCallAccessorTests.m; sourceTree = "<group>"; };
62959AE22524DA7700A3D7F1 /* CAPPluginCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPPluginCall.h; sourceTree = "<group>"; };
62959AE32524DA7700A3D7F1 /* JSExport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSExport.swift; sourceTree = "<group>"; };
62959AE52524DA7700A3D7F1 /* CAPBridgedPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPBridgedPlugin.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -275,6 +277,7 @@
62FABD2A25AE6182007B3814 /* BridgedTypesHelper.swift */,
621ECCC7254204BE00D3D615 /* JSONSerializationWrapper.h */,
621ECCC6254204BE00D3D615 /* JSONSerializationWrapper.m */,
6263685F25F6EC0100576C1C /* PluginCallAccessorTests.m */,
621ECCCD254204C400D3D615 /* CapacitorTests-Bridging-Header.h */,
62959BBD2526510200A3D7F1 /* Info.plist */,
);
Expand Down Expand Up @@ -603,6 +606,7 @@
62A91C3425535F5700861508 /* ConfigurationTests.swift in Sources */,
62FABD2325AE60BA007B3814 /* BridgedTypesTests.m in Sources */,
621ECCC3254204B700D3D615 /* BridgedTypesTests.swift in Sources */,
6263686025F6EC0100576C1C /* PluginCallAccessorTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
2 changes: 2 additions & 0 deletions ios/Capacitor/Capacitor/CAPBridgedJSTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
- (NSString * _Nullable)getString:(NSString * _Nonnull)key defaultValue:(NSString * _Nullable)defaultValue;
- (NSDate * _Nullable)getDate:(NSString * _Nonnull)key defaultValue:(NSDate * _Nullable)defaultValue;
- (NSDictionary * _Nullable)getObject:(NSString * _Nonnull)key defaultValue:(NSDictionary * _Nullable)defaultValue;
- (NSNumber * _Nullable)getNumber:(NSString * _Nonnull)key defaultValue:(NSNumber * _Nullable)defaultValue;
- (BOOL)getBool:(NSString * _Nonnull)key defaultValue:(BOOL)defaultValue;
@end

@interface CAPPluginCall (BridgedJSProtocol) <BridgedJSValueContainerImplementation>
Expand Down
17 changes: 16 additions & 1 deletion ios/Capacitor/Capacitor/CAPBridgedJSTypes.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ - (NSString * _Nullable)getString:(NSString * _Nonnull)key defaultValue:(NSStrin

- (NSDate * _Nullable)getDate:(NSString * _Nonnull)key defaultValue:(NSDate * _Nullable)defaultValue {
id value = [[self dictionaryRepresentation] objectForKey:key];
if (value != nil && [value isKindOfClass:[NSString class]]) {
if (value != nil && [value isKindOfClass:[NSDate class]]) {
return value;
}
else if (value != nil && [value isKindOfClass:[NSString class]]) {
return [[[self class] jsDateFormatter] dateFromString:value];
}
return defaultValue;
Expand All @@ -25,4 +28,16 @@ - (NSDictionary * _Nullable)getObject:(NSString * _Nonnull)key defaultValue:(NSD
}
return defaultValue;
}

- (NSNumber * _Nullable)getNumber:(NSString * _Nonnull)key defaultValue:(NSNumber * _Nullable)defaultValue {
id value = [[self dictionaryRepresentation] objectForKey:key];
if (value != nil && [value isKindOfClass:[NSNumber class]]) {
return value;
}
return defaultValue;
}

- (BOOL)getBool:(NSString * _Nonnull)key defaultValue:(BOOL)defaultValue {
return [[self getNumber:key defaultValue:[NSNumber numberWithBool:defaultValue]] boolValue];
}
@end
4 changes: 2 additions & 2 deletions ios/Capacitor/Capacitor/CAPPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
// need to override init()
-(void)load;
-(NSString* _Nonnull)getId;
-(BOOL)getBool:(CAPPluginCall* _Nonnull) call field:(NSString* _Nonnull)field defaultValue:(BOOL)defaultValue;
-(NSString* _Nullable)getString:(CAPPluginCall* _Nonnull)call field:(NSString* _Nonnull)field defaultValue:(NSString* _Nonnull)defaultValue;
-(BOOL)getBool:(CAPPluginCall* _Nonnull) call field:(NSString* _Nonnull)field defaultValue:(BOOL)defaultValue DEPRECATED_MSG_ATTRIBUTE("Use accessors on CAPPluginCall instead. See CAPBridgedJSTypes.h for Obj-C implementations.");
-(NSString* _Nullable)getString:(CAPPluginCall* _Nonnull)call field:(NSString* _Nonnull)field defaultValue:(NSString* _Nonnull)defaultValue DEPRECATED_MSG_ATTRIBUTE("Use accessors on CAPPluginCall instead. See CAPBridgedJSTypes.h for Obj-C implementations.");
-(id _Nullable)getConfigValue:(NSString* _Nonnull)key;
-(void)setCenteredPopover:(UIViewController* _Nonnull)vc;
-(BOOL)supportsPopover;
Expand Down
32 changes: 6 additions & 26 deletions ios/Capacitor/Capacitor/CAPPlugin.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import "CAPPlugin.h"
#import "CAPBridgedJSTypes.h"
#import <Capacitor/Capacitor-Swift.h>
#import <Foundation/Foundation.h>

Expand All @@ -19,34 +20,13 @@ -(NSString *) getId {
return self.pluginName;
}

-(BOOL) getBool:(CAPPluginCall *)call field:(NSString *)field defaultValue:(BOOL)defaultValue {
id idVal = [call.options objectForKey:field];

if(![idVal isKindOfClass:[NSNumber class]]) {
return defaultValue;
}

NSNumber *value = (NSNumber *)idVal;
if(value == nil) {
return defaultValue;
}
if(value.integerValue == 0) {
return FALSE;
}
return TRUE;
- (BOOL)getBool:(CAPPluginCall *)call field:(NSString *)field defaultValue:(BOOL)defaultValue {
NSNumber* value = [call getNumber:field defaultValue:[NSNumber numberWithBool:defaultValue]];
return [value boolValue];
}

-(NSString *) getString:(CAPPluginCall *)call field:(NSString *)field defaultValue:(NSString *)defaultValue
{
id idVal = [call.options objectForKey:field];
if(![idVal isKindOfClass:[NSString class]]) {
return defaultValue;
}
NSString *value = (NSString *)idVal;
if(value == nil) {
return defaultValue;
}
return value;
- (NSString *) getString:(CAPPluginCall *)call field:(NSString *)field defaultValue:(NSString *)defaultValue {
return [call getString:field defaultValue:defaultValue];
}

-(id)getConfigValue:(NSString *)key {
Expand Down
106 changes: 106 additions & 0 deletions ios/Capacitor/CapacitorTests/PluginCallAccessorTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#import <XCTest/XCTest.h>
#import <Capacitor/Capacitor.h>
#import <Capacitor/CAPBridgedJSTypes.h>
// forward declaration of internal capacitor classes that are exposed in the swift header via the @testable import.
@interface CAPWebViewAssetHandler: NSObject
@end
@interface CapacitorBridge: NSObject
@end
@interface CAPWebViewDelegationHandler: NSObject
@end
// import that will fail without the declarations
#import "CapacitorTests-Swift.h"

// interface for this class
@interface PluginCallAccessorTests : XCTestCase
@property (strong, nonatomic) CAPPluginCall* call;
@end

@implementation PluginCallAccessorTests

- (void)setUp {
[super setUp];
NSDate* date = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:632854800];
NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init];
NSDictionary* options = @{@"testString":@"foo",
@"testDict": @{@"testSubkey":@"sub value"},
@"testFloat": @3.14159,
@"testDateObject": date,
@"testDateString": [formatter stringFromDate:date],
@"testBoolTrue": @TRUE,
@"testBoolFalse": @FALSE};
[self setCall:[[CAPPluginCall alloc] initWithCallbackId:@"test" options:options success:NULL error:NULL]];
}

- (void)testStringAccessor {
NSString* value = [[self call] getString:@"testString" defaultValue:NULL];
XCTAssertEqual(value, @"foo");

value = [[self call] getString:@"badString" defaultValue:NULL];
XCTAssertNil(value);

value = [[self call] getString:@"badString" defaultValue:@"default"];
XCTAssertEqual(value, @"default");
}

- (void)testDateObjectAccessor {
NSDate* value = [[self call] getDate:@"testDateObject" defaultValue:NULL];
XCTAssertEqual([value timeIntervalSinceReferenceDate], 632854800);

value = [[self call] getDate:@"badString" defaultValue:NULL];
XCTAssertNil(value);

NSDate *defaultDate = [NSDate date];
value = [[self call] getDate:@"badString" defaultValue:defaultDate];
XCTAssertEqual(value, defaultDate);
}

- (void)testDateStringAccessor {
NSDate* objectValue = [[self call] getDate:@"testDateObject" defaultValue:NULL];
NSDate* stringValue = [[self call] getDate:@"testDateString" defaultValue:NULL];
XCTAssertNotNil(objectValue);
XCTAssertNotNil(stringValue);
XCTAssertEqual(objectValue, stringValue);
}

- (void)testObjectAccessor {
NSDictionary* value = [[self call] getObject:@"testDict" defaultValue:NULL];
XCTAssertEqual([value objectForKey:@"testSubkey"], @"sub value");

value = [[self call] getObject:@"badString" defaultValue:NULL];
XCTAssertNil(value);

value = [[self call] getObject:@"badString" defaultValue:@{@"defaultKey":@"default"}];
XCTAssertEqual([value objectForKey:@"defaultKey"], @"default");
}

- (void)testNumberAccessor {
NSNumber* value = [[self call] getNumber:@"testFloat" defaultValue:NULL];
XCTAssertNotNil(value);
XCTAssertTrue([value isEqualToNumber:@3.14159]);

value = [[self call] getNumber:@"badString" defaultValue:NULL];
XCTAssertNil(value);

value = [[self call] getNumber:@"badString" defaultValue:@100];
XCTAssertEqual([value intValue], 100);

value = [[self call] getNumber:@"testBoolTrue" defaultValue:NULL];
XCTAssertNotNil(value);
XCTAssertEqual([value boolValue], TRUE);
}

- (void)testBoolAccessor {
BOOL value = [[self call] getBool:@"testBoolTrue" defaultValue:false];
XCTAssertTrue(value);

value = [[self call] getBool:@"testBoolFalse" defaultValue:true];
XCTAssertFalse(value);

value = [[self call] getBool:@"badString" defaultValue:true];
XCTAssertTrue(value);

value = [[self call] getBool:@"badString" defaultValue:false];
XCTAssertFalse(value);
}
@end

0 comments on commit e3657d7

Please sign in to comment.