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 hope开发者_运维技巧s 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);
}
精彩评论