iPod Touch iOS 5.1.1 Not calling viewDidDisappear:animated - iphone

I've posted this question elsewhere, but as SO is such a great community I'm doing so here as well.
First up, I'm using Cocos2D 2.0-gles20 to put a multiplayer/team oriented game together.
I've been integrating GameKitHelper into the app. To date it's been working just fine on my iPhone4 and iPad2 and in the Simulator, but now when I try to use it on an iPod Touch 4th I'm getting assertions in [CCDirectorIOS startAnimation] because the app is getting a viewWillAppear when it shouldn't and no call to viewDidDisappear when it should.
The reason this matters is that these methods on the CCDirectorIOS class cause Cocos2D to start/stop animation whilst another UIKit view is in front. This is something that I've managed myself with Cocos2D-0.99 but with 2.0 it is handled nicely within the director so that each app doesn't have to handle it specifically.
The GameKitHelper class has the following methods for pushing a GKMatchmakerViewController onto the screen:
-(void) showMatchmakerWithInvite:(GKInvite*)invite
{
GKMatchmakerViewController* inviteVC = [[[GKMatchmakerViewController alloc] initWithInvite:invite] autorelease];
if (inviteVC != nil)
{
inviteVC.matchmakerDelegate = self;
[self presentViewController:inviteVC];
}
}
-(UIViewController*) getRootViewController
{
return [CCDirector sharedDirector];
}
-(void) presentViewController:(UIViewController*)vc
{
UIViewController* rootVC = [self getRootViewController];
[rootVC presentModalViewController:vc animated:YES];
}
-(void) dismissModalViewController
{
UIViewController* rootVC = [self getRootViewController];
[rootVC dismissModalViewControllerAnimated:YES];
}
When I call showMatchmakerWithInvite, on the iPhone4, etc I see a call to viewDidDisappear: on the CCDirectorIOS object which stops animation. This is fine. When the GK view is gone, I see a call to viewWillAppear which restarts the animation. Sweet.
On the iPod Touch however, running exactly the same project, the call to viewDidDisappear is not made, but a call to viewWillAppear is, before the GK view has gone.
I can't fathom why there would be a difference. All devices are running iOS 5.1.1.
It's almost as if the behaviour of UIKit is different on the iPod Touch, but I find that hard to believe. My other thought was that I was looking at a timing issue, but I put some code in to allow the app to keep running even with the problem, but the call to viewDidDisappear never happened.
I can work around this I think by managing the start/stop of animation myself, but I would have preferred not to customise the Cocos2D code.
Does anyone have any ideas?
Thanks

Well, being the impatient person I am, rather than leave it to others and work on something else, I nutted it out.
I turns out that the iPod Touch devices in question had multi player games disabled in the restrictions app. This seems to cause the GK view to not show "properly" and as a result the events like viewDidDisappear: and viewWillAppear: don't occur the way I was expecting.
So I've been able to revert all of my tweaks and instrumentation in the Cocos2D code, and simply apply a correction to the GameKitHelper class to ensure that if features such as multi-player are disabled, the player isn't able to request them.

Related

Keyboard shows then immediately hides itself when showing MFMessageComposeViewController

