When I use swipe gesture on the screen the label on the screen it didn't update the content and the number stop at 120, after I declare:
#property (weak, nonatomic) UILabel *label;
when I swipe the screen then it appear error on the Xcode,
If someone can help me to solve this problem I will really appreciate it
#interface ViewController ()
{
double numOfSpeed;
}
#property (weak, nonatomic) UILabel *label;
#end
implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
numOfSpeed = 120;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(200, 300, 100, 100)];
label.text =[NSString stringWithFormat:#"%.0f", numOfSpeed];
label.backgroundColor = UIColor.blueColor;
[self.view addSubview:label];
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeToControlTheSpeedOfRhythm:)];
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeToControlTheSpeedOfRhythm:)];
UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeToControlTheSpeedOfRhythm:)];
UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeToControlTheSpeedOfRhythm:)];
[swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[swipeLeft setDirection:UISwipeGestureRecognizerDirectionLeft];
[swipeUp setDirection:UISwipeGestureRecognizerDirectionUp];
[swipeDown setDirection:UISwipeGestureRecognizerDirectionDown];
[swipeLeft setNumberOfTouchesRequired:1];
[swipeRight setNumberOfTouchesRequired:1];
[swipeUp setNumberOfTouchesRequired:1];
[swipeDown setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:swipeLeft];
[self.view addGestureRecognizer:swipeUp];
[self.view addGestureRecognizer:swipeDown];
[self.view addGestureRecognizer:swipeRight];
}
- (void)swipeToControlTheSpeedOfRhythm:(UISwipeGestureRecognizer *)sender
{
NSLog(#"gesture respone");
if(sender.direction == UISwipeGestureRecognizerDirectionLeft)
{
numOfSpeed -= 10;
self.label.text = [NSString stringWithFormat:#"%.0f", numOfSpeed];
NSLog(#"gesture Left respone");
}else if (sender.direction == UISwipeGestureRecognizerDirectionDown){
numOfSpeed -= 10;
self.label.text = [NSString stringWithFormat:#"%.0f", numOfSpeed];
NSLog(#"gesture down respone");
}else if (sender.direction==UISwipeGestureRecognizerDirectionUp){
numOfSpeed += 10;
self.label.text = [NSString stringWithFormat:#"%.0f", numOfSpeed];
NSLog(#"gesture up respone");
}else if(sender.direction==UISwipeGestureRecognizerDirectionRight){
numOfSpeed += 10;
self.label.text = [NSString stringWithFormat:#"%.0f", numOfSpeed];
NSLog(#"gesture right respone");
}
}
#end
You should init your UILabel like this:
self.label = [[UILabel alloc] initWithFrame:CGRectMake(200, 300, 100, 100)];
Then use self.label through all your code. The problem is that your label property is not being assigned inside your viewDidLoad code.
Edit
And use a strong reference in your UILabel property unless you're using #IBOutlets.
Remove "UILabel *" from
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(200, 300, 100, 100)];
Related
How to add CollectionView in NSObject controller?
I have one NSObject controller which i am accessing on each ViewController. I already added some component on it like image view. Now I want to add CollectionView on it. I have written code as follows:
in AboutMe.h file
#interface AboutMe : NSObject<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
-(UIButton *) showAboutMeView:(UIViewController *)id;
#end
and in AboutMe.m file
#import "AboutMe.h"
#implementation AboutMe {
UIView *objMessageView;
UICollectionView *_collectionView
NSMutableArray *arrstrProfileImage;
NSMutableArray *arrstrUsersNameEn;
NSMutableArray *arrstrUsersNameMr;
}
-(UIButton *) showAboutMeView:(UIViewController *)id {
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenX = screenRect.origin.x;
CGFloat screenY = screenRect.origin.y;
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
arrstrProfileImage = [[NSMutableArray alloc] initWithObjects:#"male.png",#"female.png",nil];
arrstrUsersNameEn = [[NSMutableArray alloc] initWithObjects:#"Mr. (Corporator)",#"Mrs.(Corporator)", nil];
objMessageView = [[UIView alloc] initWithFrame:CGRectMake(screenX, screenY, screenWidth,screenHeight-64)];
objMessageView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:.8f];
[id.view addSubview:objMessageView];
UIImageView *objUIImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, screenWidth, 150)];
objUIImageView.image = [UIImage imageNamed:#"abc.png"];
objUIImageView.contentMode = UIViewContentModeScaleAspectFit;
[objMessageView addSubview:objUIImageView];
UIButton *objUIButtonOk = [[UIButton alloc] initWithFrame:CGRectMake(screenX, screenHeight-120, screenWidth, 50)];
[objUIButtonOk setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
objUIButtonOk.titleLabel.font = [UIFont boldSystemFontOfSize:25];
[objUIButtonOk setTitle:#"OK" forState:UIControlStateNormal];
[objMessageView addSubview:objUIButtonOk];
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
_collectionView=[[UICollectionView alloc] initWithFrame:CGRectMake(objMessageView.frame.origin.x+10, objUIImageView.frame.origin.y+objUIImageView.frame.size.height+5, objMessageView.frame.size.width-20, objUIButtonOk.frame.origin.y-(objUIImageView.frame.origin.y+objUIImageView.frame.size.height+25)) collectionViewLayout:layout];
[_collectionView setDataSource:self];
[_collectionView setDelegate:self];
_collectionView.showsVerticalScrollIndicator = NO;
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[_collectionView setBackgroundColor:[UIColor gray]];
[objMessageView addSubview:_collectionView];
return objUIButtonOk;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return arrstrProfileImage.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
UIImageView *objUIImageView;
UILabel *objUILabel;
for (UILabel *lbl in cell.contentView.subviews)
{
if ([lbl isKindOfClass:[UILabel class]])
{
[lbl removeFromSuperview];
}
}
for (UIImageView *img in cell.contentView.subviews)
{
if ([img isKindOfClass:[UIImageView class]])
{
[img removeFromSuperview];
}
}
cell.backgroundColor=[UIColor lightGrayColor];
cell.layer.cornerRadius = 3;
cell.layer.masksToBounds = YES;
objUIImageView = [[UIImageView alloc] initWithFrame:CGRectMake(cell.contentView.frame.size.width/2-50, cell.contentView.frame.origin.y+25, 100, 100)];
objUIImageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#",[arrstrProfileImage objectAtIndex:indexPath.row]]];
objUIImageView.contentMode = UIViewContentModeScaleAspectFit;
[cell.contentView addSubview:objUIImageView];
objUILabel = [[UILabel alloc] initWithFrame:CGRectMake(cell.contentView.frame.origin.x+5, objUIImageView.frame.size.height+20, cell.contentView.frame.size.width-10, cell.contentView.frame.size.height - (objUIImageView.frame.size.height+20))];
objUILabel.backgroundColor = [UIColor clearColor];
objUILabel.textAlignment = NSTextAlignmentCenter;
objUILabel.numberOfLines = 0;
objUILabel.lineBreakMode = NSLineBreakByWordWrapping;
objUILabel.font = [UIFont boldSystemFontOfSize:16];
objUILabel.textColor = [UIColor blackColor];
if ([[NSString stringWithFormat:#"%#",[UserDefault objectForKey:#"lang"]] isEqualToString:#"M"]) {
objUILabel.text = [arrstrUsersNameMr objectAtIndex:indexPath.row];
}else{
objUILabel.text = [arrstrUsersNameEn objectAtIndex:indexPath.row];
}
[cell.contentView addSubview:objUILabel];
return cell;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(objMessageView.frame.size.width/2 -15,objMessageView.frame.size.width/2 -15);
}
#end
I am accessing this in ViewController as:
AboutMe *objAboutMe = [[AboutMe alloc] init];
UIButton *objBtn = [objAboutMe showAboutMeView:self];
[objBtn addTarget:self action:#selector(click:) forControlEvents:UIControlEventTouchUpInside];
A blank white view get loaded.
Here Problem is I am not able to set Delegate to CollectionView.
Please Help me in this.
You're CollectionView delegate won't work unless you change inheritation of your AboutMe class.
So you need to update this line and inherit from UIViewController:
#interface AboutMe : UICollectionViewController <UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
Also I would make an additional suggestion. When working with method like this:
-(UIButton *) showAboutMeView:(UIViewController *)id {
Try to mantain only that code, that is related to creation and returning UIButton, so for example instantiation and operations with objMessageView could be placed in another method, etc.
Here is my code:
#interface UserProfileViewController : UIViewController<UIGestureRecognizerDelegate>{
}
#property (nonatomic, retain) UILabel *myLabel;
#property (nonatomic, retain) UIImageView *imageView;
#end
#implementation UserProfileViewController
#synthesize myLabel;
#synthesize imageView;
- (void)viewDidLoad
{
[super viewDidLoad];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
scrollView.contentSize = CGSizeMake(320, 700);
scrollView.clipsToBounds = YES;
[scrollView setUserInteractionEnabled:YES];
myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];
myLabel.text = #"Kim Gysen";
myLabel.center = CGPointMake(CGRectGetWidth(self.view.bounds)/2.0f, 25);
myLabel.textAlignment = NSTextAlignmentCenter;
myLabel.textColor = [UIColor whiteColor];
[myLabel setBackgroundColor:[UIColor clearColor]];
self.imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 140, 180)];
self.imageView.center = CGPointMake(CGRectGetWidth(self.view.bounds)/2.0f, 150);
UIImage *image = [UIImage imageNamed: #"ProfilePic.jpeg"];
[imageView setImage:image];
//Long press
self.imageView.userInteractionEnabled = YES;
UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPressFrom:)];
longPressGestureRecognizer.delegate = self;
[self.imageView addGestureRecognizer:longPressGestureRecognizer];
[scrollView addSubview:myLabel];
[scrollView addSubview:imageView];
[self.view addSubview:scrollView];
}
- (void) handleLongPressFrom: (UISwipeGestureRecognizer *)recognizer
{
CGPoint location = [recognizer locationInView:self.view];
NSLog(#"Tap Gesture Coordinates: %.2f %.2f", location.x, location.y);
if(UIGestureRecognizerStateBegan == recognizer.state)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Gesture Recognizer Demo"
message:#"Long Press Gesture performed"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[alert show];
}
}
I get no errors in my ViewDidLoad, but the BAD_EXC_ACCESS error appears on the long press, before the method is actually fired. I understood that I'm leaking somewhere but where?
I'm using ARC...
You should make a property in your main view controller (typed strong) that points to the ProfileViewController then use:
self.profileView = [[UserProfileViewController alloc] init];
[self.view addSubview: self.profileView.view];
I have faced one issue to display UIPickerView with a Done button in Ipad.
I done detailed researches though many links and blogs and got the suggestion as "display the UIPickerView from an UIActionSheet"
I saw many posts related this, however there is no good answers.So please dont close it as a duplicate.
Also i was able to get some good codes to do it and it worked fine in my Iphone devices.
However i were found a difficulty in Ipad devices.
The Action-Sheet is not displaying as a full view.
Please see the below screenshot.this was the result!!!
The code is used to do this is pasted below.
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:nil
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 40, 0, 0);
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
[actionSheet addSubview:pickerView];
[pickerView release];
UISegmentedControl *closeButton = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObject:#"Close"]];
closeButton.momentary = YES;
closeButton.frame = CGRectMake(260, 7.0f, 50.0f, 30.0f);
closeButton.segmentedControlStyle = UISegmentedControlStyleBar;
closeButton.tintColor = [UIColor blackColor];
[closeButton addTarget:self action:#selector(dismissActionSheet:) forControlEvents:UIControlEventValueChanged];
[actionSheet addSubview:closeButton];
[closeButton release];
[actionSheet showInView:[[UIApplication sharedApplication] keyWindow]];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
Then I have downloaded a excellent sample application from github through sample pickers
After the download, i have copied the classes only mandatory for me to my application.
The method they are using to show the UIPickerView+Done button through Action-Sheet is described below
ActionStringDoneBlock done = ^(ActionSheetStringPicker *picker, NSInteger selectedIndex, id selectedValue) {
if ([myLabel respondsToSelector:#selector(setText:)]) {
[myLabel performSelector:#selector(setText:) withObject:selectedValue];
}
};
ActionStringCancelBlock cancel = ^(ActionSheetStringPicker *picker) {
NSLog(#"Block Picker Canceled");
};
NSArray *colors = [NSArray arrayWithObjects:#"Red", #"Green", #"Blue", #"Orange", nil];//picker items to select
[ActionSheetStringPicker showPickerWithTitle:#"Select a Block" rows:colors initialSelection:0 doneBlock:done cancelBlock:cancel origin:myButton];
In the last line of code they have used the parameter as origin: and we can pass any objects (button,label etc) to it.
The Action-sheet will take origin as the passed object.
Here my issue came again :). I have used segment control to pick the time as per my conditions.
if i give mySegment as the origin parameter,the Action-sheet origin arrow will display from middle of my segment control.Not from the selected tab ,which is too bad and will give confusion to my valuable users.
So i have added individual labels under the segment sections and given it for the origin parameter of the mentioned method and i fixed my issue.
However i know its not a good fix :)
May i know is there any easy way to do it?
Is Apple support ActionSheet+UIPickerView+DoneButton in Ipad?
Any help on this issue is Appreciated
-(void)viewDidload
{
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.frame = CGRectMake(165,165, 135,35);
[button1 setTitle:#"Type #" forState:UIControlStateNormal];
[button1 addTarget:self action:#selector(button1) forControlEvents:UIControlEventTouchUpInside];
[s addSubview:button1];
}
-(void)button1
{
items1 =[[NSMutableArray alloc]initWithObjects:#"H",#"E",#"T",#"K",nil];
myPickerView1 =[[UIPickerView alloc] initWithFrame:CGRectMake(60,80,200,300)];
myPickerView1.transform = CGAffineTransformMakeScale(0.75f, 0.75f);
myPickerView1.delegate = self;
myPickerView1.dataSource = self;
myPickerView1.showsSelectionIndicator = YES;
myPickerView1.backgroundColor = [UIColor clearColor];
myPickerView1.tag=1;
[myPickerView1 selectRow:1 inComponent:0 animated:YES];
[self.view addSubview:myPickerView1];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
{
switch (pickerView.tag)
{
case 1:
return [items1 count];
break;
case 2:
return [items2 count];
break;
}
return 0;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
switch (pickerView.tag)
{
case 1:
return[items1 objectAtIndex:row];
break;
case 2:
return[items2 objectAtIndex:row];
break;
}
return 0;
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
switch (pickerView.tag)
{
case 1:
{
[button1 setTitle:[items1 objectAtIndex:row] forState:UIControlStateNormal];
}
break;
case 2:
{
[button2 setTitle:[items2 objectAtIndex:row] forState:UIControlStateNormal];
}break;
}
pickerView.hidden = YES;
}
You have to use UIPopOverController.
First, create a UIPickerViewController for iPhone. You need it for the nib, which will be pushed into the popOver. Initialize the picker in ViewWithPicker
.h
#import <UIKit/UIKit.h>
#class ViewWithPickerController;
#protocol PopoverPickerDelegate
#required
- (void) viewWithPickerController:(ViewWithPickerController*) viewWithPickerController didSelectValue:(NSString*) value;
#end
#interface ViewWithPickerController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> {
IBOutlet UIPickerView *pickerView;
id<PopoverPickerDelegate> delegate;
NSMutableArray *array;
}
#property(nonatomic, retain) IBOutlet UIPickerView *pickerView;
#property(nonatomic, assign) id<PopoverPickerDelegate> delegate;
#end
.m, after you initialized the array in viewDidLoad, picker methods:
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)picker {
return 1;
}
// returns the number of rows in each component.
- (NSInteger)pickerView:(UIPickerView *)picker numberOfRowsInComponent:(NSInteger)component {
return [array count];
}
//returns the string value for the current row
- (NSString *)pickerView:(UIPickerView *)picker titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [array objectAtIndex:row];
}
//handle selection of a row
- (void)pickerView:(UIPickerView *)picker didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
NSString *value = [pickerView.delegate pickerView:picker titleForRow:row forComponent:component];
//notify the delegate about selecting a value
if(delegate != nil)
[delegate viewWithPickerController:self didSelectValue:value];
}
Then, import the viewWithPicker into your main class, create a button and give it this action:
- (IBAction) showPickerPopupAction:(id) sender {
self.viewWithPickerController = [[[ViewWithPickerController alloc] initWithNibName:#"ViewWithPicker" bundle:[NSBundle mainBundle]] autorelease];
viewWithPickerController.contentSizeForViewInPopover =
CGSizeMake(viewWithPickerController.view.frame.size.width, viewWithPickerController.view.frame.size.height);
viewWithPickerController.delegate = self;
self.popoverController = [[[UIPopoverController alloc]
initWithContentViewController:viewWithPickerController] autorelease];
[self.popoverController presentPopoverFromRect:popoverButtonForPicker.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
popoverController.delegate = self;
}
And to select a specific value
- (void) viewWithPickerController:(ViewWithPickerController*) viewWithPickerController didSelectValue:(NSString*) value
{
yourLabel.text = [NSString stringWithFormat:#"%# ",value];
}
Use UIPopoverController for done button in picker, create a view controller class in which take a picker and add navigation cancel and done button.
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:nextViewController];
_datePickerPopover = [[UIPopoverController alloc] initWithContentViewController:navigationController];
nextViewController.datePickerPopover = _datePickerPopover;
_datePickerPopover.delegate=self;
[_datePickerPopover setPopoverContentSize:CGSizeMake(320, 453) animated:NO];
if (isSearchOpen) {
[_datePickerPopover presentPopoverFromRect:CGRectMake(btn.frame.origin.x+10+245, btn.frame.origin.y+100-scrollPointY, 44, 44) inView:self.splitViewController.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
else
{
[_datePickerPopover presentPopoverFromRect:CGRectMake(btn.frame.origin.x+10+245, btn.frame.origin.y+55, 44, 44) inView:self.splitViewController.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];//
}
Try out below code for UIPicker View in iPad
-(IBAction)tDriveBtnPressed:(id)sender
{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
txtDate.text = [NSString stringWithFormat:#"%#",
[df stringFromDate:[NSDate date]]];
[df release];
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 300, 44)];
pickerToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDone:)];
[barItems addObject:doneBtn];
[doneBtn release];
[pickerToolbar setItems:barItems animated:YES];
[barItems release];
datePicker = [[UIDatePicker alloc] init];
datePicker.datePickerMode = UIDatePickerModeDate;
CGRect pickerRect = datePicker.bounds;
datePicker.bounds = pickerRect;
UIViewController* popoverContent = [[UIViewController alloc] init];
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 344)];
popoverView.backgroundColor = [UIColor whiteColor];
datePicker.frame = CGRectMake(0, 44, 320, 300);
[datePicker addTarget:self action:#selector(dateChange:) forControlEvents:UIControlEventValueChanged];
[popoverView addSubview:pickerToolbar];
[popoverView addSubview:datePicker];
popoverContent.view = popoverView;
//resize the popover view shown
//in the current view to the view's size
popoverContent.contentSizeForViewInPopover = CGSizeMake(320, 244);
//create a popover controller
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
CGRect popoverRect = [self.view convertRect:[tDriveBtn frame]
fromView:[tDriveBtn superview]];
popoverRect.size.width = MIN(popoverRect.size.width, 100) ;
popoverRect.origin.x = popoverRect.origin.x;
// popoverRect.size.height = ;
[popoverController
presentPopoverFromRect:popoverRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
//release the popover content
[popoverView release];
[popoverContent release];
}
-(void)dateChange:(id)sender
{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
txtDate.text= [NSString stringWithFormat:#"%#",
[df stringFromDate:datePicker.date]];
[df release];
}
- (void)pickerDone:(id)sender
{
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
txtDate.text= [NSString stringWithFormat:#"%#",
[df stringFromDate:datePicker.date]];
[df release];
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
self.popoverController=nil;
}
}
I'm trying to connect a gesture to a UIView so I can tap on the object, but it is not working. What am I doing wrong?
Shape.h
#import <UIKit/UIKit.h>
#interface Shape : UIView;
- (id) initWithX: (int)xVal andY: (int)yVal;
#end
Shape.m
#import "Shape.h"
#implementation Shape
- (id) initWithX:(int )xVal andY:(int)yVal {
self = [super init];
UIView *shape = [[UIView alloc] initWithFrame:CGRectMake(xVal, yVal, 10, 10)];
shape.backgroundColor = [UIColor redColor];
shape.userInteractionEnabled = YES;
[self addSubview:shape];
return self;
}
#end
MODIFIED CODE: The following code is in the main ViewController. I have removed the UITapGestureRecognizer from the Shape class. The code works if I make the following change, but then it is 'box' that responds to the tap gesture, not 'shape':
[shape addGestureRecognizer:tap];
to
[box addGestureRecognizer:tap];
- (void)handlerTap:(UITapGestureRecognizer *)recognizer {
//CGPoint location = [recognizer locationInView:[recognizer.view superview]];
NSLog(#"Success");
}
-(void)drawShapes{
NSLog(#"Draw");
if(!box){
box = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight-100)];
box.backgroundColor = [UIColor colorWithRed: 0.8 green: 0.8 blue: 0.0 alpha:0.2];
[self.view addSubview:box];
}
for (int i = 0; i<5; i++) {
int x = arc4random() % screenWidth;
int y = arc4random() % screenHeight;
Shape * shape =[[Shape alloc] initWithX:x andY:y ];
[box addSubview:shape];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
[tap setNumberOfTapsRequired:1];
[tap addTarget:self action:#selector(handlerTap:)];
[box addGestureRecognizer:tap];
}
}
SOLUTION: I have learned that
self = [super init];
needs to be changed to include a CGRECT that defines the boundaries of the view that *shape is placed into.
self = [super initWithFrame:CGRectMake(xVal, yVal, 10, 10)];
Also, *shape needs to be placed at 0,0 to ensure its correct placement within its parent.
UIView *shape = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
#import "Shape.h"
#implementation Shape
- (id) initWithX:(int )xVal andY:(int)yVal {
self = [super initWithFrame:CGRectMake(xVal, yVal, 10, 10)];
UIView *shape = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
shape.backgroundColor = [UIColor redColor];
shape.userInteractionEnabled = YES;
[self addSubview:shape];
return self;
}
#end
You should set the target of the gesture recognizer to self, not the view, because you implemented the handlerTap: method in the Shape class.
I am trying to implement a "Done" button in a UIPickerView Similar to the one under this link
I looked in the class reference but I couldn t find it
Thanks
The easiest way to do it is to model it in Interface Builder. It is a UIView containing a UIToolbar and a UIPickerView.
Then create an outlet for the UIView and connect it.
If you then have a UITextField you can assign your custom view to its inputView property.
[self.textField setInputView:self.customPicker];
Alternatively you can add the picker to your main view...
- (void)viewDidLoad
{
[super viewDidLoad];
self.customPicker.frame = CGRectMake(0, CGRectGetMaxY(self.view.frame), CGRectGetWidth(self.customPicker.frame), CGRectGetHeight(self.customPicker.frame));
[self.view addSubview:self.customPicker];
}
... and then use this method to show or hide the picker.
- (void)setPickerHidden:(BOOL)hidden
{
CGAffineTransform transform = hidden ? CGAffineTransformIdentity : CGAffineTransformMakeTranslation(0, -CGRectGetHeight(self.customPicker.frame));
[UIView animateWithDuration:0.3 animations:^{
self.customPicker.transform = transform;
}];
}
I added a UIToolbar with a UIBarButtonItem for the 'done' button in my xib with the frame set so that it's not initially visible (y value equal to the height of the parent view).
Every time the user access the picker, I changed the frame (the y value) of the UIDatePicker and the UIToolbar with an animation so that it slides up along with the picker from the bottom of the screen similar to the keyboard.
Check out my code below.
- (IBAction)showPicker
{
if(pickerVisible == NO)
{
// create the picker and add it to the view
if(self.datePicker == nil) self.datePicker = [[[UIDatePicker alloc] initWithFrame:CGRectMake(0, 460, 320, 216)] autorelease];
[self.datePicker setMaximumDate:[NSDate date]];
[self.datePicker setDatePickerMode:UIDatePickerModeDate];
[self.datePicker setHidden:NO];
[self.view addSubview:datePicker];
// the UIToolbar is referenced 'using self.datePickerToolbar'
[UIView beginAnimations:#"showDatepicker" context:nil];
// animate for 0.3 secs.
[UIView setAnimationDuration:0.3];
CGRect datepickerToolbarFrame = self.datePickerToolbar.frame;
datepickerToolbarFrame.origin.y -= (self.datePicker.frame.size.height + self.datePickerToolbar.frame.size.height);
self.datePickerToolbar.frame = datepickerToolbarFrame;
CGRect datepickerFrame = self.datePicker.frame;
datepickerFrame.origin.y -= (self.datePicker.frame.size.height + self.datePickerToolbar.frame.size.height);
self.datePicker.frame = datepickerFrame;
[UIView commitAnimations];
pickerVisible = YES;
}
}
- (IBAction)done
{
if(pickerVisible == YES)
{
[UIView beginAnimations:#"hideDatepicker" context:nil];
[UIView setAnimationDuration:0.3];
CGRect datepickerToolbarFrame = self.datePickerToolbar.frame;
datepickerToolbarFrame.origin.y += (self.datePicker.frame.size.height + self.datePickerToolbar.frame.size.height);
self.datePickerToolbar.frame = datepickerToolbarFrame;
CGRect datepickerFrame = self.datePicker.frame;
datepickerFrame.origin.y += (self.datePicker.frame.size.height + self.datePickerToolbar.frame.size.height);
self.datePicker.frame = datepickerFrame;
[UIView commitAnimations];
// remove the picker after the animation is finished
[self.datePicker performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:0.3];
}
}
I create a custom class, this supports multiple orientation:
DateTimePicker.h
#interface DateTimePicker : UIView {
}
#property (nonatomic, assign, readonly) UIDatePicker *picker;
- (void) setMode: (UIDatePickerMode) mode;
- (void) addTargetForDoneButton: (id) target action: (SEL) action;
#end
DateTimePicker.m
#define MyDateTimePickerToolbarHeight 40
#interface DateTimePicker()
#property (nonatomic, assign, readwrite) UIDatePicker *picker;
#property (nonatomic, assign) id doneTarget;
#property (nonatomic, assign) SEL doneSelector;
- (void) donePressed;
#end
#implementation DateTimePicker
#synthesize picker = _picker;
#synthesize doneTarget = _doneTarget;
#synthesize doneSelector = _doneSelector;
- (id) initWithFrame: (CGRect) frame {
if ((self = [super initWithFrame: frame])) {
self.backgroundColor = [UIColor clearColor];
UIDatePicker *picker = [[UIDatePicker alloc] initWithFrame: CGRectMake(0, MyDateTimePickerToolbarHeight, frame.size.width, frame.size.height - MyDateTimePickerToolbarHeight)];
[self addSubview: picker];
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame: CGRectMake(0, 0, frame.size.width, MyDateTimePickerToolbarHeight)];
toolbar.barStyle = UIBarStyleBlackOpaque;
toolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle: #"Done" style: UIBarButtonItemStyleBordered target: self action: #selector(donePressed)];
UIBarButtonItem* flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
toolbar.items = [NSArray arrayWithObjects:flexibleSpace, doneButton, nil];
[self addSubview: toolbar];
self.picker = picker;
picker.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
self.autoresizesSubviews = YES;
self.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
}
return self;
}
- (void) setMode: (UIDatePickerMode) mode {
self.picker.datePickerMode = mode;
}
- (void) donePressed {
if (self.doneTarget) {
[self.doneTarget performSelector:self.doneSelector withObject:nil afterDelay:0];
}
}
- (void) addTargetForDoneButton: (id) target action: (SEL) action {
self.doneTarget = target;
self.doneSelector = action;
}
Using custom view in your view controller:
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(buttonPressed:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Show picker" forState:UIControlStateNormal];
button.frame = CGRectMake(100, 50, 100, 40.0);
[self.view addSubview:button];
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
picker = [[DateTimePicker alloc] initWithFrame:CGRectMake(0, screenHeight/2 - 35, screenWidth, screenHeight/2 + 35)];
[picker addTargetForDoneButton:self action:#selector(donePressed)];
[self.view addSubview:picker];
picker.hidden = YES;
[picker setMode:UIDatePickerModeDate];
}
-(void)donePressed {
picker.hidden = YES;
}
-(void)buttonPressed:(id)sender {
picker.hidden = NO;
}
Hope this helps. :)
There is a more elegant solution. I'm not sure if this is recent (as of iOS7), but this has been working for me splendidly.
TJDatePicker.h
#protocol TJDatePickerActionDelegate <NSObject>
- (void)cancel:(id)sender;
- (void)done:(id)sender;
#end
#interface TJDatePicker : UIDatePicker
#property (strong, nonatomic) UIView *navInputView;
#property (weak, nonatomic) id<TJDatePickerActionDelegate> actionDelegate;
#end
TJDatePicker.m
#import "TJDatePicker.h"
#interface TJDatePicker ()
#property (strong, nonatomic) TJButton *cancelButton;
#property (strong, nonatomic) TJButton *doneButton;
#end
#implementation TJDatePicker
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self updateSubviews];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self updateSubviews];
}
- (void)updateSubviews
{
self.navInputView.frame = CGRectMake(0, 0, self.width, 45);
self.cancelButton.frame = CGRectMake(5, 5, 80, 35);
CGFloat width = 80;
self.doneButton.frame = CGRectMake(CGRectGetMaxX(self.navInputView.frame) - width, self.cancelButton.frame.origin.y, width, self.cancelButton.height);
}
- (UIView *)navInputView
{
if (!_navInputView)
{
_navInputView = [[UIView alloc] init];
_navInputView.backgroundColor = [UIColor whiteColor];
self.cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.cancelButton setTitle:#"CANCEL" forState:UIControlStateNormal];
[self.cancelButton addTarget:self action:#selector(cancelButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_navInputView addSubview:self.cancelButton];
self.doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.doneButton setTitle:#"DONE" forState:UIControlStateNormal];
[self.doneButton addTarget:self action:#selector(doneButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[_navInputView addSubview:self.doneButton];
}
return _navInputView;
}
- (void)cancelButtonPressed
{
[self.actionDelegate cancel:self];
}
- (void)doneButtonPressed
{
[self.actionDelegate done:self];
}
And then at implementation time...
self.datePicker = [[TJDatePicker alloc] init];
self.datePicker.actionDelegate = self;
self.textField.inputAccessoryView = self.datePicker.navInputView;
The key here is to use the inputAccessoryView of the UITextField that you are planning on setting the UIDatePicker to.
You get the "Done" button in the toolbar using the ActionSheetPicker. Its is a great alternative to building it yourself.
https://github.com/skywinder/ActionSheetPicker-3.0
Success! Ok, I would never suggest doing this, but here's where the done button is created in your particular tutorial code:
Looking at the storyboard, we can see that when you click the "Role" box within "AddPersonTVC.h" (class at the top right of the storyboard), it pops up a class called "RollPickerTVCell.h"
Looking into RollPickerTVCell.h, we notice that the whole class is a subclass of "CoreDataTableViewCell"
#interface RolePickerTVCell : CoreDataTableViewCell <UIPickerViewDataSource, UIPickerViewDelegate>
Looking at the class "CoreDataTableViewCell.m", we finally find our uibarbuttonitem!
UIBarButtonItem *doneBtn =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(done:)];
In case you are working on a Table View Cell and you are not using a UITextField (hence you won't be using the Accessory View), here's what I did:
I created a table view cell called GWDatePickerCell that looks like this (no .nib files involved).
GWDatePickerCell.h:
#import <UIKit/UIKit.h>
#interface GWDatePickerCell : UITableViewCell
#property (nonatomic, strong) UIDatePicker *datePicker;
#property (nonatomic, strong) UIToolbar *toolbar;
#property (nonatomic, strong) UIBarButtonItem *buttonDone;
#end
GWDatePickerCell.m:
#import "GWDatePickerCell.h"
#implementation GWDatePickerCell
- (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if(!(self=[super initWithStyle:style reuseIdentifier:reuseIdentifier])) return nil;
_datePicker = [[UIDatePicker alloc] init];
[_datePicker setMinuteInterval:5];
[_datePicker setDatePickerMode:UIDatePickerModeDateAndTime];
[self.contentView addSubview:_datePicker];
_toolbar = [[UIToolbar alloc] init];
_buttonDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:nil action:nil];
_toolbar.items = #[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], _buttonDone];
[self.contentView addSubview:_toolbar];
return self;
}
- (void)layoutSubviews{
[super layoutSubviews];
CGRect r = self.contentView.bounds;
r.origin.y +=44;
r.size.height = 216;
CGRect tb = self.contentView.bounds;
tb.size.height = 44;
_datePicker.frame = r;
_toolbar.frame = tb;
}
#end
Now all I had to do when creating the cells in the Table View:
Specify the #selector for the Done button.
Set the correct cell height in heightForRowAtIndexPath