iOS8 animation code does not work anymore - objective-c

The code I used to animate a UITextField worked for me until XCode Version 6.0 (6A215l). Now XCode6 Beta7 not reposition UITextField. What should I do to make it work?
Here the code:
#interface TableConfigViewController ()
#property(nonatomic, strong) IBOutlet UITextField *customTableName;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
[self.customTableName setDelegate:self];
}
- (void)animateTextField:(UITextField*)textField
up:(BOOL)up
{
const float movementDuration = 0.5f;
const int movementDistance = 380;
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"animation" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:movementDuration];
self.customTableName.frame = CGRectOffset(self.customTableName.frame, 0, movement);
[UIView commitAnimations];
}
- (void)textFieldDidBeginEditing:(UITextField*)textField
{
[self animateTextField:textField up:YES];
}
- (void)textFieldDidEndEditing:(UITextField*)textField
{
[self animateTextField:textField up:NO];
}
Thank you very much in advance

Not sure if this is the source of your problem but you should consider using the block based APIs (available since iOS 4.0) for UIView animations.
From Apple's docs regarding beginAnimations:context:
"Use of this method is discouraged in iOS 4.0 and later. You should use the block-based animation methods to specify your animations instead."
For example (untested):
- (void)animateTextField:(UITextField*)textField
up:(BOOL)up
{
const float movementDuration = 0.5f;
const int movementDistance = 380;
int movement = (up ? -movementDistance : movementDistance);
[UIView animateWithDuration:movementDuration
animations:
^{
self.customTableName.frame = CGRectOffset(self.customTableName.frame, 0, movement);
}
];
}

Related

Why doesn't my animation loop?

I need to perform a blinking effect on a image once the user click on a particular button. But my code doesn't work:
- (void)next
{
[UIView animateWithDuration:2.0f delay:0 options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat animations:^{
NSLog(#"Done"); // <- USED AS COUNTER
[image setAlpha:0];
[image setAlpha:0.5];
} completion:nil];
}
What happens is my image changing its alpha to 0.5 and stops. Furthermore my console shows DONE just one time. What did I wrong?
I just created a test project and this blinked just fine...
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong)UIView *blinker;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.blinker = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
self.blinker.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.blinker];
[self next];
}
- (void)next
{
[UIView animateWithDuration:2.0f delay:0 options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat animations:^{
NSLog(#"Done"); // <- USED AS COUNTER
[self.blinker setAlpha:0];
[self.blinker setAlpha:0.5];
} completion:nil];
}
With the exception that you expect the log to continue to print out in the console. So I suspect you are doing something to your image. You aren't calling self. so I am guessing it is an instance variable (ivar) and you are changing what it points to somewhere else in the code.
If you need a counter to go off every blink you may want to consider something like this...
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong)UIView *blinker;
#property (nonatomic,)NSInteger counter;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.blinker = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
self.blinker.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.blinker];
[self next];
}
- (void)next
{
[UIView animateWithDuration:1.0 animations:^{
self.counter++;
NSLog(#"Counter: %#", #(self.counter));
self.blinker.alpha = 0.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 animations:^{
self.blinker.alpha = 1.0;
} completion:^(BOOL finished) {
//check to see if you want to continue blinking if so call next again
[self next];
}];
}];
}
I don't have any context as to why you want to count, but hopefully that helps.

how to spin an image continuously

