The following piece of code works nice on iOS 6.0 (both simulator and device). The game center is presented allright. But it does nothing on iOS 5.0 simulator. Unfortunately I don't have a device with iOS 5.0, so I can't check if it is a simulator-related issue.
- (void)showLeaderboard:(NSString *)leaderboard
{
GKLeaderboardViewController * leaderboardViewController = [[GKLeaderboardViewController alloc] init];
leaderboardViewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[leaderboardViewController setCategory:leaderboard];
[leaderboardViewController setLeaderboardDelegate:self];
[[[UIApplication sharedApplication] delegate].window.rootViewController presentViewController:leaderboardViewController animated:YES completion:^{
}];
[leaderboardViewController release];
}
So what happens? Nothing. No view is presented. It doesn't log any messages into the console. It does not even reach the completion block.
I tried to play around and here is what I've managed to figure out. I use CustomLeaderboardViewController inherited from GKLeaderboardViewController instead of pure GKLeaderboardViewController, and place a breakpoint in the shouldAutorotateToInterfaceOrientation method. It does not fire with the code above. But if I use
setCategory:nil
instead of
setCategory:leaderboard
then that breakpoint fires. Still nothing happens further and the completion block is not called.
Any thoughts why could such a thing happen?
Make sure that none of your variables (e.g., 'leaderboard') are non-nil, as Objective C likes to fail silently in such cases.
It turned out to be just a silly mistake. [[UIApplication sharedApplication] delegate].window.rootViewController was nil, because it was never set in case of iOS 5.0.
Related
We are using cocos2d-js to develop an iOS App which can launch different games. So I add an button in the native app viewcontroller and start the game by clicking the button, just like this:
-(void)didClickGame2Btn:(id)sender
{
//加载游戏
cocos2d::Application *app = cocos2d::Application::getInstance();
// Initialize the GLView attributes
app->initGLContextAttrs();
cocos2d::GLViewImpl::convertAttrs();
// Use RootViewController to manage CCEAGLView
RootViewController *rootViewController = [[RootViewController alloc] init];
rootViewController.wantsFullScreenLayout = YES;
[self.navigationController presentViewController:rootViewController animated:YES completion:^{
// IMPORTANT: Setting the GLView should be done after creating the RootViewController
cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)rootViewController.view);
cocos2d::Director::getInstance()->setOpenGLView(glview);
NSString *documentDir = [SEGetDirectories dirDoc];
NSString *wPath = [NSString stringWithFormat:#"%#/GameData/Game2",documentDir];
NSLog(#"document------:%#",documentDir);
std::vector<std::string> searchPathList;
searchPathList.push_back([wPath UTF8String]);
cocos2d::FileUtils::getInstance()->setSearchPaths(searchPathList);
//run the cocos2d-x game scene
app->run();
}];
[[UIApplication sharedApplication] setStatusBarHidden:true];
}
the rootViewController contains the game view. And then we add an button in the game, which is used to exit the game. The click event code of the exit game button likes:
//exit the game and close the view controller
gameEndCallBack:function(sender){
cc.log("director end............");
cc.director.end();
var ojb = jsb.reflection.callStaticMethod("ViewControllerUtils", "dismissCurrentVC");
}
We use the reflection to dismiss the rootViewController:
+(void)dismissCurrentVC
{
UIViewController *currentVC = [ViewControllerUtils getCurrentVC]; //这里获取最顶层的viewcontroller
[currentVC dismissViewControllerAnimated:YES completion:^{
NSLog(#"xxx");
}];
}
Everything is ok when the first time to enter the game, but after dismissing the rootViewController, we try to enter the game again, it crash.
The crash line is in the ScriptingCore::runScript metod and executing the code:
evaluatedOK = JS_ExecuteScript(cx, global, *script, &rval);
And the crash info is "exc_bad_access".
It is much the same problem as this topic, but the approaches in it did not solve the problem.
http://discuss.cocos2d-x.org/t/how-to-destroy-a-cocos-game-on-ios-completely/23805
This problem has been confusing me serveral days, I have no solution for this. Can anyone give me some help?
You can make the app to support multiple games with in the app.
All you have done is required but in addition to that please follow the below instructions.
First of all, cocos provide a singleton instance of cocos2d::Application that can not be restarted again especially in iOS. So the approach of ending the Director cc.director.end(); won't help you.
You should start the application only once by using the function call cocos2d::Application::getInstance()->run(); and next time if you want to start the game layer, you should not call this method again.
Instead, just pause cocos2d::Director::getInstance()->pause(); and resume cocos2d::Director::getInstance()->resume(); the director when you want to stop the game.
In this approach, if you dismiss/dealloc the view-controller instance then you should create the glview cocos2d::GLView instance again without calling the run method.
One more problem is, take care of the delay in loading the new scene. GLView will display the previous game scene for a while. Do a work around that will show blank screen while the new scene is ready.
Hope this will help you.
I have Simple popOver controller in my project. i can dismiss it using action button with following code.
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
but sometimes app gets crash if i do something on that viewController
before dismiss it.
Example : There is a pickerView for selection and post button. but without posting it if i did some selection and cancel it im getting this error. its only happening occasionally. not everytime. if it happens onetime then it might happen everytime after that.
Can someone explain? is it memory leak or something?
I think have solved the problem . in that PopOver new window i was using locationManager and i was using just
[locationManager stopUpdatingLocation];
but i have added following thing as well
locationManager = nil;
no crash anymore
Sometimes if you have dealloc function as mentioned below, this issue may occur.
- (void)dealloc {
[_yourview release]; //don't do this
[super dealloc];
}
I hope this might help some one else
I'm working on an app which was made in some older version of Xcode, it is currently having min supported version iOS 7.0
+[UIStatusBar frameForStyle:orientation:]: unrecognized selector sent to instance
I have set the break point, but unable to find the issue.
Guys thanks for your responses and interest, Accidentally I came to know that, I had set the UIStatusBar hidden, while there was a MPVloumeView added to view, Whenever I tried to change the volume, It crashed the application. According to another SO answer, the MPVloumeView should be in the first UIWindow of application.
I just added another MPVloumeView in first window, and made it invisible
MPVolumeView* mpView=[[MPVolumeView alloc]initWithFrame:CGRectMake(0, 0, 1, 1)];
[mpView setTintColor:[UIColor clearColor]];
mpView.alpha=0.01;
{
NSArray *windows = [UIApplication sharedApplication].windows;
if (windows.count > 0) {
[[windows objectAtIndex:0] addSubview:mpView];
}
}
There is no class reference for UIStatusBar, so you are calling a class method on an unknown class.
What are you trying to do with the status bar? You can edit it through the plist or through UIApplication like [[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
It does look like (from looking at code on GitHub) that UIStatusBar.h was part of UIKit at some point. Maybe it is a private class that we should not really have access to?
I have a piece of code that runs fine on iOS7, but has issues in iOS8.
It is a popup, that is initialized from a nib and immediately after, it's show method is called.
The problem is, that the initFromNib in iOS8 returns immediately, before calling viewDidLoad.
Consequently all IBOutlets, that the code relies on in show are nil.
The same code is used at multiple occasions, it works with a datepicker embedded in the popup, but it seems that the tableview, that is embedded in the popup in this special case is not initializing immediately on initFromNib.
To repeat the question: Is this a new behavior in iOS8 and
How should I handle this case in objC:
Init a popup from nib and show it immediately after initialization has been finished.
Currently, I would implement my show method as a delegate that is called at the end of viewDidLoad, but this would integrate too much external workflow into the popup for my opinion. But then, I am not really experienced in iOS development ...
Thanks for helping out or pointing me to matching resources.
UPDATE: This is the code calling the view
- (void)onButtonTapped:(id)sender {
if(shouldResignFirstResponder){
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
}
isFirstResponder = YES;
if (self.beginEditingBlock!=nil){
self.beginEditingBlock([self fieldId]);
}
JXCheckListPopoverController *popover = [[JXCheckListPopoverController alloc]
initWithNibName:#"JXCheckListPopoverController" bundle:nil];
if([self getEditableFieldType] == EditableField_multipleStrings) {
valuesBeforeEditing = [self.fieldValues copy];
[popover setupPopoverWithParams:params delegate:self
fieldValues:self.fieldValues readOnly:readOnly];
} else {
NSMutableDictionary *selectedValue = [[NSMutableDictionary alloc]
initWithObjectsAndKeys:fieldValue, #"selectedValue", nil];
self.fieldValueBeforeEditing = fieldValue ? fieldValue : #"";
[popover setupPopoverWithParams:params
delegate:self fieldValues:selectedValue readOnly:readOnly];
}
[popover show:self.bounds parent:self];
[[NSNotificationCenter defaultCenter] postNotificationName:#"fieldSelected" object:self];
self.startDate = [NSDate date];
}
viewDidLoad is called after this method has finished. I understand, that this is somewhat uncool, but I inherited this code as a bad heritage and would like to understand how to rework the workflow. As there may be hundreds of popover views present during editing (present but not visible), I cannot create them all upfront - at least not as far as as I understand the code.
This is the show method:
- (void)show:(CGRect)rect parent:(UIView *)parent {
if ([self.popoverController isPopoverVisible]){
[self.popoverController dismissPopoverAnimated:YES];
}
UIPopoverController *popover = [[UIPopoverController alloc]initWithContentViewController:self];
popover.delegate = self;
const CGFloat height = contentTableView.rowHeight* possibleValues.count;
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenHeight = screenRect.size.height;
//todo: replace hardcoded sizes here
[popover setPopoverContentSize:CGSizeMake(350.0, MIN(height,screenHeight))];
self.popoverController = popover;
if (parent.window!=nil){
[self.popoverController presentPopoverFromRect:rect inView:parent permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIF_popupShow object:nil];
}
The problem is that you were always doing this wrong. iOS 8 has merely exposed the problem. Keep in mind what viewDidLoad means. It means that this view has loaded and that any outlets are now connected. Nothing more. It exists, but that is all. In particular, it is not in the interface yet. So what you were doing in viewDidLoad, you were doing too soon. Use viewDidAppear: or viewDidLayoutSubviews, for example, to know when the view is actually in the interface and we are ready to do something else.
Behavior for popovers has changed in iOS8. I'm not sure about regular view lifecycle thought. One would think that viewDidLoad will be called in a sync manner when you instantiate view from a XIB file, but judging by your comments it's not the case.
If I were on your place - I would try to create a sample small project where you can pin-point the problem and solution exactly. I know that re-factoring large body of code might not be an easy solution, but it might be necessary. In my projects I'm trying to wrap application logic for presenting alerts and popovers in a way so all differences between OS versions and devices are hidden from the application code and can adjusted easily.
I have found a solution to the problem.
I have changed the code to set the height of the tableview contained in the popup in the viewWillAppear method:
const CGFloat height = contentTableView.rowHeight* possibleValues.count;
CGFloat screenHeight = screenRect.size.height;
[popover setPopoverContentSize:CGSizeMake(350.0, MIN(height,screenHeight))];
This did not hurt the logic and it solved the problem.
The answer to the question is possibly that some change was there in nib loading, but I could not find a reference anywhere.
So I accept my answer as correct, as it solves my problem, but I feel kind of bad about it, because it does not explain the real issue. I have given the other persons answering a "+1" on their answers.
I have an EAGLView-based class that runs the following code when a menu selection is made in OpenGL:
-(void) startPicker
{
self.gameState = kStatePicker;
GKPeerPickerController *picker = [[GKPeerPickerController alloc] init];
picker.delegate = self;
picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
[picker show];
}
For some unknown reason, the picker is a blank rounded rect when it appears, with no visible interface or directions.
If I launch it at the end of my init function, it works. Afterward, it launches fine from the menu.
I have tried placing the code in startPicker inside a main queue dispatch, but that doesn't seem to help. I've tried running the picker with and without ARC, but that makes no difference. This code is more or less directly taken from the GKTank example that Apple provided a while ago, to introduce GameKit's bluetooth framework.
Can anyone tell me why this might be happening, and what a possible solution is?
Just following up. I discovered in the view controller that contains this view that there was a call to [UIView setAnimations:NO]; This prohibits GKPeerPickerController from appearing properly.