I recently made a menu screen to my cocos2d app where I have attached two pickerviews to the UIWindow. Everything works good, but when I go to select which "game" I want to play and the scene changes, the pickerviews remain. How can I remove them?
Thanks!
More info:
The button is a CCMenuItem (if that matters)
Edit: And this is how Im changing the scene once a button is pressed.
[[CCDirector sharedDirector] replaceScene:menuScene];
If a CCNode object (like CCMenuItem) remains on screen after changing scenes, you have a memory leak.
You're saying that you attach the views (CCMenuItem?) to the UIWindow. I can't imagine how that would work since CCNode objects are not UIView objects.
One of those two issues is likely to be your problem, but hard to give you a concrete fix without seeing the relevant code sections.
I figured it out, all I did was give each pickerview a unique tag, and then when my button is pressed, I used
[UIView removeFromSuperview: tag];
for each picker view.
Related
I'm trying to load a UIView and then right away detect touches on that new view. Currently, overriding touchesBegan gives a delay of around a second.
So, I load up the UIView and immediately keep tapping on the screen. It takes around a second for touchesBegan to be called. From that point on, all is well. However, I can't afford the ~second wait initially.
I have stripped back all the code in the UIView to just the barebones incase anything was clogging up the main thread, but the delay still persists.
How can I go about getting immediate feedback of touches from a newly presented UIView? Thanks.
-- EDIT BELOW --
I've been playing around with this for the past few hours. Even when creating a custom UIWindow and overriding sendEvent, the UITouchPhase gets halted when the new view is displayed. To begin receiving events again I have to take my finger off the screen and place it back on the screen. (I don't want to have to do this).
The problem seems to lie with the segue to the new view controller. When it segues, the touch phase is ended. If I simply add a subview to the current view controller, I see the desired functionality (i.e. instant responding to touch).
Given my newly presented view contains a lot of logic, I wanted to wrap it all up in it's own view controller rather than add it to the presenter view controller. Is there a way for me to do this and use 'addSubview` to present it? This should hopefully achieve the desired effect.
In the end, I created a custom view controller with it's own xib. Where I would have segued, I now instantiate that custom view controller and append it's view. This has eliminated the touch lag.
Have you disabled multi-touch? There's an inherent delay while the controller waits to see if there's a follow up touch (on all single touches). The initial sluggishness might be from loading up the multi-touch code and deciding what to do about it.
myViewController.view.multipleTouchEnabled=NO;
As to your final question, look into view controller containment. Since iOS 5 Apple has provided the hooks officially and safely to present one view controller as a sub view of another.
Sadly I've no insight as to the greater issue.
I found an answer that worked for me from a similar question asked here:
iOS: Why touchesBegan has some delay in some specific area in UIView
This solution isn't check-marked on that thread, so I'll copy it here to make it easier to find.
override func viewDidAppear(animated: Bool) {
let window = view.window!
let gr0 = window.gestureRecognizers![0] as UIGestureRecognizer
let gr1 = window.gestureRecognizers![1] as UIGestureRecognizer
gr0.delaysTouchesBegan = false
gr1.delaysTouchesBegan = false
}
I find that tapping on iAds can freeze the screen on any Sprite Kit game. It's not just my specific project, since the stock Sprite Kit example project also freezes with iAd. This does not happen in the simulator though! I cannot decide whether if it's because the simulator runs iOS 8 and my actual testing device is on 7.1, or because of the fact that the simulator is just a simulator so it does things differently.
So if you tap on the iAd then click on the link in the iAd to go to safari (or manually switch over to any app at this point), then switch back to the Sprite Kit app, the app is frozen. The iAd banner is still live, and it loads ads just how it's supposed to. But the rest of the app is frozen. Or to be specific, It still receives touches and stuff (I can see from NSLogs) but the rendering of the nodes is frozen. If you open up iAd again by tapping on it, and close the iAd, then the app resumes somehow and it works again just fine.
If you're curious, here are the ONLY modifications that I did to the stock Sprite Kit example project:
// in GameViewController.h
#import <iAd/iAd.h>
#interface GameViewController : UIViewController <ADBannerViewDelegate>
#end
// in GameViewController.m
#interface GameViewController() {
ADBannerView* iAdBanner;
NSLayoutConstraint* centerAd;
}
#end
#implementation GameViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure iAd
iAdBanner = [[ADBannerView alloc] initWithFrame:CGRectZero];
iAdBanner.alpha = 0.0;
iAdBanner.delegate = self;
centerAd = [NSLayoutConstraint constraintWithItem:iAdBanner
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0];
[self.view addSubview:iAdBanner];
[self.view addConstraint:centerAd];
// The rest of viewDidLoad is the stock code. I'm not pasting that in...
}
// iAd delegate methods
-(void) bannerViewDidLoadAd:(ADBannerView *)banner {
// fade in iAd banner
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[banner setAlpha:1.0];
[UIView commitAnimations];
}
-(void) bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
NSLog(#"iAd error: %#", error.localizedDescription);
banner.alpha = 0.0;
}
Plus I set the deployment target to 7.1 (and obviously include the iAd framework in the project).
As you can see, I'm not doing anything to the app that could cause this crash. I simply add the iAd banner and that's it. So the problem is not in my code. This must be a bug in Apple's frameworks.
Does anyone know a workaround? I have found several topics on this on the internet, but nobody could suggest a working solution.
EDIT:
I found out that iOS 7.1 on my device calls bannerViewActionDidFinish: when returning to the app. iOS 8 in the simulator however, calls that method before leaving the app (exactly when you leave the app to be exact). That doesn't directly affect the code posted above, since it doesn't implement this method. But it does indicate that the iAd implementations iOS 7.1 and iOS 8 do things differently.
--- Final answer in EDIT 2 ---
Well I did read about this before, and I did try it, but seems like I failed when I tried it earlier. I tried it again and it works now.
So what you want to do is set the canDisplayBannerAds property of your view controller to YES, then use the originalContentView property instead of the normal view one to set up your SKView. Or if you want to access your view from inside a scene, that would be: self.view.window.rootViewController.originalContentView. So basically any time you need to do something with your view that is specific to SKView (like transition to a scene) and what cannot be done with a regular UIView then use scene.view.window.rootViewController.originalContentView instead of just scene.view. The reason for this is that iAd somehow explicitly casts your view as UIView when you set the canDisplayBannerAds property in your view controller, so you cannot use the SKView methods on your view anymore. The originalContentView is a workaround for this.
This totally solved my problem, the app returns to its normal state now.
EDIT:
Nope, it didn't solve my problem. :(
Switching to another app and back while an ad is open now doesn't freeze the app. Good. But simply opening and closing an ad now freezes it the same way. This makes no sense...
So if I don't set canDisplayBannerAds in my view controller, then leaving the app and coming back is the case when the app freezes. But just opening and closing an ad works fine. But if I do set canDisplayBannerAds, then it's the other way around.
This really makes no sense. I'm very confused now...
EDIT 2 (actual solution):
Finally I solved it! But it wasn't easy god damn it...
So the problem was in the view hierarchy. If I add the ADBannerView as a subview of my main view, then it freezes the app. This is strange, since that's the suggested method to add a banner to the screen.
If I don't add the banner as as subview manually, it sill appears on the screen though! I guess iAd is implemented in a way that once initialized, it will display itself on the screen no matter what. It appears a bit differently though. If it's not a subview of any view, then it comes in from the bottom with a "slide up" animation, resizing everything to a smaller box that's above it. This is a default behavior of an iAd banner I guess. So this way it doesn't freeze the screen, it works just fine! But since I wanted a bit more control over the banner (like animating it myself, instead of leaving that to the banner itself) I did the following:
In my view controller, I created an instance of SKView (NOT by casting self.view as SKView as usual, but a completely new instance). Then I added that as a subview of self.view. After that, I initialize the ADBannerView, and add it as a subview of self.view as well. Note that self.view is not directly displaying anything, I use it as a "container" to hold the other two. The view hierarchy then looks something like this:
self.view
/ \
SKView ADBannerView
This way the ADBannerView is not the direct subview or superview of my SKView (which is the main view my game uses) so it cannot screw it up because it doesn't have a concept of that view since they are both subviews of the same view. At this point I have no idea whether you need to set canDisplayBannerAds in your view controller or not. I have it set, and it works. I didn't try leaving that out.
In a nutshell, I have full control of the banner view as well as my game view, and they can't mess with each other since they are not in a subview/superview relationship.
This was very tough to figure out, but here you go. If you also have problems with iAd and Sprite Kit, just organize your views like this.
After upgrading my project to iOS7
when I do a BACK Button and the UINavigationController goes back to the previous page, an ImageView on the top of the screen shifts down.
I use IB to do my layouts. These are my Simulated Metrics:
I have AutoLayout off. Any ideas on what the issue might be? I wasnt sure if anyone wants to see specific code and I didnt want to clutter up the question with too much code.
Updates: Based on the comment questions, I wanted to make these updates:
In no place in the application .h or .m file do I make any changes to the imageview's sizes or location.
In both the viewDidLoad and viewDidAppear I call a user-defined method called recalculateAll but their is no reference at all to any imageview sizes. Just for trying it out I commented out the entire section and ran the code and it still jumps down.
In my init I do programatically set some imageviews (you see the #132 in what appears to be a bubble) using their x and y's.
Here is a typical navigation I use for moving from the view controller to the tableviewcontroller:
GetTimeOffByType *showTimeOffReport = [[GetTimeOffByType alloc] initWithNibName:#"GetTimeOffByType" bundle:nil];
showTimeOffReport.timeOffType = #"Vacation";
[self.navigationController pushViewController:showTimeOffReport animated:YES];
These are all .xib files, no storyboarding at all. Its basically a view controller which has an embedded UINavigationController with 6 buttons. Each time a button is pressed it pushes a UITableViewController passing different parameters and showing different data. The transition I am using to get back to the original UIViewController is simply the iOS generated BACK button (so no code to show for that)
Update#2 Hopefully this will help someone solve this wierd behavior. So if I were to click on the table view cell on showTimeOffReport to get the cell detail and then using BACK navigate all the way back it doesnt jump down.
Update#3 Ok this is something I just discovered : The issue of jumping down or not is related to the translucency of the UINavigationBar. If you have a Translucent = YES it will start from the top of the window. If you have a translucent = NO it will start from the bottom of the UINavigationBar.
You might try setting the new property on UIViewController edgesForExtendedLayout to UIRectEdgeNone.
Here is a good resource that explains more about how view layouts changed in iOS 7.
See Apple Documentation
If you plan to be backwards compatible you will probably need to do some runtime checks and adjust positioning if the device is not running iOS 7.
This might help you..You can try adding UIViewControllerBasedStatusBarAppearance key and set it's value NO in your info.plist
UIViewControllerBasedStatusBarAppearance = NO
I've got a UIView that gets used in a modal view using the UIModalTransitionStylePartialCurl transition style when it appears. This UIView includes a UIButton. The odd thing is that whenever the view appears, as the primary page peels up to the top of the window the button on the modal view animates itself, with the text seeming to get typed onto the button from the center of itself. The movement of this animation is a bit distracting.
Why does this happen? Is there any way to prevent it?
The UIButton does use a custom background, but it is defined in the XIB for the modal view and does not use any special subclass of my own. It is a standard button.
I had the same problem and the mentioned autoresizingMask code didn't work for me.
Although it did give me some pointers in which direction I should look.
Basically the view that will appear should be 'drawn' before being show to have it's initial placing.
Before IOS 5 this was automatically done for the animation including the page-curl, but IOS 5 broke it.
But adding the forced 'drawing' yourself at viewDidLoad solved it for me!
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self.view layoutIfNeeded];
}
Although in this post I offer my answer for this problem. The patch PHO offered later in this very thread is cleaner. Thank you PHO! :)
Short version:
I'm alloc/init/retaining a new UIViewController in one UIViewControllers viewDidLoad method, adding the new View to self.view. This usually works, but it seems to mess up orientation change handling of my iPad app.
Longer version:
I'm building a fairly complex iPad application, involving a lot of views and viewcontrollers. After running into some difficulties adjusting to the device orientation, I made a simple XCode project to figure out what the problem is.
Firstly, I have read the Apple Docs on this subject (a small document called "Why won't my UIViewController rotate with the device?"), and while I do believe it has something to do with one of the reasons listed there, I'm not really sure how to fix it.
In my test project I have an appDelegate, a rootViewController, and a UISplitViewController with two custom viewControllers. I use a button on the rootViewController to switch to the splitViewController, and from there I can use a button to switch back to the rootViewController. So far everything is great, i.e. all views adjust to the device orientation.
However, in the right viewController of the splitViewController, I use the viewDidLoad method to initialize some other viewControllers, and add their views to its own view:
self.newViewController = [[UIViewController new] autorelease];
[newViewController.view setBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:newViewController.view];
This is where things go wrong. Somehow, after adding this view, adjusting to device orientation is messy. On startup everything is fine, after I switch to the splitViewController everything is still fine, but as soon as I switch back to the rootViewController it's all over. I have tried (almost) everything regarding retaining and releasing the viewcontroller, but nothing seems to fix it.
As you can see from the code above, I have declared the newViewController as a property, but the same happens if I don't.
Shouldn't I be adding a ViewController's view to my own view at all? That would really mess up my project, as I have a lot of viewControllers doing all sorts of things.
Any help on this would be greatly appreciated...
I had the same problem, seams resolved by removing from the parent view the "autoresize subview" option in IB.
Select the view a then: Inspector -> Attributes (first tab) -> drawing.
What I think is happening is that your new viewcontroller is getting the autorotation calls and probably not handling them. Meanwhile your old viewcontrollers and its views won't get the autorotation calls and will be stuck in whatever orientation they were in.
I can't tell, but I think what you want to do is to make a UIView and add it to your old viewcontroller, instead of making a UIVIewController and adding its view.