I am trying to monitor the callStates.I implemented an own class for this with this init method:
- (id) init
{
self = [super init];
if (!self) return nil;
callCenter = [[CTCallCenter alloc] init];
[callCenter setCallEventHandler: ^(CTCall* call) {
if ([call.callState isEqualToString: CTCallStateConnected]) {
} else if ([call.callState isEqualToString: CTCallStateDialing]) {
} else if ([call.callState isEqualToString: CTCallStateDisconnected]) {
} else if ([call.callState isEqualToString: CTCallStateIncoming]) {
}
NSLog(#"\n\n callEventHandler: %# \n\n", call.callState);
}];
return self;
}
#property(nonatomic, strong) CTCallCenter* callCenter;
I linked the CoreTelephony Framework in my Project...But the Block never gets called...If i put the same Code in my AppDelegate, it works...
Des it only work in AppDelegate?!
UPDATE:
I allocate my Class in my AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
VoiceReceiver *v __attribute__((unused)) = [[VoiceReceiver alloc] init];
....
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
VoiceReceiver *v __attribute__((unused)) = [[VoiceReceiver alloc] init];
....
}
Will not work. As soon as this callback is finished v will be dealloc'd.
If you need to use it in the appDelegate. Make the calss a property in the .h and init it where you are now.
e.g.
appDeletage.h
#property (nonatomic, strong) VoiceReceiver *voiceReciever;
appDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
voiceReciever = [[VoiceReceiver alloc] init];
....
}
The key difference here is that the appDeleagte is a singleton that will always be in memory so long as the app is running. Adding a strong property to this means it won't be removed unless the app crashes.
Related
i've the following situation.
2 identical react-native apps (differs only for bundleId, app icon etc) structured like this:
-> project structure
My goal it's to emit an event from native side to the JS layer through the bridge when a push notification has been received or tapped by the user (assuming that the app is in foreground and app has finished launching).
On the first App the following code works as expected when i trigger a push notification to my simulator with the command xcrun simctl push <device-id> <bundleId> <filename>.apns, the second app crash immediatly with the following error:
Thread 1: "Error when sending event: pushDelivered with body: <the string passed as body>. RCTCallableJSModules is not set. This is probably because you've explicitly synthesized the RCTCallableJSModules in CustomEventsEmitter, even though it's inherited from RCTEventEmitter."
-> xcode view
Here is the code implementation of RCTEventEmitter's sendEventWithName that provoke the assertion.
I don't know if it's a problem with my implementation. In 1 of the 2 apps works like a charm, in the other đź’Ą.
Anyone can help me find the problem in the code ? Probably a problem with the bridge?
i've tried many times to reinstall pods, clean project and rebuild. The code works on the project A and not on the project B.. i cannot figure out the reason
AppDelegate.h
#import <React/RCTBridgeDelegate.h>
#import <React/RCTBridgeModule.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
#import <UserNotifications/UNUserNotificationCenter.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, RCTBridgeModule, UNUserNotificationCenterDelegate>
#property (nonatomic, strong) UIWindow *window;
#property (nonatomic, strong) NSDictionary *receivedNotificationUserInfo;
#end
AppDelegate.mm
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTAppSetupUtils.h>
#import <UserNotifications/UserNotifications.h>
#import "CustomEventsEmitter.h"
#implementation AppDelegate
bool hasFinishedLaunching = false;
CustomEventsEmitter *customEventsEmitter = NULL;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
hasFinishedLaunching = true;
customEventsEmitter = [CustomEventsEmitter allocWithZone: nil];
RCTAppSetupPrepareApp(application);
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
NSDictionary *initProps = [self prepareInitialProps];
UIView *rootView = RCTAppSetupDefaultRootView(bridge, #"MyAppName", initProps);
if (#available(iOS 13.0, *)) {
rootView.backgroundColor = [UIColor systemBackgroundColor];
} else {
rootView.backgroundColor = [UIColor whiteColor];
}
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;
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:#"index"];
#else
return [[NSBundle mainBundle] URLForResource:#"main" withExtension:#"jsbundle"];
#endif
}
-(void)applicationDidBecomeActive:(UIApplication *)application
{
application.applicationIconBadgeNumber = 0;
}
// The method will be called on the delegate when the user responded to the notification by opening
// the application, dismissing the notification or choosing a UNNotificationAction. The delegate
// must be set before the application returns from applicationDidFinishLaunching:.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler {
NSLog(#"didReceiveNotificationResponse response: %#", response);
NSDictionary *userInfo = response.notification.request.content.userInfo;
if (userInfo[#"_od"]){
// if no listeners has been registered yet, store the value
// this is the case when the notification was clicked from closed app
if(![customEventsEmitter hasListeners]) {
// handle this case ...
}
// if listeners has been registered, emit an event
// this is the case when the notification was clicked from foreground app
else {
[self emitPushTappedEvent:userInfo[#"_od"]];
}
}
if (completionHandler != nil) {
completionHandler();
}
}
//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSDictionary *userInfo = notification.request.content.userInfo;
NSLog(#"User Info : %#", userInfo);
[self emitPushDeliveredEvent:userInfo[#"_od"]];
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}
-(void)emitPushDeliveredEvent:(NSString*)value {
NSLog(#"emitPushDeliveredEvent called");
[customEventsEmitter sendEventWithName:#"pushDelivered" body:value];
}
-(void)emitPushTappedEvent:(NSString*)value {
NSLog(#"emitPushTappedEvent called");
[customEventsEmitter sendEventWithName:#"pushTapped" body:value];
}
#end
And this are the CustomEventsEmitter files:
CustomEventsEmitter.h
#ifndef CustomEventsEmitter_h
#define CustomEventsEmitter_h
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
#interface CustomEventsEmitter : RCTEventEmitter <RCTBridgeModule>
- (void)sendEventName:(NSString *)eventName body:(id)body;
- (bool)hasListeners;
#end
#endif
CustomEventsEmitter.m
#import "CustomEventsEmitter.h"
#implementation CustomEventsEmitter
{
bool hasListeners;
}
RCT_EXPORT_MODULE(CustomEventsEmitter);
+ (id)allocWithZone:(NSZone *)zone {
static CustomEventsEmitter *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
- (NSArray<NSString *> *)supportedEvents {
return #[#"pushDelivered", #"pushTapped"];
}
// Will be called when this module's first listener is added.
-(void)startObserving {
hasListeners = YES;
// Set up any upstream listeners or background tasks as necessary
}
// Will be called when this module's last listener is removed, or on dealloc.
-(void)stopObserving {
hasListeners = NO;
// Remove upstream listeners, stop unnecessary background tasks
}
-(bool)hasListeners {
return hasListeners;
}
- (void)sendEventName:(NSString *)eventName body:(id)body {
if (hasListeners) {
NSLog(#"CustomEventsEmitter sendEventName emitting event: %#", eventName);
[self sendEventWithName:eventName body:body];
} else {
NSLog(#"CustomEventsEmitter sendEventName called without listeners: %#", eventName);
}
}
#end
HELP ME UNDERSTAND PLEASEEEE
Oh i've solved it!
It was a mistake of mine.
The AppModule didn't invoke the CustomEventsEmitter's methods correctly..
changing the code like below makes the events be emitted correctly through the RN bridge
-(void)emitPushDeliveredEvent:(NSString*)value {
NSLog(#"emitPushDeliveredEvent called");
[customEventsEmitter sendEventName:#"pushDelivered" body:value];
//[customEventsEmitter sendEventWithName:#"pushDelivered" body:value];
}
-(void)emitPushTappedEvent:(NSString*)value {
NSLog(#"emitPushTappedEvent called");
[customEventsEmitter sendEventName:#"pushTapped" body:value];
//[customEventsEmitter sendEventWithName:#"pushTapped" body:value];
}
I have some functions in my SecondViewController.m file and I want to call these functions when the application is launched. I have tried to do it like this, but it’s not working.
I have put a print statement in the function to see if it is getting called or not and it appears that the print statement is executed correctly.
Here is the following code:
In SecondViewController.h:
#interface AlertsManagementController : UIViewController {
PushNotificationSettings *pushNotificationSettings;
IBOutlet UISwitch *switch1;
IBOutlet UISwitch *switch2;
}
#property (nonatomic, retain) PushNotificationSettings *pushNotificationSettings;
In SecondViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (projectAppDelegate *)[[UIApplication sharedApplication] delegate];
pushNotificationSettings = [[PushNotificationSettings alloc] init];
NSDictionary * settings = [pushNotificationSettings getPushSettings];
}
-(void)modificationPush
{
if (switch1.on && switch2.on)
[switch2 setOn:NO];
printf("Function 1 executed!");
}
-(void)sendTokenFunc{
NSMutableDictionary *preferences1 = [[NSMutableDictionary alloc] init];
if (switch1.on)
[preferences1 setObject:#"1" forKey:#“switch1”];
else
[preferences1 setObject:#"0" forKey:#“switch1”];
if (switch2.on)
[preferences1 setObject:#"1" forKey:#“switch2”];
else
[preferences1 setObject:#"0" forKey:#“switch2”];
[pushNotificationSettings savePushSettingsWithDictionary:preferences1];
[preferences1 release];
[appDelegate uploadToken:[appDelegate tokenValue]];
printf("Function 2 executed!");
}
In appDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
SecondViewController * vc = [[SecondViewController alloc]init];
[vc modificationPuch];
[vc sendTokenFunc];
}
This can be done by using NSNotificationCenter.
First go to your SecondViewController.m file and in viewDidLoad write the following code.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(myNotification:) name:#"myNotification" object:nil];
Then outside viewDidLoad make a function myNotification. I will show you the eg below
-(void)myNotification:(NSNotification*)notification
{
//write the code you wanna excecute when the app opens here
}
Go to appDeligate.m and write this code in application didFinishLaunchingWithOptions
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotification" object:self userInfo:nil];
Thank you,
Happy coding;)
But if SecondViewController didn't inited, you must get EXC_BAD_ACCESS :)
hello i want to play through watchKit .i have set all things.but when i am awake parent application from watchKit on button press it awake but from playerController class i have a method to play poem. but this method is not called my code in appdelegate is below.
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply {
NSString *str=[userInfo objectForKey:#"counterValue"];
//reply(#{#"one":#"string"});
PlayerController *vc=[[PlayerController alloc] init];
if ([vc isKindOfClass:[PlayerController class]]){
if ([str isEqualToString:#"1"]) {
[vc playpoems];
NSString *theee=#"12345";
reply(#{#"one":theee});
}
}
}
in this code i got Log from reply block but only method from class is not calling...this method is properly working in class.
you are creating a new instance of viewcontroller in appdelegate.
please try with this code as i am telling.
in your .m file
#implementation PlayerController
PlayerController *selfvc;
+(PlayerController *)getInstance{
return selfvc;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
selfvc =self;
}
and in your header file
#interface PlayerController : UIViewController
+(PlayerController *)getInstance;
#end
and then in your appdelegate try with this code
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply {
NSString *str=[userInfo objectForKey:#"counterValue"];
//reply(#{#"one":#"string"});
PlayerController *vc=[PlayerController getInstance];
if ([vc isKindOfClass:[PlayerController class]]){
if ([str isEqualToString:#"1"]) {
[vc playpoems];
NSString *theee=#"12345";
reply(#{#"one":theee});
}
}
}
and then your controller function will be called.
I have NSMutableArray in "AppDelegate.h"
#property (strong, nonatomic) NSMutableArray *myArray;
and "AppDelegate.m"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.myArray = [[NSMutableArray alloc] init];
return YES;
}
In UITableViewController i add objects in NSMutableArray
- (IBAction)AddComment:(UIBarButtonItem *)sender
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
SectionObject *sectionObject = [[SectionObject alloc] init];
sectionObject.id = (NSInteger*)appDelegate.myArray.count;
sectionObject.name = [NSString stringWithFormat:#"New object %i",appDelegate.myArray.count];
[appDelegate.myArray addObject:sectionObject];
[self.tableView reloadData];
}
To edit the object I pass other UITableViewController objects from the array controller
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController *navController = segue.destinationViewController;
ExerciseTableViewController *controller = (ExerciseTableViewController *)navController;
controller.contactdb = [appDelegate.myArray objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
}
When i am going back to write
-(void)viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
self.contactdb.name = self.nameTextField.text;
}
[super viewWillDisappear:animated];
}
I receive an error 'EXC_BAD_ACCESS'. If i not edit self.contactdb.name, I dont have error. How can i edit object in other controller?
Your if-statement:
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound)
basically guarantees your view controller has already been removed from the navigation stack. That's why you get a EXC_BAD_ACCESS error when trying to access properties from that view controller. You should place your self.contactdb.name = self.nameTextField.text statement somewhere else.
I have started exploring the Dropbox API for an app that I have where I would like the user to be able to back up the database file. The problem I have run into is that after the user links the app with their account (similar to logging in via Facebook) the app doesn't return to the foreground. When I manually go back to the app it is still on the backups screen, but the account has not been linked (as best as I can tell) and the handleOpenUrl app delegate method is not called.
Any ideas? or maybe someone knows a good tutorial for this. The sample Dropbox app works fine, and I'm doing my best to use it as a guide but obviously i've messed something up.
App Delegate:
#import "AppDelegate_iPad.h"
#import <DropboxSDK/DropboxSDK.h>
#interface AppDelegate_iPad () <DBSessionDelegate>
#end
#implementation AppDelegate_iPad
#synthesize window,viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.viewController = [[mainMenuViewController alloc]init];
[window addSubview:viewController.view]; //< this is a main menu viewcontroller for my app
[self.window makeKeyAndVisible];
// Set these variables before launching the app
NSString* appKey = #"XXXX";
NSString* appSecret = #"XXX";
NSString *root = kDBRootAppFolder;
NSString* errorMsg = nil;
if ([appKey rangeOfCharacterFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]].location != NSNotFound) {
errorMsg = #"Make sure you set the app key correctly in DBRouletteAppDelegate.m";
} else if ([appSecret rangeOfCharacterFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]].location != NSNotFound) {
errorMsg = #"Make sure you set the app secret correctly in DBRouletteAppDelegate.m";
} else if ([root length] == 0) {
errorMsg = #"Set your root to use either App Folder of full Dropbox";
} else {
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"Info" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:plistPath];
NSDictionary *loadedPlist =
[NSPropertyListSerialization
propertyListFromData:plistData mutabilityOption:0 format:NULL errorDescription:NULL];
NSString *scheme = [[[[loadedPlist objectForKey:#"CFBundleURLTypes"] objectAtIndex:0] objectForKey:#"CFBundleURLSchemes"] objectAtIndex:0];
if ([scheme isEqual:#"db-APP_KEY"]) {
errorMsg = #"Set your URL scheme correctly in DBRoulette-Info.plist";
}
}
DBSession* session =
[[DBSession alloc] initWithAppKey:appKey appSecret:appSecret root:root];
session.delegate = self; // DBSessionDelegate methods allow you to handle re-authenticating
[DBSession setSharedSession:session];
[session release];
if (errorMsg != nil) {
[[[[UIAlertView alloc]
initWithTitle:#"Error Configuring Session" message:errorMsg
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil]
autorelease]
show];
}
NSURL *launchURL = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
NSInteger majorVersion =
[[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:#"."] objectAtIndex:0] integerValue];
if (launchURL && majorVersion < 4) {
// Pre-iOS 4.0 won't call application:handleOpenURL; this code is only needed if you support
// iOS versions 3.2 or below
[self application:application handleOpenURL:launchURL];
return NO;
}
return YES;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { /// this is never called
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
}
return YES;
}
return NO;
}
#end
From the main Menu, the user pressed a backup button and that opens the following view controller:
#import "BackupManagerViewController.h"
#import <DropboxSDK/DropboxSDK.h>
#import <stdlib.h>
#interface BackupManagerViewController () <DBRestClientDelegate>
//#property (nonatomic, readonly) DBRestClient* restClient;
#end
#implementation BackupManagerViewController
#synthesize itemsArray,delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
//[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
return (orientation != UIDeviceOrientationLandscapeLeft) &&
(orientation != UIDeviceOrientationLandscapeRight);
}
- (IBAction)didPressLink {
if (![[DBSession sharedSession] isLinked]) {
[[DBSession sharedSession] link];
} else {
[[DBSession sharedSession] unlinkAll];
[[[[UIAlertView alloc]
initWithTitle:#"Account Unlinked!" message:#"Your dropbox account has been unlinked"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil]
autorelease]
show];
}
}
-(DBRestClient *)restClient{
if (restClient == nil) {
restClient = [[DBRestClient alloc]initWithSession:[DBSession sharedSession]];
restClient.delegate = self;
}
return restClient;
}
-(IBAction) closeButtonPressed {
[delegate closeBackupManager];
}
#end
Things to check are
Make sure you don't have two applications with same db-APP_KEY
Make sure only one of these is implemented (not both) in your application delegate.
(a)
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
(b)
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
Option (b) is deprecated so please go with the option (a) in your new applications
You have entered correct APP_KEY in the URL scheme .
I ran into the same problem, but got it working after deleting the sample app DBRoulette from the simulator. I also deleted my own app and restarted the simulator, but I am not sure if those steps were necessary.
Did you add the drop box URL schema to your app's info.plist?
I believe this problem had to do with running in the simulator. I ran it on a device and it worked fine.