cocos2d schedule selector error - iphone

i have an error when scheduling a method. (to display how many star you get according to your score. i have addStar0 addStar1 addStar2 addStar3 methods)
[self schedule:#selector(addStar0) interval:0.2f];
and the methods are:
-(void) addstar0 {
[self unschedule:_cmd];
if (star > starProgress) {
starProgress++;
[self schedule:#selector(addStar1) interval:0.5f];
}
else {
[self schedule:#selector(displayResult) interval:0.5f];
}
}
error message:
Signature not found for selector - does it have the following form? -(void) name: (ccTime) dt
I've tried changing all my methods into addStar1: (ccTime) delta and schedule: #selector(addStar:) interval: 0.2f, but still the same. (actually i've used both ways to schedule( with/without parameter), and both of them worked well in my last project. )
also, one weird thing: sometimes i can't use [self schedule: something], but [CCScheduler sharedScheduler] schedule: something] works fine. I guess it may be project settings or so?
Please answer it with code. thank you.

You are using 'addStar0' for selector
[self schedule:#selector(addStar0) interval:0.2f];
then
-(void) addstar0 {
should be
-(void) addStar0 {

I think your error is actually on [self unschedule:_cmd];
Where is _cmd defined? Try commenting out that line and running it again.

put [self unschedule:_cmd]; after the else statement

Related

How can I change the order of iOS Kif tests?

As far as I can tell the tests in my KIFTestScenario+EXAdditions just go in alphabetical order. How can I get the tests to go in an order that I want. I would rather not simply name them like this scenarioToATestLogin.
Thanks!
We used to have that problem, but now we subclass the KifTestController, and in that controller we add our KifTestScenario's like this:
- (void)initializeScenarios {
[self addScenario:[KIFTestScenario scenarioTestMediaPlayer]];
[self addScenario:[KIFTestScenario scenarioTestVideoPlayer]];
[self addScenario:[KIFTestScenario scenarioTestSharing]];
[self addScenario:[KIFTestScenario scenarioTestContentView]];
}
Then in our AppDelegate, we start up the KiffTest's in this method:
- (void)runIntegrationTests {
[[OurTestController sharedInstance] startTestingWithCompletionBlock:^{
exit([[OurTestController sharedInstance] failureCount]);
}];
}
And our scenarios run in the order that we have added them above.

Implement game center, and "missed method" error [duplicate]

Apologies ahead of time if this is a completely off-the-mark question, or if I'm not including enough information - I'm very new to iOS development (and Objective-C), and have a habit of jumping into the deep end...
I'm having trouble understanding the "callDelegate" code in GameCenterManager.m that's in the GKTapper Sample Code and also provided in this tuts+ tutorial: http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-game-center-achievements-and-leaderboards-part-2/
This is the code:
- (void) callDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err
{
assert([NSThread isMainThread]);
if([delegate respondsToSelector: selector])
{
if(arg != NULL)
{
[delegate performSelector: selector withObject: arg withObject: err];
}
else
{
[delegate performSelector: selector withObject: err];
}
}
else
{
NSLog(#"Missed Method");
}
}
My app always logs that "Missed Method" line, but I'm not sure what this callDelegate code is actually doing (so I can't fix it). I figure the best way forward is to learn what this is actually doing, and get better output than 'Missed Method'...
One caveat is that my app is currently using Game Center in sandbox mode, since I'm still developing it. This 'Missed Method' line might be expected in this situation - I'm not sure of that, either.
Would anybody be able to translate this code into paragraph form? I'm particularly unsure about the '[delegate respondsToSelector: selector]' piece.
Alternatively, would anybody be able to rewrite the NSLog line so that it outputs more/relevant detail about the problem? I tried this in the hopes of seeing which selector is not going through 'respondsToSelector' properly, but it didn't seem to work:
NSLog(#"Missed Method, %#", selector);
T'he best way to see exactly what is happening is putting a breakpoint at the beginning of callDelegate and then debugging your program, instead of simply running it. You can debug by pressing cmd-y.
Doing like this, each time your program enters the callDelegate function, it stops and the debugger window pops up. There you will be able to inspect where the call came from and what the parameters are.
As to a plain description of this function I would say that it is an helper function that wraps a call to a selector by preceding it with a check of existence of that selector. Instead of checking each time and the performing the selector, you call the helper function that will do both things for you.
So, the reason you always see the log line is that the function you would like to call is not there. By using the debugger you will be able to see which function it is, which class is missing it, and who attempted the operation.
Some comments requested further details about what I commented out to resolve this issue. I didn't think this was good to add as an edit to the question, since it specifically goes over the resolution. It's been a while since I've worked on this project, so it's not all at the top of my head & I'm not sure I've done everything correctly ... I'll do my best to explain it, though.
In the file GameCenterManager.h, it looks like authenticateLocalUser is being initialized:
- (void) authenticateLocalUser;
In the file App_NameViewController.m, viewDidLoad is checking to see if Game Center is available:
self.currentLeaderBoard = kLeaderboardID;
if ([GameCenterManager isGameCenterAvailable]) {
self.gameCenterManager = [[[GameCenterManager alloc] init] autorelease];
[self.gameCenterManager setDelegate:self];
[self.gameCenterManager authenticateLocalUser];
} else {
// The current device does not support Game Center.
}
In the file GameCenterManager.m
- (void) authenticateLocalUser
{
if([GKLocalPlayer localPlayer].authenticated == NO)
{
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error)
{
// report any unreported scores or achievements
[self retrieveScoresFromDevice];
[self retrieveAchievementsFromDevice];
//[self callDelegateOnMainThread: #selector(processGameCenterAuth:) withArg: NULL error: error];
}];
}
}
The line that I commented out, which moved me past the Missed Method error, was:
[self callDelegateOnMainThread: #selector(processGameCenterAuth:) withArg: NULL error: error];
I hope this helps!
Add this code to Game_CenterViewController.m you will see the error
- (void)processGameCenterAuth:(NSError *)error{
NSLog(#"error %#", error);
}

Facebook loginViewFetchedUserInfo is called twice

I am using facebook SDK 3.0 in my app. The delegate method is called twice when after logging to facebook.
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
user:(id<FBGraphUser>)user {
//loginThroughFb=TRUE;
NSString *userId=[[NSString alloc] initWithString:[user id]];
[self soapCallForLogin:#"" password:#"" deviceId:#"" fbid:userId];
NSLog(#"%#",userId);
[userId release];
}
I tried 'HelloFacebookSample' project and the method is called only once.
So I guess the best solution for such case is to keep a reference to the last user object and compare it to the new object you get the next call, and if they're equal you can just ignore that call.
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user {
if (![self isUser:cachedUser equalToUser:user]) {
cachedUser = user;
/// Do something
}
}
- (BOOL)isUser:(id<FBGraphUser>)firstUser equalToUser:(id<FBGraphUser>)secondUser {
return
[firstUser.objectID isEqual:secondUser.objectID] &&
[firstUser.name isEqual:secondUser.name] &&
[firstUser.first_name isEqual:secondUser.first_name] &&
[firstUser.middle_name isEqual:secondUser.middle_name] &&
[firstUser.last_name isEqual:secondUser.last_name] &&
...
}
I also had this problem. I managed to fix it with an ugly hack, but it works. I keep a counter in the FBLoginView delegate. When the fetchedUserInfo is called, I check the counter. If it is greater than zero, return. Otherwise, do two things -
1. increment the message counter
2. Fire a delayed event that zeroes the message counter again.
So your fetchedUserInfo method will look like this:
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
user:(id<FBGraphUser>)user {
if ([self messageCounter] >0)
return;
else
{
self.messageCounter++;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
[self setMessageCounter:0];
});}
// Do whatever you were going to do }
Fixed in FB SDK 3.8 released on Sept 18 2013. The delegate methods are now called once per login regardless of how many times the repeated logging out and back in occur.
I was also able to reproduce this on FB SDK 3.7.1 and within their own sample program "Scrumptious"
As mentioned (at least for me) this only happens after:
Logging in once
Logging out
Logging back in (Now it happens)
What is interesting is the order of calls on re-logins:
On the first login I the calls I see are:
- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView;
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user;
On the 2nd (and later) logins I see:
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user;
- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView;
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user;
Which gives a handy little workaround of setting a flag in the middle method like so:
- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView {
// Set flag
self.isFirstLoginDone = YES;
}
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user {
// Check
if(self.isFirstLoginDone) {
// Execute code I want to run just once
NSLog(#"fetched");
}
// Don't forget to clear the flag (I guess it shouldn't matter if everything is cleaned up)
self.isFirstLoginDone = NO;
}
There could be another reason, which i jsut faced.
My situation:
ViewController A has a login (With fbloginview and its delegate set)
User chooses to register, moves to ViewController B with another fbloginview and its delegate set.
The above makes the delegate fire twice.
I have fixed this by setting delegate to nil on ViewWillDisappear in ViewController A.
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
fbLoginButton.delegate=self;
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
fbLoginButton.delegate=nil;
}
I used this simple trick :
(Define an int facebookCounter in your interface)
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
user:(id<FBGraphUser>)user {
if (self.facebookCounter==0) {
self.facebookCounter++;
return;
}
//Do stuff here
}
I needed to add thread safety in this method. A simple class variable did not work. The following two options will work, depending on the use case-
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView user:(id<FBGraphUser>)user {
//self.executedOnce = NO; in the init method of this class
#synchronized(self){
if(!self.executedOnce) {
//do something once per init of this class
self.executedOnce = YES;
}
}
//OR- This will only execute once in the lifetime of the app, thus no need for the executedOnce flag
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//do something once per lifetime of the app
});
}
just in the loginViewFetchedUserInfo method set the delegate of the loginView to nil. then it can never be called. and if you need the login again, set the delegate to the correct object.

What causes "Missed Method" in this code?

Apologies ahead of time if this is a completely off-the-mark question, or if I'm not including enough information - I'm very new to iOS development (and Objective-C), and have a habit of jumping into the deep end...
I'm having trouble understanding the "callDelegate" code in GameCenterManager.m that's in the GKTapper Sample Code and also provided in this tuts+ tutorial: http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-game-center-achievements-and-leaderboards-part-2/
This is the code:
- (void) callDelegate: (SEL) selector withArg: (id) arg error: (NSError*) err
{
assert([NSThread isMainThread]);
if([delegate respondsToSelector: selector])
{
if(arg != NULL)
{
[delegate performSelector: selector withObject: arg withObject: err];
}
else
{
[delegate performSelector: selector withObject: err];
}
}
else
{
NSLog(#"Missed Method");
}
}
My app always logs that "Missed Method" line, but I'm not sure what this callDelegate code is actually doing (so I can't fix it). I figure the best way forward is to learn what this is actually doing, and get better output than 'Missed Method'...
One caveat is that my app is currently using Game Center in sandbox mode, since I'm still developing it. This 'Missed Method' line might be expected in this situation - I'm not sure of that, either.
Would anybody be able to translate this code into paragraph form? I'm particularly unsure about the '[delegate respondsToSelector: selector]' piece.
Alternatively, would anybody be able to rewrite the NSLog line so that it outputs more/relevant detail about the problem? I tried this in the hopes of seeing which selector is not going through 'respondsToSelector' properly, but it didn't seem to work:
NSLog(#"Missed Method, %#", selector);
T'he best way to see exactly what is happening is putting a breakpoint at the beginning of callDelegate and then debugging your program, instead of simply running it. You can debug by pressing cmd-y.
Doing like this, each time your program enters the callDelegate function, it stops and the debugger window pops up. There you will be able to inspect where the call came from and what the parameters are.
As to a plain description of this function I would say that it is an helper function that wraps a call to a selector by preceding it with a check of existence of that selector. Instead of checking each time and the performing the selector, you call the helper function that will do both things for you.
So, the reason you always see the log line is that the function you would like to call is not there. By using the debugger you will be able to see which function it is, which class is missing it, and who attempted the operation.
Some comments requested further details about what I commented out to resolve this issue. I didn't think this was good to add as an edit to the question, since it specifically goes over the resolution. It's been a while since I've worked on this project, so it's not all at the top of my head & I'm not sure I've done everything correctly ... I'll do my best to explain it, though.
In the file GameCenterManager.h, it looks like authenticateLocalUser is being initialized:
- (void) authenticateLocalUser;
In the file App_NameViewController.m, viewDidLoad is checking to see if Game Center is available:
self.currentLeaderBoard = kLeaderboardID;
if ([GameCenterManager isGameCenterAvailable]) {
self.gameCenterManager = [[[GameCenterManager alloc] init] autorelease];
[self.gameCenterManager setDelegate:self];
[self.gameCenterManager authenticateLocalUser];
} else {
// The current device does not support Game Center.
}
In the file GameCenterManager.m
- (void) authenticateLocalUser
{
if([GKLocalPlayer localPlayer].authenticated == NO)
{
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error)
{
// report any unreported scores or achievements
[self retrieveScoresFromDevice];
[self retrieveAchievementsFromDevice];
//[self callDelegateOnMainThread: #selector(processGameCenterAuth:) withArg: NULL error: error];
}];
}
}
The line that I commented out, which moved me past the Missed Method error, was:
[self callDelegateOnMainThread: #selector(processGameCenterAuth:) withArg: NULL error: error];
I hope this helps!
Add this code to Game_CenterViewController.m you will see the error
- (void)processGameCenterAuth:(NSError *)error{
NSLog(#"error %#", error);
}

UIAlertView clickedButtonAtIndex EXC_BAD_ACCESS

I currently have a UIAlertView being shown with two option buttons. When the user presses one of the buttons, I would like a method (in the same object) to be called that would then retrieve a file from the web.
I can call the method fine and can call NSLog(), but as soon as I come to use any object variables, I get an EXC_BAD_ACCESS error.
My first thought was it could be a threading issue, so thought calling NSNotificationCenter might solve it, but that too ends in the same error.
Below is the code I've got at the moment. I have tried a few different things (some are commented out) to no avail. The 'dbURL' object is a property of the class. (Edit: below code is not complete)
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
//If database update
[[NSNotificationCenter defaultCenter] postNotificationName:#"newdb" object:self]; //EXC_BAD_ACCESS happens here
if ([alertView.title isEqualToString: #"Database Update"]){
switch (buttonIndex) {
case 0:
//[self getNewDatabase];
//[self performSelectorOnMainThread:#selector(getNewDatabase) withObject:nil waitUntilDone:NO];
//[NSThread detachNewThreadSelector:#selector(getNewDatabase) toTarget:self withObject:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"newdb" object:self];
break;
// Get a new database file from the server
- (void)getNewDatabase{
NSLog(#"in database: %#", dbURL);
}
Thanks in advance!
The problem was an object I was calling as not being retained properly and therefore the reference was lost, resulting in an EXC_BAD_ACCESS error
Thanks to Nick Weaver. Using the NSZombieEnabled argument in the build options helped to identify the rogue reference.
You can't compare NSString with == . You need to use isEqualToString:
[alertView.title isEqualToString:#"Database Update"]