我正在将实时游戏中心应用到我的游戏中,我在呈现GKMatchmakerViewController
时遇到问题。这是我的情况:
有一个HomeViewController,我在其中提供GameViewController
下一个代码:
GameViewController *gameViewController = [[GameViewController alloc] initWithNibName:@"GameViewController" bundle:nil];
gameViewController.delegate = self;
[self presentViewController:gameViewController animated:NO completion:nil];
然后在GameViewController
我加入GCHelper
并致电游戏中心开始比赛:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[GCHelper sharedInstance] authenticateLocalUser];
[[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController:self delegate:(id)self];
}
问题在于,我再次回到游戏中心的小警报显示:
但是没有显示游戏中心的大窗口。我确信问题在于我正在提出GameViewController
。
我该如何解决这个问题?
更新:
当我尝试在HomeViewConroller中调用Game Center时,一切都很完美。
更新2(已尝试): 我尝试了GCHelper:
[presentingViewController presentViewController:mmvc animated:YES completion:nil];
使用:
AppDelegate * appdelegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
[appdelegate.homeViewController presentViewController:mmvc animated:YES completion:nil];
然后我收到错误: 其视图不在窗口层次结构中!
答案 0 :(得分:2)
GCHelper.h
//
// GCHelper.h
// KvK
//
// Created by Kalim on 11/22/12.
//
//
#import <Foundation/Foundation.h>
#import <GameKit/Gamekit.h>
@interface GCHelper : NSObject<GKMatchmakerViewControllerDelegate, GKMatchDelegate>
{
BOOL isUserAuthenticated;
UIViewController *presentingViewController;
GKMatch *match;
BOOL matchStarted;
GKInvite *pendingInvite;
NSArray *pendingPlayersToInvite;
NSMutableDictionary *playersDict;
NSString *MultiplayerID;
NSData *MultiData;
NSString *otherPlayerID;
char AlertMessageBoxNo;
BOOL isDataRecieved;
}
//variables
@property (assign, readonly) BOOL gameCenterAvailable;
@property (retain) UIViewController *presentingViewController;
@property (retain) GKMatch *match;
@property (retain) GKInvite *pendingInvite;
@property (retain) NSArray *pendingPlayersToInvite;
@property (retain) NSMutableDictionary *playersDict;
@property (retain) NSString *MultiplayerID;
@property (retain) NSData *MultiData;
-(NSString*)getOtherPlayerId;
-(void)setOtherPlayerId;
//Functions
+ (GCHelper *)sharedInstance;
-(BOOL)isGameCenterAvailable;
-(void)authenticationChanged;
-(void)authenticateLocalUser;
-(void)gameOver:(NSString*)message;
-(void)setDataRecieved:(BOOL)d;
-(BOOL)getDataRecieved;
- (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController;
@end
GCHelper.mm
//
// GCHelper.m
// KvK
//
// Created by Kalim on 11/22/12.
//
//
#import "GCHelper.h"
#import "IPadSharebleClass.h"
@implementation GCHelper
@synthesize gameCenterAvailable;
@synthesize presentingViewController;
@synthesize match;
@synthesize pendingInvite;
@synthesize pendingPlayersToInvite;
@synthesize playersDict;
@synthesize MultiData;
@synthesize MultiplayerID;
static GCHelper *sharedHelper = nil;
+(GCHelper *) sharedInstance
{
if (!sharedHelper)
{
sharedHelper = [[GCHelper alloc] init];
}
return sharedHelper;
}
- (BOOL)isGameCenterAvailable
{
Class gcClass = (NSClassFromString(@"GKLocalPlayer"));
NSString *reqSysVer = @"4.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending);
return (gcClass && osVersionSupported);
}
- (id)init
{
if ((self = [super init]))
{
gameCenterAvailable = [self isGameCenterAvailable];
if (gameCenterAvailable)
{
NSNotificationCenter *nc =
[NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(authenticationChanged)
name:GKPlayerAuthenticationDidChangeNotificationName
object:nil];
}
else
{
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"Game Center Alert" message:@"Game Center Not Available" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
}
return self;
}
-(void)authenticationChanged
{
if ([GKLocalPlayer localPlayer].isAuthenticated && !isUserAuthenticated)
{
NSLog(@"Authentication changed: player authenticated.");
isUserAuthenticated = TRUE;
[GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite)
{
NSLog(@"Received invite");
self.pendingInvite = acceptedInvite;
self.pendingPlayersToInvite = playersToInvite;
IPadCallAnyWhereF.inviteReceived();
};
}
else if (![GKLocalPlayer localPlayer].isAuthenticated && isUserAuthenticated)
{
NSLog(@"Authentication changed: player not authenticated");
isUserAuthenticated = FALSE;
}
}
- (void)authenticateLocalUser
{
if (!gameCenterAvailable) return;
NSLog(@"Authenticating local user...");
if ([GKLocalPlayer localPlayer].authenticated == NO)
{
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:nil];
}
else
{
NSLog(@"Already authenticated!");
}
}
-(void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController
{
if (!gameCenterAvailable) return;
matchStarted = NO;
self.match = nil;
self.presentingViewController = viewController;
if (pendingInvite != nil)
{
[presentingViewController dismissModalViewControllerAnimated:NO];
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:pendingInvite] autorelease];
mmvc.matchmakerDelegate = self;
[presentingViewController presentModalViewController:mmvc animated:YES];
self.pendingInvite = nil;
self.pendingPlayersToInvite = nil;
}
else
{
[presentingViewController dismissModalViewControllerAnimated:NO];
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = minPlayers;
request.maxPlayers = maxPlayers;
request.playersToInvite = pendingPlayersToInvite;
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = self;
[presentingViewController presentModalViewController:mmvc animated:YES];
self.pendingInvite = nil;
self.pendingPlayersToInvite = nil;
}
}
#pragma mark GKMatchmakerViewControllerDelegate
- (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController *)viewController
{
[presentingViewController dismissModalViewControllerAnimated:YES];
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"Game Center Alert" message:@"Game Cancel By you" delegate:self cancelButtonTitle:@"Try Again" otherButtonTitles:@"Main Menu", nil];
[alert show];
[alert release];
AlertMessageBoxNo='E';
}
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error
{
[presentingViewController dismissModalViewControllerAnimated:YES];
NSLog(@"Error finding match: %@", error.localizedDescription);
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"Game Center Alert" message:@"Connection Time out" delegate:self cancelButtonTitle:@"Try Again" otherButtonTitles:@"Main Menu", nil];
[alert show];
[alert release];
AlertMessageBoxNo='A';
}
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)theMatch
{
[presentingViewController dismissModalViewControllerAnimated:YES];
self.match = theMatch;
match.delegate = self;
if (!matchStarted && match.expectedPlayerCount == 0)
{
NSLog(@"***************Ready to start match!**************");
[self lookupPlayers];
}
}
- (void)lookupPlayers
{
NSLog(@"Looking up %d players...", match.playerIDs.count);
[GKPlayer loadPlayersForIdentifiers:match.playerIDs withCompletionHandler:^(NSArray *players, NSError *error)
{
if (error != nil)
{
NSLog(@"Error retrieving player info: %@", error.localizedDescription);
matchStarted = NO;
//IPadCallAnyWhereF.matchEnded();
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"Game Center Alert" message:@"Error retrieving player info" delegate:self cancelButtonTitle:@"Try Again" otherButtonTitles:@"Main Menu", nil];
[alert show];
[alert release];
AlertMessageBoxNo='F';
}
else
{
self.playersDict = [NSMutableDictionary dictionaryWithCapacity:players.count];
for (GKPlayer *player in players)
{
NSLog(@"Found player: %@", player.alias);
[playersDict setObject:player forKey:player.playerID];
}
NSLog(@"Total Number of Players : %d",players.count);
matchStarted = YES;
IPadCallAnyWhereF.matchStarted();
}
}];
}
#pragma mark GKMatchDelegate
- (void)match:(GKMatch *)theMatch didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID
{
if (match != theMatch) return;
MultiData=data;
MultiplayerID=playerID;
if(otherPlayerID==nil)
{
otherPlayerID=[playerID retain];
}
IPadCallAnyWhereF.match();
}
-(void)setDataRecieved:(BOOL)d
{
isDataRecieved=d;
}
-(BOOL)getDataRecieved
{
return isDataRecieved;
}
-(NSString*)getOtherPlayerId
{
return otherPlayerID;
}
-(void)setOtherPlayerId
{
otherPlayerID=nil;
}
- (void)match:(GKMatch *)theMatch player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state
{
if (match != theMatch) return;
switch (state)
{
case GKPlayerStateConnected:
NSLog(@"New Player connected!");
if (!matchStarted && theMatch.expectedPlayerCount == 0)
{
NSLog(@"&&&&&&&&&& Ready to start match in the match!");
[self lookupPlayers];
}
break;
case GKPlayerStateDisconnected:
NSLog(@"--------Player disconnected!--------");
matchStarted = NO;
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"Game Center Alert" message:@"Player Disconnected" delegate:self cancelButtonTitle:@"Try Again" otherButtonTitles:@"Main Menu", nil];
[alert show];
[alert release];
AlertMessageBoxNo='B';
//IPadCallAnyWhereF.matchDisconnect();
break;
}
}
- (void)match:(GKMatch *)theMatch connectionWithPlayerFailed:(NSString *)playerID withError:(NSError *)error
{
if (match != theMatch) return;
NSLog(@"Failed to connect to player with error: %@", error.localizedDescription);
matchStarted = NO;
//IPadCallAnyWhereF.matchEnded();
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"Game Center Alert" message:@"Failed to connect to player" delegate:self cancelButtonTitle:@"Try Again" otherButtonTitles:@"Main Menu", nil];
[alert show];
[alert release];
AlertMessageBoxNo='C';
}
- (void)match:(GKMatch *)theMatch didFailWithError:(NSError *)error
{
if (match != theMatch) return;
NSLog(@"Match failed with error: %@", error.localizedDescription);
matchStarted = NO;
//IPadCallAnyWhereF.matchEnded();
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"Game Center Alert" message:@"Match failed" delegate:self cancelButtonTitle:@"Try Again" otherButtonTitles:@"Main Menu", nil];
[alert show];
[alert release];
AlertMessageBoxNo='D';
}
-(void)gameOver:(NSString*)message
{
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"Game Center Alert" message:message delegate:self cancelButtonTitle:@"Try Again" otherButtonTitles:@"Main Menu", nil];
[alert show];
[alert release];
AlertMessageBoxNo='G';
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:@"Try Again"])
{
IPadCallAnyWhereF.matchDisconnect();
}
else if([title isEqualToString:@"Main Menu"])
{
IPadCallAnyWhereF.gotoMainMenu();
}
}
@end
答案 1 :(得分:2)
问题是 [presentsViewController dismissModalViewControllerAnimated:NO];
我应该删除dismissViewController,而且一切都还好。
//[presentingViewController dismissViewControllerAnimated:NO completion:nil]; // that I removed
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = minPlayers;
request.maxPlayers = maxPlayers;
request.playersToInvite = pendingPlayersToInvite;
GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
mmvc.matchmakerDelegate = self;
[presentingViewController presentViewController:mmvc animated:YES completion:nil];
self.pendingInvite = nil;
self.pendingPlayersToInvite = nil;