I have an wheel image in .png format, I want to know how can i animate so that it rotates continuously, I searched on stackoverflow and found certain snippets of code which helped me rotate my image but it wouldn't rotate continuously, it would just rotate for a few seconds and stop, the code as follows
the code in viewdidload
UIImageView *imageToMove =
[[UIImageView alloc] initWithImage:[UIImageimageNamed:#"horo_circle.png"]];
[self.view addSubview:imageToMove];
[self rotateImage:imageToMove duration:5.0
curve:UIViewAnimationCurveEaseIn degrees:180];
and the animation
- (void)rotateImage:(UIImageView *)image duration:(NSTimeInterval)duration
curve:(int)curve degrees:(CGFloat)degrees
{
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform =
CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees));
image.transform = transform;
// Commit the changes
[UIView commitAnimations];
}
and the following lines after the import
#define M_PI 3.14159265358979323846264338327950288 /* pi */
#define DEGREES_TO_RADIANS(angle) (angle / 180.0 * M_PI)
You are better of doing this with a CABasicAnimation:
if ([self.spinnerOverlay animationForKey:#"SpinAnimation"] == nil) {
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2*M_PI];
animation.duration = 10.0f;
animation.repeatCount = INFINITY;
[self.spinnerOverlay.layer addAnimation:animation forKey:#"SpinAnimation"];
}
In this code I check whether the animation is all ready set, not need to set it again.
The spinnerOverlay is in your case the UIImageView you want to rotate.
To stop the animation:
[self.spinnerOverlay.layer removeAnimationForKey:#"SpinAnimation"];
The code bellow will spin a UIImageView called iconView continiously until rotate == NO.
The image will always return to its original position.
- (void)performRotationAnimated
{
[UIView animateWithDuration:0.5
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
self.iconView.transform = CGAffineTransformMakeRotation(M_PI);
}
completion:^(BOOL finished){
[UIView animateWithDuration:0.5
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
self.iconView.transform = CGAffineTransformMakeRotation(0);
}
completion:^(BOOL finished){
if (_rotate) {
[self performRotationAnimated];
}
}];
}];
}
This is a variation on the same theme.
(Total duration: 2 * 0.5 = 1 sec for a spin)
Works like magic!
Here is another way to do it with a timer.
In your viewController.h file, you'll need to declare your timer and image:
#interface ViewController : UIViewController
{
IBOutlet UIImageView *spinningImage;
NSTimer *spinTimer;
}
Next, in your ViewController.m, you add this code and can make the spin go faster by lowering the time interval or by increasing the transform interval.
-(void) viewDidLoad {
spinTimer = [NSTimer scheduledTimerWithTimeInterval:.01 target: self selector:#selector(spinVoid) userInfo:nil repeats:YES];
}
-(void) spinVoid {
spinningImage.transform = CGAffineTransformRotate(spinningImage.transform, 0.001);
}
Hope this helps!
Now that we're at iOS6, please consider switching to block based animations (that are available since iOS 4.0) rather than the classical method. Try this:
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionRepeat animations:^{
image.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees));
} completion:nil];
Using the method you've chosen for animations :
[UIView setAnimationRepeatCount:10000000];
or, you can specify the UIViewAnimationOptionRepeat flag in the blocks method animateWithDuration:delay:options:animations:completion:

Admob banner not getting remove from superview

