Navigate to Swift UIViewController from Objective-C file - react-native

I'm trying to add a native module to a react native project. When the user clicks a button in react native, I want to open the first screen of this native project: https://github.com/AgoraIO/OpenVideoCall-iOS/tree/master/OpenVideoCall
I followed the instructions here https://facebook.github.io/react-native/docs/native-modules-ios to make a native module in Obj-C. I have a class MainViewController which extends UIController. How can I launch or navigate to MainViewController from the objective-C file. I have turned on packages/definesmodules in Xcode build settings, and I try importing "buildtarget-Swift.h" as described here Call Swift function from Objective C class. The import works but MainViewController cannot be found when I try using it.
Here is my code (my Xcode target name is "merge_test" and MainViewController is in merge_test/OpenVideoCall/MainViewController.swift)
:
`
#import "Call.h"
#import <UIKit/UIKit.h>
#import "merge_test-Swift.h"
#implementation Call
RCT_EXPORT_MODULE();
//exports a method to javascript
RCT_EXPORT_METHOD(navigateToExample:(NSString *)name){
MainViewController * vc = [[MainViewController alloc] init];
}
#end
`
I get the error 'Unknown receiver mainviewcontroller' but I'm pretty sure I'm doing more wrong than just that. How do I do this? It was incredibly simple for android, I feel there must be a simple way for ios.
Thanks!

Related

Menu bar application actions with Objective C?

I've recently been trying to create an application on Xcode 9.4.1 with the Objective-C programming language.
I am trying to make the application work from the menu bar rather than a full app.
However, I have only managed to make the Menu items show up and have no idea how to add actions such as a web link to the buttons.
Can anyone help with this? All I want is to add actions to the buttons using code.
P.S. I am not using storyboards.
Without providing what you've done so far it seems like you're asking for complete code, nevertheless I happen to have an old project that does it. In the app delegate you do something like this: in the barItemAction method you can do whatever you need to perform
#interface AppDelegate ()
#property NSStatusItem *barItem ;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.barItem = [NSStatusBar.systemStatusBar statusItemWithLength:NSVariableStatusItemLength];
self.barItem.button.title = #"🚀";
[self.barItem setAction:#selector(barItemAction)];
// Insert code here to initialize your application
}
-(void)barItemAction {
NSLog(#"🚀 button was clicked ");
}

React Native - Native iOS module crashes when opening Settings app

I'm trying to create a simple React Native module which will allow me to open the iOS settings application from within a React Native application.
My implementation:
#import <UIKit/UIKit.h>
#import "RNOpenAppSettings.h"
#implementation RNOpenAppSettings
- (dispatch_queue_t)methodQueue
{
return dispatch_queue_create("com.krazylabs.RNOpenAppSettings", DISPATCH_QUEUE_SERIAL);
}
RCT_EXPORT_MODULE(OpenAppSettings)
RCT_EXPORT_METHOD(open){
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
#end
The above actually does open the iOS settings application but then crashes almost immediately. My first assumption was that perhaps the operation was taking too long and blocking the React Native queue; which is why I'm creating a separate queue. This did not help.
Has anyone run into this?
I was able to resolve this by calling openURL asynchronously using GCD. Hopefully this helps someone else.
#import <UIKit/UIKit.h>
#import "RNOpenAppSettings.h"
#implementation RNOpenAppSettings
RCT_EXPORT_MODULE(OpenAppSettings)
RCT_EXPORT_METHOD(open){
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
});
}
#end

Adding Google Cardboard SDK to a React Native project

