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
}
}
Related
I am confused about these delegate method calls.
Which one is the correct way of calling the delegate method?
#protocol XYZDelegate <NSObject>
#required
- (void)someMethod:(id)someObject;
#end
method 1:
- (void)someButtonAction:(UIButton *)sender {
if([self.delegate && [self.delegate respondsToSelector:#selector(someMethod:)]]) {
[self.delegate someMethod:sender];
}
}
method 2:
- (void)someButtonAction:(UIButton *)sender {
if([self.delegate && [self.delegate respondsToSelector:#selector(someMethod:)]]) {
[self.delegate performSelector:#selector(someMethod:) withObject:sender];
}
}
They are both pretty much the same. They will result in the same outcome.
The second is slightly less efficient.
What I would change is the line...
if([self.delegate && [self.delegate respondsToSelector:#selector(someMethod:)]]) {...
The method someMethod: is required by the protocol.
So you can remove it completely...
- (void)someButtonAction:(UIButton *)sender {
[self.delegate someMethod:sender];
}
And it will still work. You can send a message to nil and it just won't do anything. If the delegate is not nil then by definition it will respond to the selector.
If the delegate object does not conform to the method then you will get a compiler error (or maybe just a warning?).
Anyway, that should suffice.
Just as a side note. I personally prefer the first method and if there is more than one parameter then you would have to call it that way to be able to pass the parameters in corrcetly.
The difference is one calls the delegate method directly, while the other uses the runtime, through performSelector, to do so dynamically.
The latter is less efficient and pointless, but the results are the same.
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.
I am working on an app and I got stuck at the point where I can't seem to retrieve the value of a BOOL set in a class.
I spent too much time already on it, been through all the questions I found that seem to cover the matter.
The bad thing here is that I get something, but not what I need (I get a 0, which means, I guess, that the value wasn't retrieved correctly as it should be 1).
The things I tried are :
pass a pointer to my first class and access to my BOOL like this:
//in some method
self.pointerFirstClass.myBOOL;
NSLog(#"%d", firstClass.myBOOL); => This gives 0!
by declaring it (talking of the pointer) as a property in my second class (and importing the h. file from my first class, where my BOOL is declared as property too):
#property FirstClass *pointerFirstClass;
But I got 0 using this.
The other shot I gave was add my BOOL in the first class and create an instance of the class in my second class
//in some method
FirstClass *firstClass = [[FirstClass alloc] init];
if (firstClass.myBOOL){
//Do something
}
NSLog(#"%d", firstClass.myBOOL); => This gives 0!
But I got 0 too.
As Booleans are primitive types, like in C, I get a bit confused since I am new to object-oriented programming, I don't know how I could like create a getter for this, for example.
I also tried to do a - (BOOL)getBOOLValue method in my first class, and call this method in my second class and assign it to a BOOL in that second class.
But the result wasn't better.
Am I missing something?
Is there a way to get my value that I didn't think of or didn't know about yet?
I am running low on thoughts on how to get around this, it shouldn't be that hard IMO so I hope it is something simple that I just left aside.
EDIT :
Some actual code. I am working between 2 files called AppDelegate (yes, the actual one) and WelcomeViewController (so a VC).
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
BOOL inRegion; //thought of this making my BOOL as a property of AppDelegate
}
#property (strong, nonatomic) UIWindow *window;
#property BOOL inRegion; //Declaring my BOOL here to make it accessible for another class
- (BOOL)getBOOLValue; //An attempt to pass my BOOL value
AppDelegate.m
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
if (state == CLRegionStateInside)
{
self.inRegion = YES; //Set my BOOL to TRUE
}
else if (state == CLRegionStateOutside)
{
self.inRegion = NO; //Else set it to False
}
- (BOOL)getBOOLValue
{
return inRegion; //Tried to create a custome "getter"
}
WelcomeViewControler.m (I changed nothing in the .h file)
I said I tried many things, right now, this is the last version of my code.
//Simply trying to do a Segue on a condition...
- (IBAction)onClick:(id)sender {
AppDelegate *appDelegate = [[AppDelegate alloc] init];
if (appDelegate.inRegion) {
[self performSegueWithIdentifier:#"WelcomeToDetection" sender:self];
}
else
{
//Do Nothing
}
}
As said, I want to retrieve the BOOL value of the AppDelegate.
Thank you.
This code doesn't make sense:
self.pointerFirstClass.myBOOL;
NSLog(#"%d", firstClass.myBOOL); => This gives 0!
The first line doesn't do anything. You're not assigning anything to the property, and you're not doing anything with the value. Furthermore, the second line doesn't relate to the first line in any way that we can see from the code you've provided. Try this instead:
self.pointerFirstClass = [[FirstClass alloc] init];
self.pointerFirstClass.myBOOL = YES;
NSLog(#"myBOOL = %d", self.pointerFirstClass.myBOOL);
In other words, you need to be sure that self.pointerFirstClass points to a valid object. And then you need to make sure that you've assigned the value you want to the myBOOL property of that object.
Update: This looks like a case where you're talking to the wrong object. Look at this:
- (IBAction)onClick:(id)sender {
AppDelegate *appDelegate = [[AppDelegate alloc] init];
This is surely not what you really want. The application object is a single object -- a real singleton, in fact, meaning that there is and can be only one application object. That object has a delegate object, and that's a specific instance of your AppDelegate class. In this code, though, you're creating a new instance of AppDelegate, one that's different from the one that the application is using. Any changes that are made to the actual application delegate in response to messages from the application will not be reflected in the new object that you've created.
What I think you want is to get the actual application delegate object, and you can do that using:
[[UIApplication sharedApplication] delegate];
So, change your code to look like this:
- (IBAction)onClick:(id)sender {
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];;
if (appDelegate.inRegion) {
[self performSegueWithIdentifier:#"WelcomeToDetection" sender:self];
}
// note: you don't need an else clause if it doesn't do anything
}
That way, you'll be talking to the same object that the app uses, which is the one that has the inRegion property set in response to the location manager call.
UPDATE - Now we can see your code the problem is obvious, you are trying to access the appDelegate by creating a new one...
- (IBAction)onClick:(id)sender {
AppDelegate *appDelegate = [[AppDelegate alloc] init];
Instead you should be doing this....
- (IBAction)onClick:(id)sender {
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]
--
Not sure if you are posting your actual code? but the first example you give...
self.pointerFirstClass.myBOOL;
NSLog(#"%d", firstClass.myBOOL); => This gives 0!
Shouldn't the second line be
NSLog(#"%d", self.pointerFirstClass.myBOOL);
Also this property...
#property FirstClass *pointerFirstClass;
Won't retain it once you've set it, it needs to be
#property (nonatomic,strong) FirstClass *pointerFirstClass;
In the second example...
FirstClass *firstClass = [[FirstClass alloc] init];
if (firstClass.myBOOL){
//Do something
}
NSLog(#"%d", firstClass.myBOOL); => This gives 0!
You allocate and initialise a new FirstClass object and then check the property straight away, if you are not setting this to YES in the init then it will be false
Like I say, maybe you're not posting your actual code?
I guess what you want is initializing myBOOL to 1.
If so, you need do something as following
#implement FirstClass
- (id)init
{
self = [super init];
if(self) {
_myBOOL = 1;
}
return self;
}
// Other methods
#end
EDIT:
The comments is why you get 0.
- (IBAction)onClick:(id)sender {
AppDelegate *appDelegate = [[AppDelegate alloc] init]; // this is the problem.
// you create a new appdelegate,
// and never call locationManager:didDetermineState:forRegion:
if (appDelegate.inRegion) {
[self performSegueWithIdentifier:#"WelcomeToDetection" sender:self];
}
else
{
//Do Nothing
}
}
rewrite your code as following:
- (IBAction)onClick:(id)sender {
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
if (appDelegate.inRegion) {
[self performSegueWithIdentifier:#"WelcomeToDetection" sender:self];
}
else
{
//Do Nothing
}
}
OK, real quick question, if I want to pass a view controller in a method, which would be the correct way(apparently, both seem to work) -
-(void)fetchedDataN:(UIViewController *)response
or
-(void)fetchedDataN:(ViewController *)response
EDIT: Here is the Complete Code to clarify things
- (IBAction)nextButton:(id)sender {
activityN.hidden=NO;
[activityN startAnimating];
[self.view bringSubviewToFront:activityN];
[audioFile stop];
NSLog(#"HELL O");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
Page04ViewController *viewControl=[[Page04ViewController alloc]initWithNibName:nil bundle:nil];
[self performSelectorOnMainThread:#selector(fetchedDataN:)
withObject:viewControl waitUntilDone:YES];
}); }
-(void)fetchedDataN:(UIViewController *)response{
if ([self interfaceOrientation] == UIDeviceOrientationLandscapeLeft) {
[self presentViewController:response withPushDirection:#"fromTop"];
// NSLog(#"landscape left");
}
else if([self interfaceOrientation] == UIDeviceOrientationLandscapeRight)
{
[self presentViewController:response withPushDirection:#"fromBottom"];
// NSLog(#"landscape right");
} }
Presumably ViewController is a subclass of UIViewController...
If you try to pass a UIViewController to the second method, that won't work (the compiler will complain) because it can't guarantee that the instance you're passing is of the correct class.
If you try to pass ViewController to the first method that will work because the compiler can make the guarantee.
The correctness of the method definition depends on your intentions - without knowing that, neither and both are correct, they are just different...
For your updated question, if the method is only presenting the view controller then using UIViewController can be considered correct as it is the most generic and flexible option. If you wanted to change the method in future to add other features which require response to be a specific subclass then the compiler will tell you that it can't guarantee the class is of the correct type.
This is right:
-(void)fetchedDataN:(UIViewController *)response.
Then you can
-(void)fetchedDataN:(UIViewController *)response
{
if ([controller isKindOfClass:[ViewControllerSubclass class]])
{
//The controller is a ViewControllerSubclass or a subclass of ViewControllerSubclass your code here
}
if ([controller isKindOfClass:[MyViewControllerSubclass class]])
{
//The controller is a MyViewControllerSubclass or a subclass of MyViewControllerSubclass your code here
}
}
If you want to pass a UIViewController; use the first method.
I never heard of the type 'ViewController'. It it your own type? If you always want to be sure the passed variable is of type 'ViewController', use the second method.
It depends if you want to pass only ViewController and/or it's descendants or UIViewController and all of it's descendants. UIViewController will be more generic way as (I assume) ViewController is subclass of UIViewController and probably you won't extend ViewController anymore. Everything depends on context and if you need to use any specific method/property defined in ViewController or you just want to receive any view controller subclassing UIViewController.
A pretty simple question, but I can't seem to find an answer. (Developing an iOS 5+ app).
In my AppDelegate, I have a property, let's call it #property (non atomic) BOOL aFlag;. I'd like my AppDelegate to be notified if the value changes. Here is what I tried (everything happens in the AppDelegate.m), which is the same as when I "link" two different objects with an observer :
-(BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
// Some stuff
_aFlag = YES;
[self addObserver:self
forKeyPath:#"aFlag"
options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context:nil];
// Some other stuff
}
-(void)observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void*)context {
if ([keyPath isEqual:#"aFlag"]) {
// Do something
} else {
// Do nothing
}
}
But observeValueForKeyPath: is not called.
Where am I wrong ? Thanks.
You should implement your own setter. In that setter you know the poperty has changed.
It's more optimised that way. Much better and less expensive then doing KVO on yourself.
Your solution works, technically you can KVO yourself.
But, imagine if you started using NSNotificationCenter for triggering methods in you class from inside your class? Can it be done? Yes. Should it be? Probably not. You may have a scenario where it's okay but not in a clean object oriented solution. You should be messaging self for this.
Well it's the same here. Implement this:
- (void)setAFlag:(BOOL)flag;
For example:
- (void)setAFlag:(BOOL)flag{
BOOL valueChanged = NO;
if(_aFlag != flag){
valueChanged = YES;
}
_aFlag = flag;
if(valueChanged)
[self doSomethingWithTheNewValueOfFlag];
}