I am building a PhoneGap app using Cordova 2.2 for IOS. I am experiencing some bizarre behavior when calling out to a native obj-c plugin I have written to show the MFMessageComposeViewController.
The setup is very simple - I have a tap event attached to a UI element, that when pressed, will make a call to my PhoneGap plugin, pass with it a number and a text message, then show the MFMessageComposeViewController with the parameters pre-populated.
My javascript looks like this:
$(document).bind('deviceready', function(){
$(".theButton").tap(function(){
cordova.exec(function(){}, function() {}, "PhoneGapSms", "SendSms", [db.getItem("profile_sms"), db.getItem("profile_emergency")]);
});
});
And my obj-c code looks like this:
- (void)SendSms:(CDVInvokedUrlCommand*)command
{
CDVInvokedUrlCommand* myCommand = command;
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
NSString* body = [command.arguments objectAtIndex:0];
NSString* toRecipientsString = [command.arguments objectAtIndex:1];
if(body != nil)
picker.body = body;
if(toRecipientsString != nil)
[picker setRecipients:[ toRecipientsString componentsSeparatedByString:#","]];
picker.messageComposeDelegate = self;
[self.viewController presentModalViewController:picker animated:YES];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[picker release];
}
So, all in all, very simple stuff.
My Problem is this:
When my iPhone is plugged into my Mac and the app is run from XCode, the Message Composer overlay appears great, with my values pre-populated. Image below demonstrating the SMS interface appears fine while plugged into XCode:
When my iPhone is unplugged from my Mac, and the app is run from the spring board, the Overlay slides up, the keyboard begins to slide up, then immediately slides down - making it impossible to type or send the message. This is what it looks like when not attached to the Mac/Xcode - the keyboard begins to slide up then immediately slides down (~ < 1 sec) leaving the following interface:
I can't for the life of me figure out what would cause the keyboard to hide when not running from XCode, but work perfectly well when it is.
Is there any way to 'force' the keyboard to display, or possibly put the whole modalviewcontroller as first responder in some form or fashion?
Any suggestions are appreciated!
Edit:
The keyboard WILL appear again if you click in the contact area
You must add MessageUI.framework to your Xcode project and include a
#import <MessageUI/MessageUI.h> in your header file.
try this code may be its helpful to you..
[self presentModalViewController:picker animated:YES];
//[self becomeFirstResponder];//try picker also instead of self
Also Refer this bellow tutorial and also check demo..
new-tutorial-developing-and-architecting-a-phonegap-application
SMSComposer
i hope this help you...
I encountered these symptoms with a Sencha Touch 2.2 and Cordova 2.6.0 setup (specifically, iOS 6+ devices).
The issue was with the web framework stealing focus away from the native SMS Composer modal, typically occurring after the first SMS Composer modal had been successfully displayed and closed.
A event.preventDefault() and event.stopPropagation() call once the event had been fired (or event.stopEvent() in Sencha land) resolved this.
Hope this helps,
-James
First: The most likely culprit, without seeing your code, is that your parent (presenting) view controller may have an action in its viewWillDisappear or viewDidDisappear that is affecting who has the "first" responder. These methods get called when presenting a view controller modally. It may be behaving differently on the simulator than the device due to timing - often really close timing conditions are different on the ARM device and the i386 processor.
Second: Does anywhere in your app register for the UIKeyboardWillShowNotification or the UIKeyboardDidShowNotification? If so, put breakpoints in the methods that are called as a result - it's possible some other controller in your view hierarchy is interfering with this one.
To answer your question...
Is there any way to 'force' the keyboard to display, or possibly put the whole modalviewcontroller as first responder in some form or fashion?
No to both. The only way to make the keyboard display is to call the becomeFirstResponder method of the input view. Since Apple doesn't expose the text view, you cannot send it messages. Setting the modalViewController as first responder would be setting the wrong object.
I found the same type of issue But Not Sure it will Solve your problem or not Just Have a Look on the Following Links :
1. http://community.phonegap.com/nitobi/topics/keyboard_is_not_triggerd_in_my_ios_build
2. https://github.com/phonegap/build/issues/31
If its not Solving your issue then you can Download the Sample code Here.
Link: https://github.com/phonegap/phonegap-plugins/tree/master/iPhone/SMSComposer

Cocos2d fails on iPad yet works in simulator

I have a very simple game using Xcode v4.2.1, Cocos2d v5.0.1. I've tried both compilers in Xcode (LLVM GCC 4.2 and Apple LLVM compiler 3.0. Is there a preference??) On the game screen is a UIKit button that presents the user with a Interface Builder (nib) Settings/Options screen to customize the game a bit. This is all based on what I learned in Ray Wenderlich's tutorial (http://www.raywenderlich.com/4817/how-to-integrate-cocos2d-and-uikit).
After the user makes their changes, they are returned to the game and the changes are in place.
This all works as I want in the simulator, however, when I test the game on an iPad I get the following errors in the debug window:
2012-01-27 18:25:27.305 BonkBonk[1082:707] failed to call context
2012-01-27 18:25:27.310 BonkBonk[1082:707] cocos2d: surface size: 1024x768
2012-01-27 18:25:27.316 BonkBonk[1082:707] Failed to make complete framebuffer object 8cdd
OpenGL error 0x0506 in -[EAGLView swapBuffers]
OpenGL error 0x0506 in -[EAGLView swapBuffers]
OpenGL error 0x0506 in -[EAGLView swapBuffers]
The OpeenGl errors continue on indefinitely.
I use the function viewWillAppear to capture the return from the settings/options screen so that I can pass the new settings to the game layer. If I comment out this code the problem goes away, however, I am not able to get the new user settings to the game layer.
Here is the code:
- (void) viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
//CCScene *scene = [[CCDirector sharedDirector] runningScene];
CCScene *scene = [BonkBonkLayer scene];
id layer = [scene getChildByTag:1];
[layer userSettings];
[super viewWillAppear:animated];
}
The commented out line //CCSene *scene... was another failed attempt at getting the layer object from the scene so that I could call the userSettings method where the game layer then can assimilate it into the game.
OK, so I've found something that alleviates my issue.
If anyone knows anything about this, please let me know. I will continue to use this fix unless I hear a reason from someone more knowledgable than myself (and that's not that difficult).
The solution is found in the comment by "psionic" at the end of the following discussion:
http://www.cocos2d-iphone.org/forum/topic/7068.
Basically, I created a static bool in the EAGLView class (EAGLView.m) that surrounds the call to _resizeFromLayer in the layoutSubViews member function. The call to _resizeFromLayer is only called the first time through, and then never again.
Please read the above discussion and let me know what you like/dislike about this solution, other than the obvious... it's a hack.
A hack,that works. I think.
I had a similar problem. I've integrated cocos2d with UIKit. I added adMob. The problem shows up when user clicks on Ads that presents the google BrowserView. If you dismiss the View using the Done button, the App works fine. However, if user press the Home button when in Browser View, and resume the App, I got the same exception.
OpenGL error 0x0506 in -[EAGLView swapBuffers]
UIKit buttons and the Ads are shown, but it does not render the cocos2d layer.
I got the solution from https://github.com/cocos2d/cocos2d-iphone/pull/198, but I did not change the cocos2d source. Instead, I added a boolean ivar called isAnimating in AppDelegate.m, and expose the property to the Layers.
To solve this, I stop animation on CCDirector before entering google Browser View. and start animation once resume to the App. isAnimating ivar is used to check that start animation is not called twice.
Hope it helps,
I had similar errors in my app when implementing Cocos2D via CCGLView.
The solution that worked for me was to call
[[CCDirector sharedDirector] popScene]
when presenting the Interface Builder Viewcontroller.

Unbalanced calls to begin/end appearance transitions for <GKModalRootViewController: 0xb7e450>

I give up on that point, I just can't figure out what is wrong and where...
Here is the problem: in my iPhone application using Cocos2d, I configured autorotation through a viewController; however, since, when Game center opens its view as the user taps on "Create new account" during the authentication, this view does not receive any touch, but the touch go to the game's view (which is hidden under the Game center view).
I have tried everything I thought about, but since I did not find any callback about this Game Center View, it is hard to find a way to correct this...
Here is the initialization of the game's view:
// Init the UI View Controller
//
viewController = [[SQViewController alloc] initWithNibName:nil bundle:nil];
viewController.wantsFullScreenLayout = YES;
EAGLView *view = [EAGLView viewWithFrame:[window bounds] pixelFormat:kEAGLColorFormatRGBA8 depthFormat:GL_DEPTH_COMPONENT24_OES];
[director setOpenGLView:view];
[director setDeviceOrientation:kCCDeviceOrientationPortrait];
[view removeFromSuperview];
[viewController setView:view];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
I have tried many other things, commented every single line in this code, tried some others (such as setHidden:NO, bringSubviewToFront...), but the only results I could get were:
- Game display ok, Game Center ok, but no autorotate
- Game displayed in portrait (the view controller only allow landscape modes), Game Center ok, no autorotate
- Game not displayed (black screen), Game Center ok
And no way to make it all work together... The only clue I have is the title of this topic, "Unbalanced calls to begin/end appearance transitions for ." But since I do not call the Game Center view myself, I don't know what to do with this...
Anyone, any idea?
I've had the same problem while displaying game center leaderboards in my cocos2d built App ever since moving up to iOS 5.0. I've seen references elsewhere to this being caused by a sub viewcontroller losing focus on the parent viewcontroller, but I've been unable to verify that or get this resolved in my app either.
Good news is that I've run this thru instruments - No Memory Leaks. Also executed the same action repetitively with no apparent failures or ill effects.
So while this message is an annoyance, it doesn't appear (at least for now) to adversely affect the App.
This Error occurs when you try to push a viewController before previous ViewController is finished . Means you are trying to push 2 ViewControllers at the same time.

Received memory warning. Level=1 when showing a UIImagePickerController

This is driving me crazy!!!
I'm getting a "Received memory warning. Level=1" whenever I attempt to show a UIImagePickerController with a sourceType = UIImagePickerControllerSourceTypeCamera.
Here is the code from my viewDidLoad where I set things up:
- (void)viewDidLoad {
[super viewDidLoad];
// Set card table green felt background
self.view.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:#"green_felt_bg.jpg"]];
// Init UIImagePickerController
// Instantiate a UIImagePickerController for use throughout app and set delegate
self.playerImagePicker = [[UIImagePickerController alloc] init];
self.playerImagePicker.delegate = self;
self.playerImagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
And here is how I present it modally ..
- (IBAction) addPlayers: (id)sender{
[self presentModalViewController:self.playerImagePicker animated:YES];
}
The result ... UIImagePicker starts to show and then boom ... I get the memory warning ... EVERY TIME! Interestingly enough, if I switch to sourceType = UIImagePickerControllerSourceTypePhotoLibrary ... everything works fine.
What in the heck am I missing or doing wrong? All I want to do is show the camera, take and save a picture.
FYI - I'm testing on my 3GS device.
Thanks to anyone who can help :)
This is very common. As long as you handle the memory warning without crashing and have enough space to keep going, don't let it drive you crazy.
It is not about how much memory your app has used, because it will probably happen even when you write a very simple app which have only one view with one button, clicking the button and then open camera.
I have tested on iPhone 3GS, iPad 2 and iPod touch 3G. It only happened in iPhone 3GS.
I found it will not happen anymore if you restart you device before you execute you app.
Another real solution is to comment the code, [super didReceiveMemoryWarning], in your viewController.
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
After lots of test on iPhone 3GS with iOS 4.3.2, I found the logic might like that:
-> Open as much as app running on background
-> Presenting a imagePicker of UIImagePickerController, clicking "Back" or "Save" from imagePicker
-> ApplicationDelegate's method, applicationDidReceiveMemoryWarning:(UIApplication *)application, will be invoked
-> Then ViewController's method, didReceiveMemoryWarning:, will be invoked
-> Then viewDidUnload
-> Then viewDidLoad
Then you could find some views have been released and the current view has been pointed to a unexpected one.
By default, [super didReceiveMemoryWarning] will run when ViewController's didReceiveMemoryWarning method is invoked. Commenting it, and viewDidUnload: and viewDidLoad: methods will not be invoked. It means the mem warning has been totally ignored. That's what we expected.
Now after I upgraded to 4.0 it happens to my app too - before in 3.1 there were no warnings.
Actually as you said before, there should be no issue. However, this causes the view that comes after it to load again and viewDidLoad is being called. This messes up my app, since I initialize the view in viewDidLoad - now it gets initialized all over again - even though it shouldn't.
Just as a comment, this might also happen to many other apps that rely on loading the view only once!
It did happen in my app Did I Do That on iOS 4.0 too. It was not consistent, but the most common cause was creating a UIImagePickerController instance and navigating to some large photo stored in one of the albums.
Fixed by persisting state in the didReceiveMemoryWarning method, and loading from state in the viewDidLoad method. One caveat is to remember to clear the state-persisted file in the correct point for your application. For me it was leaving the relevant UIViewController under normal circumstances.
I'm getting the memory warning when opening a UIImagePickerController as well. I'm on 4.01 as well.
But in addition, the UIImagePickerController is running the close shutter animation and stalling there, with the closed shutter on screen.
It seems like the UIImagePickerController's behavior on memory warnings is to close itself.
I could dismiss the UIImagePickerController from the parent ViewController in the didReceiveMemoryWarning method, but that would make for a terrible user experience.
Has anyone seen this problem?
Is there a way to handle the memory warning so that the UIImagePickerController doesn't shut itself down?
I have been struggling with the same problem for some days now. However, resetting my iPhone 4 (clearing out memory) solves the problem so it's not really an app problem.
It appears that a level 1 or 2 memory warning triggers the UIimgPickerController delegate to offload itself. The same happens in my app with the delegate of the delegate (yes it can). After the memory warning however, it will load the delegate (and it's delegate) again causing the viewDidLoad to execute any code that's in there.
I am not sure this happens only while using the UIimgPickerController because testing all that is very time consuming.
I could write some extra code to prevent the code in viewDidLoad en viewWillAppear from execuring while showing the UIimgPickerController but that's not classy, right?
Here's food for thought: it could be
that you are running out of memory
because you are testing your app. With
some memoryleaks it is very well
possible that you are working towards
this problem every time you debug.
The UIImagePickerControllerDelegate is a memory hog because you are capturing high memory assets, be that an image or video. So from the start be sure to specify the medium capture settings, as a start point, reduce this if you don't need the quality:
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.videoQuality=UIImagePickerControllerQualityTypeMedium;
Then after capturing and using these assets. Remove any temp files from the applications temp folder. Could be an extra obsessive step but its a good habit:
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:[lastCapturedFile substringFromIndex:7] ]) {
NSError *error;
// Attempt to delete the folder containing globalDel.videoPath
if ([fileManager removeItemAtPath:[lastCapturedFile substringFromIndex:7] error:&error] != YES) {
NSLog(#"Unable to delete recorded file: %#", [error localizedDescription]);
} else {
NSLog(#"deleted file");
}
}
With above it is clearing the file that was created by the delegate. In some instances if you are transcoding or creating you own assets delete the folder with that file. Note above I am removing the 'file://' part of the url string as the file manager doesn't like it:
[lastCapturedFile substringFromIndex:7]
Other things to consider are covered in the various documentation for what you are doing with that asset - transcoding, image size reduction and more. Beware that any transcoding using the AVFoundation will crash if the UIImagePickerViewController is displaying.

iphone opengl backing becomes w=0 h=0 after MFMessageComposeViewController

I have an opengl game for iPhone/iPad (universal). I added the ability to send an SMS message using MFMessageComposeViewController. Testing in a real iPhone. The SMS composer sheet animates up over my view, I can send the message or not, didFinishWithResult gets called, and when I [self dismissModalViewControllerAnimated:YES] it goes away and my glview is asked to layoutSubviews. At that point the backing width and height are now zero, and my frame buffer status check fails. The self.layer.frame.size.width is still 320x460.
- (void)layoutSubviews
{
NSLog(#"layoutSubviews");
[EAGLContext setCurrentContext:context];
[self destroyFramebuffer];
[self createFramebuffer];
[self drawView];
}
I do have a UIViewController for my glView which is where I handle orientation changes for the iPad and where I also put the MFMessage stuff. (Technically I guess since it's universal there are two different viewControllers, two app Delegates and two nibs - but I'm working in the iPhone set here because the iPad doesn't sms). On the iPad layoutSubviews gets called when the orientation changes, we destroy and re-create the framebuffers at the new size and everything is fine. But here when coming back from sending the SMS it fails on the re-creating. I can post the code if necessary but its the standard creating framebuffer code.
Another important point is that I'm using a notification to tell the method inside of the viewcontroller to start the sms stuff. I tried just having those methods in my glview and making it the MFMessageComposeViewControllerDelegate but then I was getting errors because glview is a UIView and not a UIViewController.
Any ideas?
Not sure if it's a bug or what the deal is but I had to create another view, make self.view = anotherView, retain my glview and removeFromSuperview before presenting the modal. And then wait to bring my glview back until everything was animated back into place.
If anyone wants more info please let me know.
Edit with actual answer:
It is a bug and as I suspected it has to do with the status bar. My app has no status bar. But when I
[self presentModalViewController:controller animated:YES];
the SMS message composer view does show the iphone status bar. When it is dismissed and my app showed through underneath my framebuffer was getting borked. I had figured out a weird work around of switching views to protect my glview framebuffer - but then figured out to add a statusBarHidden before the dismiss and all is well now. Here's the dismiss code:
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result {
// Notifies users about errors associated with the interface
switch (result)
{ ... }
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[self dismissModalViewControllerAnimated:YES];
}