I am developing one 2d game using cocos2d framework, in this game i am using admob for advertising, in some classes not in all classes but admob banner is visible in every class and after some time game getting crash also.
I am not getting how admob banner is comes in every class in fact i have not declare in Rootviewcontroller class. can any one suggest me how to integrate Admob in cocos2d game, i want Admob banner in particular classes not in every class,
I am using latest google admob sdk, my code is below:
Thanks in advance
`
-(void)AdMob{
NSLog(#"ADMOB");
CGSize winSize = [[CCDirector sharedDirector]winSize];
// Create a view of the standard size at the bottom of the screen.
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
bannerView_ = [[GADBannerView alloc]
initWithFrame:CGRectMake(size.width/2-364,
size.height -
GAD_SIZE_728x90.height,
GAD_SIZE_728x90.width,
GAD_SIZE_728x90.height)];
}
else { // It's an iPhone
bannerView_ = [[GADBannerView alloc]
initWithFrame:CGRectMake(size.width/2-160,
size.height -
GAD_SIZE_320x50.height,
GAD_SIZE_320x50.width,
GAD_SIZE_320x50.height)];
}
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
bannerView_.adUnitID =#"a15062384653c9e";
}
else {
bannerView_.adUnitID =#"a15062392a0aa0a";
}
bannerView_.rootViewController = self;
[[[CCDirector sharedDirector]openGLView]addSubview:bannerView_];
[bannerView_ loadRequest:[GADRequest request]];
GADRequest *request = [[GADRequest alloc] init];
request.testing = [NSArray arrayWithObjects:
GAD_SIMULATOR_ID, nil]; // Simulator
[bannerView_ loadRequest:request];
}
//best practice for removing the barnnerView_
-(void)removeSubviews{
NSArray* subviews = [[CCDirector sharedDirector]openGLView].subviews;
for (id SUB in subviews){
[(UIView*)SUB removeFromSuperview];
[SUB release];
}
NSLog(#"remove from view");
}
//this makes the refreshTimer count
-(void)targetMethod:(NSTimer *)theTimer{
//INCREASE OF THE TIMER AND SECONDS
elapsedTime++;
seconds++;
//INCREASE OF THE MINUTOS EACH 60 SECONDS
if (seconds>=60) {
seconds=0; minutes++;
[self removeSubviews];
[self AdMob];
}
NSLog(#"TIME: %02d:%02d", minutes, seconds);
}
`
UPDATES: Refer generalised answer here: Admob-banner-integration-in-cocos2d
I hope already u got solution. If not then here is all code for Admob integration in cocos2D game.
#define ENABLE_ADMOB 1
//#define COCOS2D_2_0 1
#interface MyMainMenu : CCLayer
{
#ifdef ENABLE_ADMOB
GADBannerView *mBannerView;
#endif
}
#implementation MyMainMenu
-(void)onEnter
{
[super onEnter];
#ifdef ENABLE_ADMOB
#ifdef COCOS2D_2_0
AppController *app = (AppController*)[[UIApplication sharedApplication] delegate];
#else
AppDelegate* app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
#endif
mBannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
// Specify the ad's "unit identifier." This is your AdMob Publisher ID.
mBannerView.adUnitID = MY_BANNER_UNIT_ID;
// Let the runtime know which UIViewController to restore after taking
// the user wherever the ad goes and add it to the view hierarchy.
//size
#ifdef COCOS2D_2_0
mBannerView.rootViewController = app.navController;
[app.navController.view addSubview:mBannerView];
#else
mBannerView.rootViewController = app.viewController;
[app.viewController.view addSubview:mBannerView];
#endif
// Initiate a generic request to load it with an ad.
[mBannerView loadRequest:[GADRequest request]];
CGSize AdSize = kGADAdSizeBanner.size;
CGRect frame = mBannerView.frame;
frame.origin.y = -50.0f;
#ifdef COCOS2D_2_0
frame.origin.x = (app.navController.view.bounds.size.width - AdSize.width) / 2 ;
#else
frame.origin.x = (app.viewController.view.bounds.size.width - AdSize.width) / 2 ;
#endif
mBannerView.frame = frame;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
frame = mBannerView.frame;
frame.origin.y = 0.0f;
mBannerView.frame = frame;
[UIView commitAnimations];
#endif
}
-(void)showBannerView
{
if (mBannerView)
{
[UIView animateWithDuration:0.5
delay:0.1
options: UIViewAnimationCurveEaseOut
animations:^
{
CGRect frame = mBannerView.frame;
frame.origin.y = 0.0f;
mBannerView.frame = frame;
}
completion:^(BOOL finished)
{
}];
}
}
-(void)hideBannerView
{
if (mBannerView)
{
[UIView animateWithDuration:0.5
delay:0.1
options: UIViewAnimationCurveEaseOut
animations:^
{
CGRect frame = mBannerView.frame;
frame.origin.y = -50.0f;
mBannerView.frame = frame;
}
completion:^(BOOL finished)
{
}];
}
}
-(void)dismissAdView
{
#ifdef ENABLE_ADMOB
if (mBannerView)
{
[UIView animateWithDuration:0.5
delay:0.1
options: UIViewAnimationCurveEaseOut
animations:^
{
CGRect frame = mBannerView.frame;
frame.origin.y = -50.0f;
mBannerView.frame = frame;
}
completion:^(BOOL finished)
{
[mBannerView setDelegate:nil];
[mBannerView removeFromSuperview];
mBannerView = nil;
}];
}
#endif
}
Full fix (tested with iOS 8.1 and Admob 6.12.0)
-(void)RemoveAds
{
if (adBanner != nil)
{
[adBanner setRootViewController:nil];
[adBanner removeFromSuperview];
adBanner = nil;
}
}
Since in cocos2d, you will have different classes for scenes.
My suggestion would be to create a separate class for the add banner and have a static method do the job for you. You will have to save a reference of the add banner in that class and by using the static methods you can add/remove it to/from the openglview.
For removing you will only do: [bannerView removeFromSuperview];

How to animate a UIImageview to display fullscreen by tapping on it?

