React Native - Native iOS module crashes when opening Settings app - react-native

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

Related

Navigate to Swift UIViewController from Objective-C file

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!

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

textFieldShouldReturn not firing in iPad app

I have an iPad app created using XCode 4 with Storyboard. I have a UITableViewController with the interface defined as such:
#interface CustomerViewController : UITableViewController <UITextFieldDelegate>
In the .m file, I have a code snippet as:
- (BOOL) textFieldShouldReturn:(UITextField *)textField {
if(textField == businessName) {
[email becomeFirstResponder];
return true;
}
The method 'textFieldShouldReturn' does NOT get executed. What else needs to be done? (BTW... I have never been able to get this to work in a iPad app, but always successful in a iPhone app)
In the textFieldShouldReturn method, you're testing if the textField is equal to businessName. I'm assuming that's a UITextField object, but you have to set the delegate to receive callbacks. Just a simple self.businessName.delegate = self; when you create the TextField.
Another tip, I'd recommend calling it something like businessNameTextField. It's easier to read throughout your code.
You have to set the view controller as the delegate of the text field, just declaring that you conform to the protocol isn't enough. If it works in the iPhone but not iPad, then the chances are you haven't linked the delegate outlet in the iPad storyboard, but you have in the iPhone.

upgraded to xcode 4.2 now exc_bad_access on dimissModalViewcontroller

Hi I'm having a weird problem.
My app is based on the samplecode of "PageControl" (the Apple example).
It uses a horizontal scrollview in which most of the stuff is happening.
At he bottom I have a UIToolbar from which I call a modal viewcontroller.
On XCode 4 everything worked like a charm, after the upgrade to XCode 4.2 (with the new SDK) I get a "exc_bad_access" on dimissModalViewcontroller.
The funniest thing is that it does not happen rightaway but only after 2 or 3 times presenting and dismissing the modalViewcontroller.
To simplify things I went back to the original samplecode and tried to implement the modalVieWcontroler in that context. No luck so far.
In the original PageControl Code I changed the type of "ContentController" from NSObject to UIViewController like so:
#interface ContentController : UIViewController
{
NSArray *contentList;
}
I call presentModalViewcontroller in a sub class (from ContentController) named PhoneContentController like so:(I use a notification so I can call it from anywhere)
-(void) showExplanationsModal:(NSNotification*)notification{
ExplanationsViewController *xplViewController = [[[ExplanationsViewController alloc] initWithNibName:#"Explanations" bundle:nil]autorelease];
[self presentModalViewController:xplViewController animated:YES];
}
The dismissal of the modalViewcontroller is called from the modal view itself like so:
(the notification is used tot initiate some other stuff)
- (IBAction)onClose
{
[self dismissModalViewControllerAnimated:YES];
[[NSNotificationCenter defaultCenter]postNotificationName:#"dismissExplanationsModal" object:self];
}
This code works fine with iOS4 SDK but renders occasional excec_bad_access with iOS5 SDK.
When I compile the app with iOS4 SDK it also rus fine on iOS5 devices.
I tried using Zombies but this does not point to a specific over-released object.
I'm sort of stuck on this one for a few days already ...
I have put up a copy of a sample project that illustrates the problem here http://www.sesni.biz/pagecontrol.zip
It seems for me that problem is in the onClose method. Try first sending the message, without the object (this object will be invalidated soon).
- (IBAction)onClose
{
[[NSNotificationCenter defaultCenter]postNotificationName:#"dismissExplanationsModal" object:nil];
[self dismissModalViewControllerAnimated:YES];
}
Found the problem: I changed the type of ContententController from NSObject to UIViewcontroller. This worked fine with the iOS4 SDK but crashes with iOS5 SDK.

mouseDown: not firing in WebView subclass

I think this should be quite simple, but I cannot make it work.
I want to detect mouse clicks on a WebView...
I've subclassed WebView, here is the code
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
#interface ResultsWebView : WebView {
}
#end
and
#import "ResultsWebView.h"
#implementation ResultsWebView
- (void)mouseDown:(NSEvent *)theEvent {
NSLog(#"%#", theEvent);
}
#end
In my xib file, I added a WebView and then changed the class to ResultsWebView.
I've checked in runtime and the object is a ResultsWebView, but the mouseDown event is never called...
What am I missing?
WebUIDelegate comes into rescue.
Supposing that you have a WebView instance in your NSWindowController:
WebView *aWebView;
You can set your controller as UIDelegate, as follow:
[aWebView setUIDelegate:self];
implementing the following method within your controller, you will have a form of control over mouse click events:
- (void)webView:(WebView *)sender mouseDidMoveOverElement:
(NSDictionary *)elementInformation modifierFlags:(NSUInteger)
modifierFlags
{
if ([[NSApp currentEvent] type] == NSLeftMouseUp)
NSLog(#"mouseDown event occurred");
}
as a bonus, playing with the elementInformation dictionary you can get additional informations about the DOM element in which click event occurred.
The problem is that the message isn't being sent to the WebView. Instead it is being sent to the private WebHTMLView inside your WebView, which actually processes the mouse events.
http://trac.webkit.org/browser/trunk/Source/WebKit/mac/WebView/WebHTMLView.mm#L3555
You might just want to look into using javascript in your WebView to send the onmousedown events back to your objective-c class.
Maybe this helps:
[window setAcceptsMouseMovedEvents:YES];