I installed RN Push Notificaitons for IOS by following the guide on https://github.com/zo0r/react-native-push-notification. I ran npx pod-install after the installation of both react-native-push-notification and #react-native-community/push-notification-ios. The guide on #react-native-community/push-notification-ios stated that I had to update my Appdelegate.h and Appdelegate.m so I did (please see results of edit below) for each file. I also added push notification in Xcode. I ran npx react-native run-ios and the build failed.
However, when I removed the edits made to the Appdelegate.h and Appdelegate.m files, the build succeeded and the popup appeared "App wants to send you push notifications"
Is this ok or I'm doing something wrong?
Appdelgate.m file :
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
static void InitializeFlipper(UIApplication *application) {
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin:[FlipperKitReactPlugin new]];
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
}
#endif
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
[RNCPushNotificationIOS didReceiveNotificationResponse:response];
}
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLED
InitializeFlipper(application);
#endif
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:#"yuna"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
// Define UNUserNotificationCenter
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
return YES;
}
//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:#"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:#"main" withExtension:#"jsbundle"];
#endif
}
#end
Appdelegate.h file:
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
#property (nonatomic, strong) UIWindow *window;
#end
Related
Before explaining I need to say EVERYTHING is working perfect on Android and the problem is on IOS devices I am using react-native-signature-capture , I have two signature field at the same page, I solve the problem of not getting saved but when I save one of the field both of them get the same value for the signature .
How can I handle it?
codes for signature component here
This is the extraInputsList logs in the codes
and this is my RSSSignatureViewManager.m file
#import "RSSignatureViewManager.h"
#import <React/RCTBridgeModule.h>
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUIManager.h>
#implementation RSSignatureViewManager
#synthesize bridge = _bridge;
#synthesize signView;
RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(rotateClockwise, BOOL)
RCT_EXPORT_VIEW_PROPERTY(square, BOOL)
RCT_EXPORT_VIEW_PROPERTY(showBorder, BOOL)
RCT_EXPORT_VIEW_PROPERTY(showNativeButtons, BOOL)
RCT_EXPORT_VIEW_PROPERTY(showTitleLabel, BOOL)
-(dispatch_queue_t) methodQueue
{
return dispatch_get_main_queue();
}
-(UIView *) view
{
self.signView = [[RSSignatureView alloc] init];
self.signView.manager = self;
return signView;
}
// Both of these methods needs to be called from the main thread so the
// UI can clear out the signature.
RCT_EXPORT_METHOD(saveImage:(nonnull NSNumber *)reactTag) {
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
RSSignatureView *view = viewRegistry[reactTag];
if (!view || ![view isKindOfClass:[RSSignatureView class]]) {
RCTLogError(#"Cannot find NativeView ", reactTag);
return;
}
[view saveImage];
}];
}
RCT_EXPORT_METHOD(resetImage:(nonnull NSNumber *)reactTag) {
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
RSSignatureView *view = viewRegistry[reactTag];
if (!view || ![view isKindOfClass:[RSSignatureView class]]) {
RCTLogError(#"Cannot find NativeView with tag", reactTag);
return;
}
[view erase];
}];
}
-(void) publishSaveImageEvent:(NSString *) aTempPath withEncoded: (NSString *) aEncoded {
[self.bridge.eventDispatcher
sendDeviceEventWithName:#"onSaveEvent"
body:#{
#"pathName": aTempPath,
#"encoded": aEncoded
}];
}
-(void) publishDraggedEvent {
[self.bridge.eventDispatcher
sendDeviceEventWithName:#"onDragEvent"
body:#{#"dragged": #YES}];
}
#end
Solution
just install this package from this git
you can edit package.json like this
"react-native-signature-capture": "git+https://github.com/nomi9995/react-native-signature-capture.git",
Then do yarn install, react-native link react-native-signature-capture, and finally, it works great when I have multiple signature-pads!
UPDATE:
Both the Android and iOS versions save images from any signature box to the same path/filename. To support multiple boxes, you'll need to deal with the encoding/file sequentially. Or you can overload/change the saveImage method to take a filename.
Looks every time you save an image, this library will actively delete the previous image.
Android version from RSSignatureCaptureMainView.java:140
final void saveImage() {
String root = Environment.getExternalStorageDirectory().toString();
// the directory where the signature will be saved
File myDir = new File(root + "/saved_signature");
// make the directory if it does not exist yet
if (!myDir.exists()) {
myDir.mkdirs();
}
// set the file name of your choice
String fname = "signature.png";
// in our case, we delete the previous file, you can remove this
File file = new File(myDir, fname);
if (file.exists()) {
file.delete();
}
.
.
.
iOS version from RSSignatureView.m:186
-(void) saveImage {
saveButton.hidden = YES;
clearButton.hidden = YES;
UIImage *signImage = [self.sign signatureImage: _rotateClockwise withSquare:_square];
saveButton.hidden = NO;
clearButton.hidden = NO;
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
NSString *tempPath = [documentsDirectory stringByAppendingFormat:#"/signature.png"];
//remove if file already exists
if ([[NSFileManager defaultManager] fileExistsAtPath:tempPath]) {
[[NSFileManager defaultManager] removeItemAtPath:tempPath error:&error];
if (error) {
NSLog(#"Error: %#", error.debugDescription);
}
}
.
.
.
Previous answer:
This looks to be a known issue.
In RSSignatureViewManager.m, add #import <React/RCTUIManager.h>
and change the method RCT_EXPORT_METHOD to the following
RCT_EXPORT_METHOD(saveImage:(nonnull NSNumber *)reactTag) {
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
RSSignatureView *view = viewRegistry[reactTag];
if (!view || ![view isKindOfClass:[RSSignatureView class]]) {
RCTLogError(#"Cannot find NativeView with tag #%#", reactTag);
return;
}
[view saveImage];
}];
}
i have no idea why the uiactivityviewcontroller crash when i use the prensentViewController method.
it is weird, anyone has any clue?
the program is running fine not untile when i use the presenviewcontroller.
#import "ActivityViewController.h"
#interface ActivityViewController ()
#end
#implementation ActivityViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self createTextField];
[self createButton];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) createTextField
{
self.myTextField = [[UITextField alloc] initWithFrame:CGRectMake(20.0f, 35.0f, 280.0f, 30.0f)];
self.myTextField.translatesAutoresizingMaskIntoConstraints = NO;
self.myTextField.borderStyle = UITextBorderStyleRoundedRect;
self.myTextField.placeholder =#"Enter text to Share";
self.myTextField.delegate = self;
[self.view addSubview:self.myTextField];
}
- (void) createButton
{
self.myButtonShare = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.myButtonShare.frame = CGRectMake(20.0f, 80.0f, 280.0f, 40.0f);
self.myButtonShare.translatesAutoresizingMaskIntoConstraints = NO;
[self.myButtonShare setTitle:#"Share" forState:UIControlStateNormal];
[self.myButtonShare addTarget:self action:#selector(handleShare:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.myButtonShare];
}
- (void) handleShare:(id)sender
{
NSArray *activities = #[UIActivityTypeMail,UIActivityTypeMessage];
self.myActivityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[self.myTextField.text] applicationActivities:activities];
[self presentViewController:self.myActivityViewController animated:YES completion:nil];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self.myButtonShare resignFirstResponder];
return YES;
}
What ccjensen said is all correct, except you can actually restrict your share sheet to just Mail & Message by excluding activities, this way for example:
activityController.excludedActivityTypes = #[ UIActivityTypeCopyToPasteboard, UIActivityTypeAddToReadingList ];
This would only show the email sharing by default.
The documentation for UIActivityViewController's initWithActivityItems:applicationActivities: states that the NSArray passed as the second parameter (applicationActivities) should be an "array of UIActivity". You are passing in an array containing the two objects UIActivityTypeMail and UIActivityTypeMessage which are of type NSString *const. It seems that you were hoping that you could restrict the share sheet to only show the mail and messages activity, which is currently not possible.
To stop the crash from happening, change your code to:
<...>
self.myActivityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[self.myTextField.text] applicationActivities:nil];
<...>
I have UITableview in second page then I try to navigate into third page but problem is that my code is not working. Here is the code for both AppDelegate.m file and also SecondViewController.m file,
Plz check the code and give me suggestion what i am doing wrong
SecondViewController.m file code
- (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ThirdViewController *third = [[ThirdViewControllerr alloc] initWithNibName: #"ThirdViewControllerr" bundle:nil];
ForthViewController *forth = [[ForthViewControlle alloc] initWithNibName: #"ForthViewController" bundle:nil];
if(indexPath.row==0)
{
[[self navigationController] pushViewController:third animated:YES];
}
if(indexPath.row==1)
{
[[self navigationController] pushViewController:forth animated:YES];
}
In AppDelegate.m file i write the code for Secondviewcontroller in witch using UITableview, also i have initialized the UINavigationController inside AppDelegate.m file.If anyone have idea reply me as soon as possible,
without use UINavigationController inside AppDelegate.m file its possible for UItableview Navigation
AppsDelegate.m file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[MobileViewController alloc] initWithNibName:#"MobileViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
self.window1=[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen]bounds]];
self.viewController1=[[HealthCalculatorsViewController alloc]initWithNibName:#"HealthCalculatorsViewController" bundle:nil];
UINavigationController *nav1=[[UINavigationController alloc]initWithRootViewController:_viewController1];
self.window1.rootViewController=nav1;
[self.window1 makeKeyAndVisible];
return YES;
}
Please guide me.
Thanks.
add this in your Appdelegate.h
UINavigationController * navController;
and this in your Appdelegate.m
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
FirstViewController * viewPhone =[[FirstViewController alloc]initWithNibName:#"FirstViewController_iPhone" bundle:nil];
navController=[[UINavigationController alloc]initWithRootViewController:viewPhone];
}
else
{
FirstViewControllerController * viewPad =[[FirstViewControllerController alloc]initWithNibName:#"FirstViewController_iPad" bundle:nil];
navController=[[UINavigationController alloc]initWithRootViewController:viewPad];
}
navController.navigationBar.tintColor = [UIColor blackColor];
self.window.rootViewController=navController;
on your button click
- (IBAction)Btn_Pressed:(id)sender {
SecondViewController * second=[[SecondViewController alloc]init];
if (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
second = [[SecondViewController alloc] initWithNibName:#"SecondViewController_iPhone" bundle:nil];
else
second = [[SecondViewController alloc] initWithNibName:#"SecondViewController_iPad" bundle:nil];
[self.navigationController pushViewController:lagrangae animated:YES];
}
if you dont want navigation bar just hide it by
[[self navigationController] setNavigationBarHidden:YES animated:YES];
Using iOS6:
I would like to retrieve the text entered by a user into a UITextField associated with the UIAlertView. I am aware that I could achieve the desired result with a delegate however I am curious about solving this issue with a callback function as I believe this may be an interesting pattern. I began by examining a common pattern for category extension of the UIAlertView class. Code below. Thanks in advance for any suggestions.
import <UIKit/UIKit.h>
#interface UIAlertView (Block)
- (id)initWithTitle:(NSString *)title message:(NSString *)message completion:(void (^)(BOOL cancelled, NSInteger buttonIndex, UITextField *textField))completion cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;
#end
The .m for the category follows:
#import "UIAlertView+Block.h"
#import <objc/runtime.h>
static char const * const alertCompletionBlockTag = "alertCompletionBlock";
#implementation UIAlertView (Block)
- (id)initWithTitle:(NSString *)title
message:(NSString *)message
completion:(void (^)(BOOL cancelled, NSInteger buttonIndex))completion
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ... {
self = [self initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil ];
if (self) {
objc_setAssociatedObject(self, alertCompletionBlockTag, completion, OBJC_ASSOCIATION_COPY);
va_list _arguments;
va_start(_arguments, otherButtonTitles);
for (NSString *key = otherButtonTitles; key != nil; key = (__bridge NSString *)va_arg(_arguments, void *)) {
[self addButtonWithTitle:key];
}
va_end(_arguments);
}
[self setAlertViewStyle:UIAlertViewStylePlainTextInput];
return self;
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
id completion = objc_getAssociatedObject(self, alertCompletionBlockTag);
[self complete:completion index:buttonIndex];
}
- (void) complete:(void (^)(BOOL cancelled, NSInteger buttonIndex))block index:(NSInteger)buttonIndex {
BOOL _cancelled = (buttonIndex == self.cancelButtonIndex);
block(_cancelled, buttonIndex );
objc_setAssociatedObject(self, alertCompletionBlockTag, nil, OBJC_ASSOCIATION_COPY);
//objc_removeAssociatedObjects(block);
}
#end
Usage for the category is set below. The main problem is my inability to reference the UIAlertView textField at Index 0 from within the completion block.
[[[UIAlertView alloc] initWithTitle:#"Add"
message:#"Add New Asset Type"
completion:^(BOOL cancelled, NSInteger buttonIndex){
if (!cancelled) {
//call on completion of UISheetAction ???
NSLog(#"%#",needToAccessUIAlertView._textFields[0]);
}
}
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil] show];
So basically you want to access the alert view from the block. You can do something like this:
__block __weak UIAlertView *alertViewWeak;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Add"
message:#"Add New Asset Type"
completion:^(BOOL cancelled, NSInteger buttonIndex){
if (!cancelled) {
//call on completion of UISheetAction ???
NSLog(#"%#",[alertViewWeak textFieldAtIndex:0]);
}
}
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
alertViewWeak = alertView;
[alertView show];
If you want to make a category by yourself, above is good enough.
But, there are many classes that uses delegation pattern. Do you want to make categories one by one?
There is REKit. With it, you can use that classes as if they were Block-based:
UIAlertView *alertView;
alertView = [[UIAlertView alloc]
initWithTitle:#"title"
message:#"message"
delegate:nil
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil
];
[alertView
respondsToSelector:#selector(alertView:didDismissWithButtonIndex:)
withKey:nil
usingBlock:^(id receiver, UIAlertView *alertView, NSInteger buttonIndex) {
// Do something…
}
];
alertView.delegate = alertView;
Try this library Here is another useful library to do the same. http://ichathan.com/2014/08/19/ichalertview/
shouldStartLoadWithRequest:navigationType and webViewDidStartLoad methods of UIWebview gets called once but after that the activityIndicator keeps on rotating (starts in webViewDidStartLoad) and none of the delegate methods webViewDidFinishLoad or didFailLoadWithError gets called. This is an issue on IOS 6 only.
This is working for me in iOS 5 and 6. Make sure you connect your outlets in Interface Builder. You should probably do some sort of check to see if Internet access is available. I'm doing it with the Apple Reachability class:
Header:
#import <UIKit/UIKit.h>
#interface HelpWebViewController : UIViewController <UIWebViewDelegate>
{
IBOutlet UIWebView *webView;
IBOutlet UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, strong) UIWebView *webView;
#property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
#property (nonatomic, strong) NSString *webHelpURLString;
- (void)webViewDidStartLoad:(UIWebView *)webView; //a web view starts loading
- (void)webViewDidFinishLoad:(UIWebView *)webView;//web view finishes loading
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error; //web view failed to load
#end
Implementation file:
#import "HelpWebViewController.h"
#import "Reachability.h" // Needs System Configuration Framework
#interface HelpWebViewController ()
#end
#implementation HelpWebViewController
#synthesize webView = ivWebView;
#synthesize activityIndicator = ivActivityIndicator;
#synthesize webHelpURLString = ivWebHelpURLString;
-(BOOL)reachable {
Reachability *r = [Reachability reachabilityWithHostName:#"apple.com"];
NetworkStatus internetStatus = [r currentReachabilityStatus];
if(internetStatus == NotReachable) {
return NO;
}
return YES;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSURL *webHelpURL = [NSURL URLWithString:#"support.apple.com"];
NSURLRequest *myrequest = [NSURLRequest requestWithURL:webHelpURL];
[self.webView loadRequest:myrequest];
self.webView.scalesPageToFit = YES;
if ([self reachable]) {
NSLog(#"Reachable");
}
else {
NSLog(#"Not Reachable");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"cantOpenWebPageAlertTitle", #"Cannot Open Page - UIAlert can't open web page")
message:NSLocalizedString(#"cantOpenWebPageAlertMessage", #"The page cannot be opened because you're not connected to the Internet.")
delegate:nil
cancelButtonTitle:NSLocalizedString(#"cantOpenWebPageAlertOKButton", #"OK - accept alert")
otherButtonTitles:nil];
[alert show];
alert = nil;
}
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
[self.activityIndicator startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[self.activityIndicator stopAnimating];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
[self.activityIndicator stopAnimating];
}
#end