I have an UIImageView in a UITableviewCell. When it is tapped, the UIImageView should animated to be displayed fullscreen. When the image is tapped when it is fullscreen it should shrink back to the original position.
How can this be achieved?
Add a gesture recognizer to the view controller.
Add the gesture Recognizer to your header file
#interface viewController : UIViewController <UIGestureRecognizerDelegate>{
UITapGestureRecognizer *tap;
BOOL isFullScreen;
CGRect prevFrame;
}
In your viewDidLoad add this:
isFullScreen = false;
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgToFullScreen)];
tap.delegate = self;
Add the following delegatemethod:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
{
BOOL shouldReceiveTouch = YES;
if (gestureRecognizer == tap) {
shouldReceiveTouch = (touch.view == yourImageView);
}
return shouldReceiveTouch;
}
Now you just need to implement your imgToFullScreen method.
Make sure you work with the isFullScreen Bool (fullscreen if it is false and back to old size if it's true)
The imgToFullScreen method depends on how you want to make the image become fullscreen.
One way would be:
(this is untested but should work)
-(void)imgToFullScreen{
if (!isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = yourImageView.frame;
[yourImageView setFrame:[[UIScreen mainScreen] bounds]];
}completion:^(BOOL finished){
isFullScreen = true;
}];
return;
} else {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[yourImageView setFrame:prevFrame];
}completion:^(BOOL finished){
isFullScreen = false;
}];
return;
}
}
The code from #AzzUrr1, small error corrections (brackets) and tapper implemented slightly different.
Worked for me. Now it would be great to have this implemented with a scrollView, that the user can zoom in/out if the picture is bigger.. Any suggestion?
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIGestureRecognizerDelegate>{
UITapGestureRecognizer *tap;
BOOL isFullScreen;
CGRect prevFrame;
}
#property (nonatomic, strong) UIImageView *imageView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
isFullScreen = FALSE;
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgToFullScreen)];
tap.delegate = self;
self.view.backgroundColor = [UIColor purpleColor];
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 300, 200)];
_imageView.contentMode = UIViewContentModeScaleAspectFill;
[_imageView setClipsToBounds:YES];
_imageView.userInteractionEnabled = YES;
_imageView.image = [UIImage imageNamed:#"Muppetshow-2.png"];
UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgToFullScreen:)];
tapper.numberOfTapsRequired = 1;
[_imageView addGestureRecognizer:tapper];
[self.view addSubview:_imageView];
}
-(void)imgToFullScreen:(UITapGestureRecognizer*)sender {
if (!isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = _imageView.frame;
[_imageView setFrame:[[UIScreen mainScreen] bounds]];
}completion:^(BOOL finished){
isFullScreen = TRUE;
}];
return;
}
else{
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[_imageView setFrame:prevFrame];
}completion:^(BOOL finished){
isFullScreen = FALSE;
}];
return;
}
}
I ended up using MHFacebookImageViewer. Integration is easy, no subclassing UIImageView, and it also has image zooming and flick dismiss.
Although it requires AFNetworking (for loading larger image from URL), you can comment out some code (about 10 lines) to remove this dependency. I can post my AFNetworking-free version if someone needs it. Let me know :)
One possible implementation would be to use a modal view controller with UIModalPresentationFullScreen presentation style.
Just finished a version in swift, just download and add into your project:
GSSimpleImageView.swift
And usage:
let imageView = GSSimpleImageView(frame: CGRectMake(20, 100, 200, 200))
imageView.image = UIImage(named: "test2.png")
self.view.addSubview(imageView)

keyboard hides textfield for different orientation in ipad

In my iPad application, I have few textView and textField's. When I click on textField, the keyboard covers the textField. So I am implementing the below code to move the textview up. But on rotation to portraitUpsideDown its not working fine. It slides the screen down in opposite direction. So how do I solve this problem??
-(void) animateTextField: (UITextView *) textField up: (BOOL) up
{
int txtPosition = (textField.frame.origin.y - 540);
const int movementDistance = (txtPosition < 0 ? 0 : txtPosition); // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
-(void)textViewDidBeginEditing:(UITextView *)textField
{
[self animateTextField: textField up: YES];
}
-(void)textViewDidEndEditing:(UITextView *)textField
{
[self animateTextField: textField up: NO];
}
-(BOOL)textFieldShouldReturn:(UITextView *)theTextField
{
[theTextField resignFirstResponder];
return YES;
}
This solution is for iPhone, but it considers both orientations.
You can adapt a bit and voilá:
http://cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html
Crazy,
Just add another function:
- (void) animateTextView: (UITextView*) textView up: (BOOL) up
{
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: #"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
Then call it like:
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self animateTextView: textView up: YES];
}
- (void)textViewDidEndEditing:(UITextView *)textView {
[self animateTextView: textView up: NO];
}
If your method like this.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
Try this. I don't know exactly. But I am trying to help you. May be x and y coordinate cannot be changed in any orientation. so try this.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(interfaceOrientation=UIInterfaceOrienationPotraitUpsideDown){
//Declare txtPos globally...
txtPos=(textField.frame.origin.y + 540);
}
if(interfaceOrientation=UIInterfaceOrienationPotrait)
{
txtPos=(textField.frame.origin.y - 540);
}
return(YES);
}
in animate method.
assign textPos to txtPosition variable..
You should use keyboard will show and will hide notification to capture keyboard event and adjust your view accordingly.
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardDidHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardHeight = CGRectGetHeight(keyboardFrame);
CGFloat animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
UIViewAnimationCurve animationCurve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
UIViewAnimationOptions animationOption = animationCurve << 16;
[UIView animateWithDuration:animationDuration delay:0 options:animationOption animations:^{
// adjust height using keyboardHeight
} completion:^(BOOL finished) {
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat keyboardHeight = CGRectGetHeight(keyboardFrame);
CGFloat animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
UIViewAnimationCurve animationCurve = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
UIViewAnimationOptions animationOption = animationCurve << 16;
[UIView animateWithDuration:animationDuration delay:0 options:animationOption animations:^{
// adjust height using keyboardHeight
} completion:^(BOOL finished) {
}];
}
This blog post explains this in detail
http://charlie.cu.cc/2015/10/solution-to-the-ios-software-keyboard-cover-part-of-the-ui/