RCT bridging with react native and objective C - objective-c

I have been following this tutorial, which is talking about how to communicated from React Native and objective C. I followed the tutorial, and got a good result. The problem started when I wanted to add a new function called sendData. This would be called in JS and it would pass a string, and in objective C, it would receive the string.
But, the bridging wasn't working.
Here is my code:
RCT_REMAP_METHOD(sendData : (NSString*)str,
sendData_resolver:(RCTPromiseResolveBlock)resolve
sendData_rejecter:(RCTPromiseRejectBlock)reject)
{
BOOL response = [_cppApi sendData];
resolve(response);
}
This code gives the error No visible #interface for 'CCCppCom' declares the selector 'sendData' in Xcode. (CCCppCom is a header file)
another function I have, which is getData seems to work fine.
RCT_REMAP_METHOD(getData,
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSString *response = [_cppApi getData];
resolve(response);
}
I'm not entirely sure what is going on here. I checked CCCppCom, and sendData is indeed there.
Can someone help me? Thanks in advance.

I solved the problem by using RCT_EXPORT_METHOD instead of RCT_REMAP_METHOD.

Related

How to show Airplay panel programmatically on iOS using flutter

The desired output looks like this,
how to show this on click event programmatically using flutter(even with native code if possible), it's really appreciated if anyone could show an example.
If there is no direct approach to this then a platform specific example using MethodChannel is also very welcome. Native code example must be in Objective C.
Additionally I have tried to use flutter_to_airplay but project fails to run and also has other functionalities that are not needed in this context, what is needed is showing Airplay panel only.
(Answer by M123 native code completely not working)
Here is a example how to open the AirPlayPanel in objective c.
Setup flutter
First you have to create a channel. To start communicating to the native code.
All channel names used in a single app must be unique; prefix the
channel name with a unique ‘domain prefix
static const platform = const MethodChannel('stack.M123.dev/airplay');
Then you have to invoke a method on the method channel.
Future<void> _openAirPlay() async {
try {
await platform.invokeMethod('openAirPlay');
} on PlatformException catch (e) {
print('error');
}
}
Native part
Now the flutter part is done.
First you have to add suppport for swift. For this open the ios folder in the flutter root with XCode.
Expand Runner > Runner in the Project navigator.
Open the AppDelegate.m located under Runner > Runner in the Project navigator.
Create a FlutterMethodChannel and add a handler inside the application didFinishLaunchingWithOptions: method. Make sure to use the same channel name as was used on the Flutter client side.
#import <Flutter/Flutter.h>
#import "GeneratedPluginRegistrant.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
FlutterMethodChannel* airPlayChannel= [FlutterMethodChannel
methodChannelWithName:#"stack.M123.dev/airplay"
binaryMessenger:controller.binaryMessenger];
[airPlayChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
// Note: this method is invoked on the UI thread.
if ([#"getBatteryLevel" isEqualToString:call.method]) {
int returnValue = [weakSelf openAirPlay];
result(#(returnValue));
}];
[GeneratedPluginRegistrant registerWithRegistry:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
Add the method in the AppDelegate class, just before #end
- (int)openAirPlay {
//Open air play
return (int)(100);
}
Discalimer: I am not a IOS developer so the steps are mostly theoretical.
I am following the official guide from Flutter. It can be found in full length here.

openUrl command works in Obj-C but not Swift

Our codebase is still very much a hybrid codebase, but I've been trying to do more work in Swift. Unfortunately I'm running into a weird situation where a command that works fine in Obj-C absolutely refuses to run in Swift.
I'm trying to send a file from one of our desktop products to another of our products. All of the URL schemes are set up correctly. This command in Obj-C works perfectly:
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:#"ourotherapp://v1/import?filePath=/Users/gi.joe/Documents/test.wav"]];
However, in trying to use the Swift version, this one absolutely refuses to execute. No exception, no clue, no nothing:
NSWorkspace.shared.open(URL(fileURLWithPath: "ourotherapp://v1/import?filePath=/Users/gi.joe/Documents/test.wav"))
Is there some difference in the way NSWorkspace works in Swift as opposed to Obj-C? I've looked over the Apple docs but maybe I missed something?
I see that you tried two different calls in Obj C and Swift.
I haven't tried the below code, maybe this example helps you:
if let checkURL = NSURL(string: "https://google.com") {
if NSWorkspace.shared().open(checkURL as URL) {
print("URL Successfully Opened")
}
} else {
print("Invalid URL")
}
Try this:
guard let url = URL(string: "someURL") else { return }
UIApplication.shared.open(url)

Cannot find * in scope

I'm migrating objective C to swift. I'm getting the error Cannot find 'NSUtils' in scope in the line-
_idInstance = NSUtils.sha256(_idInstance)
I have the NSUtils class in objective C. The function is also mentioned there and it's working well with other .m files:
+ (NSString *)sha256:(NSString *)clear {
....
}
The autofill suggestions also don't show for this. Please help.
In Swift, you should really use CryptoKit instead:
import CryptoKit
let digest = SHA256.hash(data: myData)
let digestString = String(bytes: digest.map { $0 }, encoding: .ascii)!

RCT_EXPORT_METHOD unknown argument type

I i try to bind my react code with an existing objective-C API. In my code i have:
#import "RcpRfidApi.h"
#implementation RcpRfidApi
// The React Native bridge needs to know our module
RCT_EXPORT_MODULE(RcpRfidApi);
- (NSDictionary *)constantsToExport {
return #{#"greeting": #"Welcome to the DevDactic\n React Native Tutorial!"};
}
RCT_EXPORT_METHOD(setReaderPower:(bool)on:(RCTResponseSenderBlock)callback) {
callback(#[[NSNull null], [NSNumber numberWithBool:on]]);
}
#end
but i have an error when i try to call my function on react
Unknowm argument type '_Bool' in method .... Extend RCTConvert to support this type.
RCT_EXPORT_METHOD() can only support BOOL or NSNumber for booleans.
https://facebook.github.io/react-native/docs/native-modules-ios
If you have this problem you maybe need to add a library to your project. Go in: Xcode > your project > Build Phases > Link binary with libraries.
In my case the Apple ExternalAccesory.framework was needed.

Objective-C To Swift: void (^safeHandler)(UIBackgroundFetchResult)

I am porting some AppDelegate code for a plugin Objective-C to Swift.
My Objective-C is pretty good but I am stumped at understanding whats going on here. This is the code I am stuck on porting:
void (^safeHandler)(UIBackgroundFetchResult) = ^(UIBackgroundFetchResult result){
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler(result);
});
};
I understand that the the ^ is for code blocks, but looking at this as a whole I am lost as to what is going on and how to port this to Swift.
I don't understand how there are two bracketed portions here:
void (^safeHandler)(UIBackgroundFetchResult)
If you can advise what that syntax is and how to port to Swift I would greatly appreciate it!
It's a block, which is a closure in Swift. This block is named safeHandler and takes a UIBackgroundFetchResult parameter and returns void.
This is the equivalent type:
let safeHandler: (UIBackgroundFetchResult) -> ()
And the whole thing would be
let safeHandler: (UIBackgroundFetchResult) -> () = { result in
dispatch_async(dispatch_get_main_queue()) {
completionHandler(result)
}
}
Note: block syntax is notoriously wonky. You can use this site to see the various block syntax forms: http://goshdarnblocksyntax.com/