Translating a UIView and setting the label text - ios

I'm starting to learn iOS gesture recognizers, going through this tutorial http://www.appcoda.com/ios-gesture-recognizers/. Have a problem translating a view with UIPanGestureRecognizer while setting the UILabels' text to the gesture's velocity.
I have been successfully translating a view with a pan gesture like this (with the help of IB):
PanViewController.h
#interface PanViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIView *testView;
#property (weak, nonatomic) IBOutlet UILabel *horizontalVelocityLabel;
#property (weak, nonatomic) IBOutlet UILabel *verticalVelocityLabel;
#end
PanViewController.m
#interface PanViewController ()
- (void)moveViewWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer;
#end
#implementation PanViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(moveViewWithGestureRecognizer:)];
[self.testView addGestureRecognizer:panGestureRecognizer];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)moveViewWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint touchLocation = [panGestureRecognizer locationInView:self.view];
self.testView.center = touchLocation;
}
But when I add the following lines to this method, the view stops translating, but the UILabels get updated with the velocity:
CGPoint velocity = [panGestureRecognizer velocityInView:self.view];
self.horizontalVelocityLabel.text = [NSString stringWithFormat:#"Horizontal Velocity: %.2f points/sec", velocity.x];
self.verticalVelocityLabel.text = [NSString stringWithFormat:#"Vertical Velocity: %.2f points/sec", velocity.y];
I'd like to understand what i'm doing wrong. How can I fix it?
Thanks in advance.

Related

xcode - multiple instances of custom view

I've created a custom UIViewController with storyboard and this is the class:
.h file:
#import <UIKit/UIKit.h>
#interface PlayerViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *PlayerNumber;
#property (weak, nonatomic) IBOutlet UIImageView *PlayerImage;
#property (weak, nonatomic) IBOutlet UILabel *PlayerNameLabel;
-(void)setPlayerName:(NSString*)PlayerNameString;
#end
.m file:
#import "PlayerViewController.h"
#interface PlayerViewController ()
#end
#implementation PlayerViewController
#synthesize PlayerImage,PlayerNameLabel,PlayerNumber;
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(void)setPlayerName:(NSString *)PlayerNameString{
self.PlayerNameLabel.text=PlayerNameString;
}
#end
from main view I create 2 instance of PlayerViewController in order to display 2 custom views:
- (void)viewDidLoad {
[super viewDidLoad];
[self DrawPlayerWithTag:1];
[self DrawPlayerWithTag:2];
}
- (void)DrawPlayerWithTag:(int)PlayerTag{
PlayerViewController *myPlayerViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"PlayerViewController"];
UIView *myPlayerView=myPlayerViewController.view;
myPlayerView.tag=PlayerTag;
myPlayerView.frame=CGRectMake(0, 0, 100, 100);
myPlayerView.center = CGPointMake(self.view.frame.size.width / 2,
self.view.frame.size.height / 2);
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doDoubleTap)];
doubleTap.numberOfTapsRequired = 2;
[myPlayerView addGestureRecognizer:doubleTap];
[self.view addSubview:myPlayerView];
[myPlayerViewController setPlayerName:#"NameA"];
}
It seems to work.
But, if I want to change the PlayerName, how can refer to view1 rather then view2 after a double tap event, and use the method setPlayerName?
Thanks a lot for your answer!
Change the callback method
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doDoubleTap:)];
You can get the tag of the view like this:
-(void)doDoubleTap:(UITapGestureRecognizer *)gesture{
NSLog(#"%ld", gesture.view.tag);
}
You can keep your code and invoke setPlayerName with this post Get to UIViewController from UIView?
But, I suggest this way:
set target for gesture is myPlayerViewController
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:myPlayerViewController action:#selector(doDoubleTap:)];
Keep ref of myPlayerViewController in "main view" by an array like:
[arrPlayerView addObject:myPlayerViewController]; /// keep pointing to myPlayerViewController, so it isn't released.
Place (void)doDoubleTap:(UITapGestureRecognizer *)gesture in PlayerViewController

UITap gesture only works on one view

I have the following code in a view controller:
#interface QuizController ()
#property (weak, nonatomic) IBOutlet UITextView *questionText;
#property (weak, nonatomic) IBOutlet UITextView *one;
#property (weak, nonatomic) IBOutlet UITextView *two;
#property (weak, nonatomic) IBOutlet UITextView *three;
#property (weak, nonatomic) IBOutlet UITextView *four;
#property(strong, nonatomic) NSMutableArray* possAnswers;
#end
#implementation QuizController
- (void)viewDidLoad {
[super viewDidLoad];
[self.manager setupGame];
self.possAnswers = [[NSMutableArray alloc] initWithObjects:#"a", #"b", #"c", #"d", nil];
}
//This listens for a tap on any of the TextViews and sets the background to Blue
- (IBAction)fourTapped:(id)sender {
NSLog(#"There's been a tap!");
[self blankBoxes];
if( [sender isKindOfClass:[UITapGestureRecognizer class]] )
{
UITapGestureRecognizer* tgr = (UITapGestureRecognizer*)sender;
UIView* view = tgr.view;
if( [view isKindOfClass:[UITextView class]]){
UITextView* tv = (UITextView*)view;
NSLog([tv text]);
[tv setBackgroundColor:[UIColor blueColor]];
}
}
}
-(void)blankBoxes
{
[_one setBackgroundColor:[UIColor whiteColor]];
[_two setBackgroundColor:[UIColor whiteColor]];
[_three setBackgroundColor:[UIColor whiteColor]];
[_four setBackgroundColor:[UIColor whiteColor]];
}
However, the only UITextView that gets highlighted is _one, no matter which view is tapped. I don't understand why this is. I'd be really grateful if anyone could point this out to me.
Gesture recognizers attach to one and only one view. That's by design. If you want a single gesture recognizer that lets you recognize taps on multiple views, you have to attach it to a common, enclosing superview, then look at the tap coordinates and figure out which view was tapped.
Normally you just create a different gesture recognizer for each view that needs to responds to taps.
Add the UIGestureRecognizer to a UIView that contains your subviews. After that use CGRectContainsPoint() to check if the tap location is in one of the subviews, then continue from there.
CGPoint *touchLocation = [gesture locationInView:self];
for(UIView *view in self.subviews){
if(CGRectContainsPoint(view.frame, touchLocation))
//Your code here
}

UITapGestures in Middle of Animations

I'm am trying to delete an image while it is moving on the screen using UITapGestureRecognizers and UIViewAnimation. I have used the UIViewAnimationOptionAllowUserInteraction, but I still get the SIGBART error. I have been looking through the internet and couldn't find a solution.
This is my .m file
#import "AbcViewController.h"
#interface AbcViewController ()
#end
#implementation AbcViewController
//single tap gesture action /deletes person
-(void) tapped:(UITapGestureRecognizer *)recognizer{
[recognizer.view removeFromSuperview];
}
//double tap gesture action
-(void) tapped2:(UITapGestureRecognizer *)recognizer{
[recognizer.view removeFromSuperview];
}
- (void)viewDidLoad
{
[super viewDidLoad];
//this makes a zombie/person
UIImageView *zombieView =[[UIImageView alloc] initWithFrame:CGRectMake(135 , 300, 50, 75)];
UIImage *zombie=[UIImage imageNamed:#"free-vector-stick-figure-clip-art_105575_Stick_Figure_clip_art_hight.png"];
[zombieView setImage:zombie];
[self.view addSubview:zombieView];
[self.view insertSubview:zombieView belowSubview:_Railing];
[zombieView setUserInteractionEnabled:TRUE];
// double tap gesture recognizer
UITapGestureRecognizer *touch2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped2:)];
[touch2 setDelegate: self];
[touch2 setNumberOfTapsRequired: 2];
[zombieView addGestureRecognizer:touch2];
//tap gesture recognizer
UITapGestureRecognizer *touch = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[touch setDelegate:self];
[touch setNumberOfTapsRequired: 1];
[zombieView addGestureRecognizer:touch];
//This makes the Person move down until he is behind the railing
[UIView animateWithDuration:8.5
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveLinear
animations:^{
CGAffineTransform transform= CGAffineTransformMakeTranslation(0,-200);
zombieView.transform = transform;
}
completion:nil];
};
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
This is my .h file:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface AbcViewController : UIViewController <UIGestureRecognizerDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *Railing;
//#property (strong, nonatomic) IBOutlet UIImageView *Person;
#property (strong, nonatomic) IBOutlet UIImageView *zombieView;
#property (strong, nonatomic) IBOutlet UIImage *zombie;
-(void) tapped:(UITapGestureRecognizer *)recognizer;
-(void) tapped2:(UITapGestureRecognizer *)recognizer;
#end
Every time I click it in mid-animation I get an error but when it's complete it works fine. I am fairly new to this so I'm sure it's simple, it always is. But, thank you for your patience and answers!
The object during the animation is not where you see it. It has already moved to its final position. Animation is an illusion: the "presentation layer" is animated, but the underlying "model layer" (the real object) stands still and has already moved when the animation starts. The model layer is the one inside a view so it is the only one that can be tapped.
Tapping an object while it is being animated is therefore a very tricky problem. I discuss it here:
http://www.apeth.com/iOSBook/ch18.html#_hit_testing_during_animation
Perhaps that discussion will give you some ideas. But no matter what, this is not going to be easy.
(Consider that perhaps you should not be using view animation for this kind of game. Sprite Kit was invented for just this sort of thing.)

How to dismiss keyboard when an UIControl is touched?

This has been asked a few times, but I don't seem to get it.
I have a view controller, with two textfields, one segmented control, a date picker and a few labels.
I want to dismiss the keyboard, when the user clicks the background or the segmented control or the date picker.
Here is my .h file:
#interface MRPatientenViewController : UIViewController
#property (nonatomic, strong) MRPatientenTableViewController *delegate;
- (IBAction)textFieldReturn:(id)sender;
#property (strong, nonatomic) IBOutlet UITextField *nachnameTextField;
#property (strong, nonatomic) IBOutlet UITextField *vornameTextField;
#property (strong, nonatomic) IBOutlet UIDatePicker *geburtsdatumPicker;
#property (strong, nonatomic) IBOutlet UISegmentedControl *genderSegmentedControl;
#end
this is my .m file:
-(IBAction)textFieldReturn:(id)sender{
[sender resignFirstResponder];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
if ([_nachnameTextField isFirstResponder] && [touch view] != _nachnameTextField) {
[_nachnameTextField resignFirstResponder];
}
else if ([_vornameTextField isFirstResponder] && [touch view] != _vornameTextField) {
[_vornameTextField resignFirstResponder];
}
[super touchesBegan:touches withEvent:event];
}
Now this dismisses the keyboard, if the background or the labels are touched.
But how do I dismiss the keyboard if the UISegmentedControl or the datepicker is touched?
You Touch code is correct but it also working fine in my code.when you click outside of text-field at that time Touch event call but its inner condition is not working good.i remove the condition and check its working fine.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[nachnameTextField resignFirstResponder];
[super touchesBegan:touches withEvent:event];
}
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[geburtsdatumPicker addGestureRecognizer:tap];
[genderSegmentedControl addGestureRecognizer:tap];
[self.view addGestureRecognizer:tap];
Then resign keyboard inside the selector
-(void) dismissKeyboard
{
[nachnameTextField resignFirstResponder];
[vornameTextField resignFirstResponder];
}
Have you tried following line of code
[textfieldInFocus resignFirstResponder];
You can do the following:
UITapGestureRecognizer *tapGesture=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapAction)];
tapGesture.delegate=self;
[self.view addGestureRecognizer:tapGesture];
- (void)tapAction
{
[nachnameTextField resignFirstResponder];
[vornameTextField resignFirstResponder];
}
and for UISegmentedControl or UIDatePicker you probably have their own selector methods for example:
For UISegmentedControl :
- (IBAction)mainSegmentControl:(UISegmentedControl *)segment{
}
or For UIDatePicker :
- (void)changeDate:(UIDatePicker *)sender {
}
just call your method [self tapAction]; in both above methods and you are good to go...!!
This is the solution which worked for me: the MRViewController.h file:
#import <UIKit/UIKit.h>
#interface MRViewController : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UITextField *textField;
#property (strong, nonatomic) IBOutlet UISegmentedControl *segmentedControl;
#end
The MRViewController.m file:
- (void)viewDidLoad
{
[super viewDidLoad];
[self hideKeyboardWhenBackgroundIsTapped];
self.textField.delegate = self;
}
-(void)hideKeyboardWhenBackgroundIsTapped{
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
[tgr setCancelsTouchesInView:NO];
[self.view addGestureRecognizer:tgr];
}
-(void)hideKeyboard{
[self.view endEditing:YES];
}
And in my storyboard scene, I got a UITextField and a UISegmentedControl.

Can't zoom UIScrollView on iOS 6

There is my .m code.
#import "ScrollZoomViewController.h"
#interface ScrollZoomViewController () <UIScrollViewDelegate>
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#end
#implementation ScrollZoomViewController
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
NSLog(#"zooming");
return self.imageView;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView.minimumZoomScale = 0.5f;
self.scrollView.maximumZoomScale = 5.0f;
self.scrollView.delegate = self;
self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);
self.scrollView.contentSize = self.imageView.image.size;
}
I'm using Xcode 4.5 and iOS 6.0 and AutoLayout closed.
Image can scroll but can't zoom. Is this because iOS 6?
You need set value for zoomScale property so as to start zooming.
Add following line after setting contentSize of scrollView.
self.scrollView.zoomScale = minimumZoomScale;
Try to remove this code:
self.scrollView.contentSize = self.imageView.image.size;
and add more content size, instead of image size.
Ex: you need to add like self.scrollView.contentSize = CGSizeMake(1770, 2346);
Hope this will solve.

Resources