Cordova iOS : Add method call in AppDelegate.m - ios

I am building an app with cordova/ionic for iOS
For multiple reasons we have to put code inside generated application() of AppDelegate.m.
I allready found some similar question, but no answer yet.
https://stackoverflow.com/questions/36792158/cordova-phonegap-ios-modify-generated-appdelegate
There is a way to do it properly with some overloading or extending ?
The simple answer is "I can edit the AppDelegate.m" but since it's a generated file in the project, i can not do it.
Any ideas ?

Maybe you can use runtime to add new method in AppDelegate.m
for example
#interface testViewController (){
AppDelegate *m_appDelegate;
}
#implementation testViewController
- (void)viewDidLoad {
[super viewDidLoad];
m_appDelegate = [AppDelegate new];
// add new method in AppDelegate.m
[self addMethod];
// call new method in AppDelegate.m
[m_appDelegate performSelector:#selector(join)];
}
- (void)addMethod{
BOOL addSuccess = class_addMethod([AppDelegate class], #selector(join), (IMP)happyNewYear, "v#:");
}
void happyNewYear(id self,SEL _cmd){
NSLog(#"new method");
}
-(void)join{
NSLog(#"in the join %s",__func__);
}
hope it helps.

Related

pebbleCentral:watchDidConnect never gets called on iOS

I have an old Pebble Classic watch, upgraded to latest firmware (3.8.2) and using latest Pebble-SDK.
I have followed the few simple steps to install SDK, setup an Xcode project and adding the code to initialise and connect:
https://developer.getpebble.com/guides/mobile-apps/ios/
My problem is, that the delegate method pebbleCentral:watchDidConnect never gets called!
I am using the Pebble Time app on the iPad to install the watchApp in the watch, so I know the iPad is connected to the watch. The same iPad runs the iOS app, which apparently does not discover the watch.
I have tried to import an old test project from a colleague, who had it running a year or two ago. Same watch, same watchApp, but of course older firmware and SDK versions. Same result...
I think the documentation on the pebble site is quite simple and easy to follow. However, I feel I am missing some explanations of how and when this watchDidConnect is supposed to be triggered.
I am most likely missing some simple step somewhere, but I am quite lost in where to look!
Any ideas are welcome!
EDIT: My code looks like this:
ViewController.h:
#import <UIKit/UIKit.h>
#import PebbleKit;
#interface ViewController : UIViewController<PBPebbleCentralDelegate>
#end
ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#property (weak, nonatomic) PBWatch* connectedWatch;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[PBPebbleCentral defaultCentral].delegate = self;
[[PBPebbleCentral defaultCentral] run];
NSLog(#"Pebble initialised");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)pebbleCentral:(PBPebbleCentral*)central watchDidConnect (PBWatch*)watch isNew:(BOOL)isNew {
NSLog(#"Pebble connected: %#", [watch name]);
self.connectedWatch = watch;
}
- (void)pebbleCentral:(PBPebbleCentral*)central watchDidDisconnect:(PBWatch*)watch {
NSLog(#"Pebble disconnected: %#", [watch name]);
if ([watch isEqual:self.connectedWatch]) {
self.connectedWatch = nil;
}
}
#end
Are you calling the -run method, after setting up your Pebble central? I noticed that the code snippet in the link you posted does not show the central's delegate being set.
[PBPebbleCentral defaultCentral].delegate = self; // Set your delegate
[PBPebbleCentral defaultCentral].appUUID = [[NSUUID alloc] initWithUUIDString:#"Your Pebble App UUID"]; // Set the app UUID
[[PBPebbleCentral defaultCentral] run]; // Call -run on the central

Bridge is nil when calling methods on React Native bridge, use a singleton?

I am working through creating my own custom component, to interact with a Bluetooth device. I tried this in Swift, but didn't get anywhere due to problems with accessing the bridge.
I reimplemented it in Objective-C and experienced the same problem (bridge = nil). To fix it, I used:
BTAdapter.h
#import "RCTBridgeModule.h"
#interface BTAdapter : NSObject<RCTBridgeModule>
- (void)sendEvent:(NSString *)name;
#end
BTAdapter.m
#import "BTAdapter.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#implementation BTAdapter
RCT_EXPORT_MODULE()
#synthesize bridge = _bridge;
+ (id)allocWithZone:(NSZone *) zone
{
static BTAdapter *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
- (void)sendEvent:(NSString *)name
{
NSLog(#"Received generic event in the bridge");
if (self.bridge == nil) {
NSLog(#"Bridge is nil"); // This happens normally
} else {
NSLog(#"Bridge is NOT nil"); // This happens with a singleton
}
[self.bridge.eventDispatcher sendAppEventWithName:name body:#"Event from the bridge"];
}
Add to my Bridging-Header.h:
#import "BTAdapter.h"
And I'm calling it in Swift like:
let adapter: BTAdapter = BTAdapter()
adapter.sendEvent("TestEvent")
Is this a bad thing to do? I followed a pretty outdated React Native GitHub issue on a similar topic, but there wasn't a whole lot of certainty surrounding this solution. This seems to suggest it's not a good idea at all.
What is wrong here?
I had this problem until I removed my own initializer code. If you need configuration, I recommend you use RCT_EXPORT_METHOD to call in and prepare your module.

How do I use my app delegate

I have a method called "pauseGame:" that pauses the game and a method called "resumeGame:"
I was wondering how I would call these in my app delegate I tried a few ways but in my debugger it ended up saying "pauseGame: method not found" and i imported my class i declared them in into my app delegate I was trying to figure out how I could solve this.
Here is the code I used for it:
- (void)applicationWillResignActive:(UIApplication *)application
{
[BPGameController pauseGame:];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[BPGameController pauseGame:];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[BPGameController resumeGame:];
}
Try this. and make sure the method resumeGame is working fine.
- (void)applicationDidBecomeActive:(UIApplication *)application {
[super applicationDidBecomeActive:application];
[BPGameController resumeGame:];
}
if resumeGame doesnt take any param it should just be
[BPGameController resumeGame];
lose the ":"
Are your pause/resume methods class methods or instance methods, in your code example it looks like you're calling them as class methods. Can you post more concrete code?
Signatures would help.
If those methods are instance methods, what you can do is add a property to YourAppDelegate, where it might look like:
#property (nonatomic, strong) BPGameController *bpgc;
And then when you instantiate the BPGameController somewhere else, set it on the appdelegate by doing
[(*YourAppDelegate)[[UIApplication sharedApplication] delegate] setBpgc:yourBPGC];
and then in the app delegate methods, you can reference your bpgc by self.bpgc and send messages like pauseGame, etc.
First your code is syntatically incorrect.AS
[BPGameController pauseGame:]; //do not call pauseGame: wihout any parameter.
instead consider calling it with nil if you do not have any value
[BPGameController pauseGame:nil];
or
If you function do not need parameters than remove from method definition.
Secondly I suspect you do not have pauseGame: declared in .h file
declare it in .h file.If not
Third if you want to call pauseGame this way[BPGameController pauseGame:nil]; than your method definition should start with + instead of - something like this.
+(void)pauseGame:(id)param{
}
If you post the definition of pauseGame: it will help more
EDIT: USE
- (void)applicationWillResignActive:(UIApplication *)application{
UIViewController *controller = self.window.rootViewController;
if([controller isKindOfClass:[UINavigationController class]]){
BPGameController *bpGameController;
for (id vc in [((UINavigationController*)controller) viewControllers])
{
if ([vc isKindOfClass:[BPGameController class]])
{
[((BPGameController *) vc) pauseGame];
break;
}
}
}
else if([controller isKindOfClass:[BPGameController class]]){
[((BPGameController *) controller) pauseGame];
}else{
//Not found
}
}

Detect frequency value using iPhone

I'm developing an app that should detect a frequency of a certain sound. I based my app on Pitch Detector. I imported the files that are in the Pitch Detector example, then I fixed my code to accept this new classes. I post here my code to explain you my issue:
ViewController.h
#import <UIKit/UIKit.h>
#class RIOInterface;
#interface ViewController : UIViewController {
BOOL isListening;
float currentFrequency;
RIOInterface *rioRef; // HERE I'M GETTING ISSUE
}
- (IBAction)startListenWatermark:(UIButton *)sender;
#property(nonatomic, assign) RIOInterface *rioRef;
#property(nonatomic, assign) float currentFrequency;
#property(assign) BOOL isListening;
#pragma mark Listener Controls
- (void)startListener;
- (void)stopListener;
- (void)frequencyChangedWithValue:(float)newFrequency;
#end
ViewController.m
#synthesize isListening;
#synthesize rioRef;
#synthesize currentFrequency;
- (IBAction)startListenWatermark:(UIButton *)sender {
if (isListening) {
[self stopListener];
} else {
[self startListener];
}
isListening = !isListening;
}
- (void)startListener {
[rioRef startListening:self];
}
- (void)stopListener {
[rioRef stopListening];
}
- (void)frequencyChangedWithValue:(float)newFrequency {
NSLog(#"FREQUENCY: %f", newFrequency);
}
In the code you can see where's my issue and Xcode says: Existing instance variable 'rioRef' with assign attribute must be __unsafe_unretained. If I delete the row that give this errore the app doesn't calls the method [rioRef startListening:self]; and [rioRef stopListening];.
In the file RIOInterface.mm I'm getting another error in line 97 and Xcode suggested me to change it from:
RIOInterface* THIS = (RIOInterface *)inRefCon; --> RIOInterface* THIS = (RIOInterface *)CFBridgingRelease(inRefCon);
The it gives me this other error on the line 283:
callbackStruct.inputProcRefCon = self;
It says me this: Assigning to 'void' from incompatible type 'RIOInterface *const__strong', so I looked to the web and I found this solution:
callbackStruct.inputProcRefCon = (__bridge void*)self;
I'm not sure if it's right to do so or not, I hope you can help me to solve this issues, thank you in advice.
For the 2nd and the 3rd problem I solved by disabling the ARC for the file in which there are the code I provided above. For the first problem I solved by writing this code:
rioRef = [RIOInterface sharedInstance];

Variable lost after dismissing modalViewController

I'm using Reachability in my iPad app and discovered some issues when using modalViewControllers.
In my mainViewController I have a BOOL variable determining weather I'm online or not. Here's my code:
// mainViewController.h
BOOL online;
// mainViewController.m
- (void)reachabilityChanged:(NSNotification *)note
{
if([[note object] isReachable]) {
online = YES;
}
else {
online = NO;
}
}
- (void)getOnline
{
NSLog(#"%d", online);
}
// modalViewController.m
#import "mainViewController.h"
- (IBAction)dismissMe
{
mainViewController *main = [[mainViewController alloc] init];
[main getOnline];
[self dismissModalViewControllerAnimated:YES];
}
When I'm calling [self getOnline] within the mainViewController, it returns 1 ('cause I am online).
But: when I'm calling [main getOnline] within the modalViewController, it returns 0 in the log.
Does anybody know why?!
I also tried to put the online variable as a #property into the modalViewController to handle the if online stuff within the modal. But when I assign a value to it (from the main), and log it within the modal, it always returns (NULL).
Hope, you can help me! With best regards, Julian
Short answer: because they use different instances of the online variable.
Long answer: you should only declare BOOL online in the header, not define it. Defining should happen in the .m file, like this:
In the mainViewController.h:
extern BOOL online; // Declare the variable
In the mainViewController.m:
BOOL online; // Define the variable
// the rest of your code
The way your code is written, a separate BOOL online is created for each .m file that includes mainViewController.h; I am sure this is not what you intended.

Resources