I'm currently working on a React Native application that amongst other things, it needs to show a panorama using the Google Cardboard SDK. I seem to have most of the things set up but given my very limited knowledge on Objective-C, I am not able to connect all ports of the puzzle.
Currently, I have my javascript connecting with objective-c so that's all fine however, looking at the example code in the Cardboard SDK, a PanoramaViewController of type UIViewController is defined and the necessary elements of the page (text, actual panorama viewer, etc) are added to the view using something like:
[_scrollView addSubview:_panoView];
In my case, given that i am defining my ViewController with type NSObject RCTBridgeModule, if I understand correctly, I am not able to do this, unless i'm not missing something else.
I've been looking around to try and find what's the best way of going about this and what I found was something along these lines:
UIViewController *rootController = UIApplication.sharedApplication.delegate.window.rootViewController;
[rootController presentViewController:MyViewController animated:YES completion:nil];
In the above, I don't know what exactly do I have to pass instead of MyViewController given that to my understanding, the Cardboard SDK only creates the view and I am responsible of creating the actual ViewController.
At the moment, this is how my ViewController.h looks like:
#import <Foundation/Foundation.h>
#import "RCTBridge.h"
#interface GCViewController : NSObject <RCTBridgeModule>
#end
and this is how my ViewController.m looks like:
#import "GCViewController.h"
#import "AppDelegate.h"
#import "RCTLog.h"
#import "GCSPanoramaView.h"
#interface GCViewController ()<GCSWidgetViewDelegate>
#end
#implementation GCViewController {
GCSPanoramaView *_panoView;
}
RCT_EXPORT_MODULE();
-(void)show360Video {
_panoView = [[GCSPanoramaView alloc] init];
_panoView.delegate = self;
_panoView.enableFullscreenButton = YES;
_panoView.enableCardboardButton = YES;
[_panoView loadImage:[UIImage imageNamed:#"test.jpg"]
ofType:kGCSPanoramaImageTypeMono];
UIViewController *rootController = UIApplication.sharedApplication.delegate.window.rootViewController;
[rootController presentViewController:XXXXXX animated:YES completion:nil];
}
RCT_EXPORT_METHOD(showVideo) {
[self show360Video];
}
#end
I would appreciate if anyone can help me on this. Thanks!
PS: in this project i'm using the Google Cardboard v0.7.2 and not the new Google VR library.
You can use rootController Which is defined before that error.Thanks

In objective C, how do I programmatically access a UIViewController?

Let's say I have a tabbar application that nests a lot of uitableviewcontrollers and uiviewcontrollers. What is the line of code that i would use to get a handle on a particular controller?
For example, let's say I want to grab the uitableviewcontroller which is currently the 3rd tab of the tab bar controller. I am in the MyObject.h/m file which has the following code:
MyObject.h
#import <Foundation/Foundation.h>
#import "MyAppDelegate.h"
#interface MyObject : NSObject
-(void) myfunction;
#end
MyObject.m
#import "MyObject.h"
#implementation MyObject
-(void) myfunction {
UITableViewController * mytvc = /*Some line of code*/;
}
#end
What do i replace /*Some line of code*/ with such that mytvc is a variable that points to the uitableviewcontroller i'm interested in?
I am using XCode 4.2. I have a storyboard that illustrates each of my uiviewcontrollers. The Tabbar view controller was the first thing xcode made for me. So I think that means it's the top of the app?
If it is your root view controller, and you have access to your app delegate, you should be able to access your controller like this:
appDelegate.window.rootViewController
rootViewController.tabBarController.viewControllers is an array of the root view controller for each tab. You can set the active view controller by setting tabBarController.selectedViewController or tabBarController.selectedIndex.
From the app delegate it's self.window.rootViewController.tabBarController. From a view controller it's self.view.window.rootViewController.tabBarController.
[[self.view.window.rootViewController.tabBarController.viewControllers objectAtIndex:2] myFunction] would access your function from another view controller. That is assuming your third tab is not a navigation controller.
If your tab has a navigation controller in it, then you have to add the navigation controller syntax on top of it. [[[self.view.window.rootViewController.tabBarController.viewControllers objectAtIndex:2] navigationController].visibleViewController myFunction] would be the full path. Looking at it now it seems a bit ridiculous.

PreferencesViewControllerDelegate

I found this in some example code I downloaded
#import "PreferencesViewController.h"
#class MetronomeView;
#interface MetronomeViewController : UIViewController <PreferencesViewControllerDelegate> {
MetronomeView *metronomeView;
}
#property (nonatomic, assign) IBOutlet MetronomeView *metronomeView;
- (IBAction)showInfo;
#end
I tried to find information on PreferencesViewControllerDelegate, but didn't find much. What is this delegate?
It's a custom view controller delegate protocol that is created by Apple, for use in the Metronome sample project (and I imagine others). The protocol declaration can be found here, and how it's implemented can be seen here.
All it does is act as a delegate that monitors what happens to PreferencesViewController, the controller that manages the preferences view.
The protocol contains one method called preferencesViewControllerDidFinish:, which is implemented by MetronomeViewController like this. When the delegate receives a signal that the preferences view has been dismissed with the Done button, this is called to hide the view:
- (void)preferencesViewControllerDidFinish:(PreferencesViewController *)controller {
[self dismissModalViewControllerAnimated:YES];
}
A similar delegate called FlipsideViewControllerDelegate can be found in the Xcode iOS project template for a Utility Application.
This looks like a custom delegate created by whoever wrote the code you downloaded. It's not an Apple delegate, since it doesn't start with any of Apple's two-letter prefixes.