Issue with custom number pad in iOS app - ios

I have an app with a custom number pad. I need the custom number pad for some, but not all of the text fields on a preferences view. I have written this method to set up the number pad for certain text fields:
-(void)setNumberPadFor:(UITextField*)textField andNibName:(NSString *)nibNamed{
textField.inputView = [[[NSBundle mainBundle] loadNibNamed:nibNamed
owner:self
options:nil] lastObject];
UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleDone
target:textField
action:#selector(resignFirstResponder)];
UIToolbar *tips = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
tips.barStyle = UIBarStyleBlackOpaque;
[tips setBackgroundColor:[UIColor blueColor]];
[tips setTintColor:[UIColor whiteColor]];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
[tips sizeToFit];
tips.items = [NSArray arrayWithObjects:spacer, btnDone, nil];
textField.inputAccessoryView = tips;
}
I am calling the setup method as follows (in viewDidLoad for the ViewController):
[self setNumberPadFor:txtMinFeet andNibName:#"PosNegNumberPad"];
[self setNumberPadFor:txtMaxFeet andNibName:#"PosNegNumberPad"];
So, in my button click events, how do I access the text field that initiated the number pad?
-(IBAction)btnNum1:(id)sender{
[[UIDevice currentDevice] playInputClick];
// update text field
}
-(IBAction)btnNum2:(id)sender{
[[UIDevice currentDevice] playInputClick];
// update text field
}
Eventually I will have two custom number pads to cover the requirements, but for now there is just one (hence one nib currently passed as a parameter).
My button actions are set up and working, that is, I can set a break point inside them and verify the app is responding to the events.
What I am unclear about is how to identify which text field initiated the number pad so I can update it accordingly.
Obviously I'm leaving something out. Any suggestions? Thanks!

One way is to use an ivar and every time you get the delegate method textFieldDidBeginEditing: you set the ivar. Later, you query the ivar to get the current text field.
The other way to do is is to find the first responder. This means traversing the subviews of your primary view to find it. This is common enough that you can find code to do that here for sure. The other way is the easiest to do.

Related

iOS/Objective-C: Add badge to custom UIBarButtonItem

This is now very common but I cannot find a way to add a badge to a custom, or non-system, UIBarButton Item.
The following will add a badge to a systemUIBarButtonItem. But it does not work for one created from an image, i.e. a custom one. I would like to avoid creating a dependency on a separate class and would really like to find something similar to this that works for a custom button. Thanks in advance for any suggestions.
This creates badge for systemButton such as a search button:
UIBarButtonItem *searchButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:#selector(searchButtonPressed)];
int badgeint = 4;
NSString *badgestring = [NSString stringWithFormat:#"%d",badgeint];
self.navigationItem.rightBarButtonItems = #[searchButton];
self.navigationItem.rightBarButtonItem.badgeValue = badgestring;
The same code for a custom button--there is no system button for notification so I need to use a custom image--does not produce the badge.
UIBarButtonItem *notificationButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"notification-32.png"] style:UIBarButtonItemStyleBordered target:self action:#selector(notificationButtonPressed)];
int badgeint = 4;
NSString *badgestring = [NSString stringWithFormat:#"%d",badgeint];
self.navigationItem.rightBarButtonItems = #[notificationButton];
self.navigationItem.rightBarButtonItem.badgeValue = badgestring;
Note: the reason I have barbuttonitems is that sometimes I use more than one)
Thanks for any suggestions
EDIT:
I found out that I made a stupid error--I set the value two different times. I thought the second would override the first, but apparently it confused it. There is no difference between system and custom buttons. I did discover, however, that if you have multiple buttons, the badge will always appear at the right of the group. Using this method, you can't seem to put the badge on a bar button item second in from right for example.

Next/Previous Keyboard Toolbar iOS7

Currently, I am trying to set the next/previous buttons on my keyboard toolbar to the new, sleek iOS 7 back button/forward buttons that get put in navigation controllers to go back. Here is what I am trying. How can I use the system bar button item instead of the boring static text?
[self setToolbar:[[UIToolbar alloc] initWithFrame:self.frame]];
[self.toolbar setBarStyle:UIBarStyleDefault];
[self.toolbar setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth)];
[self addSubview:self.toolbar];
[self setSegmentedControl:[[UISegmentedControl alloc] initWithItems:#[ NSLocalizedStringFromTable(#"Previous", #"BSKeyboardControls", #"Previous button title."),
NSLocalizedStringFromTable(#"Next", #"BSKeyboardControls", #"Next button title.") ]]];
Here is what it looks like now:
Here is what I want it to look like:
Any ideas on how to access those system items without actually using images? I know its the exact iOS 7 back bar button item, I just don't know how to access it in a tool bar. I've searched everywhere. If it helps, i'm using BSKeyboardControls.
EDIT: To make it look exactly like the second image, use the images provided by Joshua, and save them as back#2x.png, and forward#2x.png into your xcode proj. Use Chun's code, but make sure to call the method for getting the images like this: imageNamed:#"back", and not #"back#2x". You now have iOS 7 back and forward buttons :)
EDIT2: To get it to look exactly like the next/previous arrow buttons use the following customizations in the correct implementation methods:
[self.segmentedControl setWidth:50 forSegmentAtIndex:0];
[self.segmentedControl setWidth:38 forSegmentAtIndex:1];
negativeSeparator.width = -19;
EDIT3: The toolbar with the < > arrows comes by default with all UIWebViews, and it appears when you tap a textfield.
If anyone is interested in a sample project, let me know, and i'll upload a link!
EDIT4: As of May 24, 2014, BSKeyboardControls now has this functionality by default.
These are the images used in toolbar, e.g. the back and forward button images:
Use the icons shared by Joshua and then try with below piece of code and you will be good to go. I have not added the done button here.
UIImage *backImage = [[UIImage imageNamed:#"backImage"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *forwardImage = [[UIImage imageNamed:#"forward"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:#[backImage, forwardImage]];
[self.segmentedControl addTarget:self action:#selector(segmentedControlChangedState:) forControlEvents:UIControlEventValueChanged];
self.segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
self.segmentedControl.tintColor = [UIColor clearColor];
UIBarButtonItem *aSegmentedControlBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.segmentedControl];
[self setItems:#[aSegmentedControlBarButtonItem, self.flexibleSpace]];
1) Download latest files from: https://github.com/simonbs/BSKeyboardControls
2) Import the images for back/next buttons. These can be whatever you want and you can set the appropriate sizes so that they look good. Joshua has a good set. I have mine saved as "keyboardBack.png" and "keyboardForward.png"
3) In BSKeyboardControls.m, update initWithFields:fields. Here you can do some customization like setting the width of your back/next buttons. I removed the Done button here too to follow your screenshot but you can add it back.
- (id)initWithFields:(NSArray *)fields
{
if (self = [super initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)])
{
// Creates toolbar
[self setToolbar:[[UIToolbar alloc] initWithFrame:self.frame]];
[self.toolbar setBarStyle:UIBarStyleDefault];
[self.toolbar setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth)];
[self addSubview:self.toolbar];
// Import images
UIImage *backImage = [[UIImage imageNamed:#"keyboardBack"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *forwardImage = [[UIImage imageNamed:#"keyboardForward"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
// Create segmentedcontrol
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:#[backImage, forwardImage]];
self.segmentedControl.tintColor = [UIColor clearColor];
// Set button widths
[self.segmentedControl setWidth:50 forSegmentAtIndex:0];
[self.segmentedControl setWidth:50 forSegmentAtIndex:1];
// Other BSKeyboardControls stuff
[self.segmentedControl addTarget:self action:#selector(segmentedControlValueChanged:) forControlEvents:UIControlEventValueChanged];
[self.segmentedControl setMomentary:YES];
[self.segmentedControl setEnabled:NO forSegmentAtIndex:BSKeyboardControlsDirectionPrevious];
[self.segmentedControl setEnabled:NO forSegmentAtIndex:BSKeyboardControlsDirectionNext];
[self setSegmentedControlItem:[[UIBarButtonItem alloc] initWithCustomView:self.segmentedControl]];
[self setVisibleControls:(BSKeyboardControlPreviousNext)];
[self setFields:fields];
}
return self;
}
4) The left padding on the toolbar is a bit too much, so you can fix it by adding a negative separator in toolbarItems: in BSKeyboardControls.m:
- (NSArray *)toolbarItems
{
NSMutableArray *items = [NSMutableArray arrayWithCapacity:3];
if (self.visibleControls & BSKeyboardControlPreviousNext)
{
UIBarButtonItem *negativeSeperator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
negativeSeperator.width = -12;
[items addObject:negativeSeperator];
[items addObject:self.segmentedControlItem];
}
if (self.visibleControls & BSKeyboardControlDone)
{
[items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]];
[items addObject:self.doneButton];
}
return items;
}
Note: I probably don't have the button widths and paddings to the exact specs, but you can tweak it to your liking!
If you don't mind living on the edge you could use Apple's undocumented system items to achieve the iOS 7 look. Here are left and right bar button items.
[self setDoneButton:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:105 target:nil action:nil]];
[self setDoneButton:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:106 target:nil action:nil]];
Source: http://iphonedevwiki.net/index.php/UIBarButtonItem
You can use this great tool by #iftekhar and customise IQSegmentedNextPrevious according to your need for giving images instead of next previous button.
Using Xcode 7.3, you can also just enter a symbol as the title for the Bar Item. This works both in code and in Interface Builder:
Place your cursor where you want the symbol to appear (eg, title box in IB or within quotes in code).
In Xcode's menu, click Edit, then Emoji & Symbols. (Alternatively, press control-command-space to bring up the list of characters.)
In the search box, type less or greater.
Then, select the symbol you want.
The less-than and greater-than symbols are colored blue in the toolbar by default.
In code:
backButton.title = "<"
In IB:
Use this: https://github.com/simonbs/BSKeyboardControls
But it uses the segmented control which got flattened in iOS 7.
Edit:
Just change the text of the segments:
[self setSegmentedControl:[[UISegmentedControl alloc] initWithItems:#[#"<",#">") ]]];
This may not be the most elegant. (Not even sure this exact code compiles, but you see the point)

dim AND lock the background when using UIActionSheet on iPad

I have researched this question for a few hours, sounds pretty simple to me but haven't been able to find a viable solution. I have an iPad application where I'm using a UIActionSheet to confirm a delete. I'm adding a label to increase the font size. Everything looks and works great. I also have a requirement to dim and lock the background while the Action Sheet is visible. I can dim but cannot see how to lock the background so that the user must make a selection on the Action Sheet to dismiss it. I have tried setting UserInteractionEnabled but it doesn't work. Any Ideas?
// dim the background
UIView *dimViewDelete = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
dimViewDelete.backgroundColor = [UIColor blackColor];
dimViewDelete.alpha = 0.3f;
dimViewDelete.tag = 2222;
[self.view addSubview:dimViewDelete];
if ([self.listArray count] > 0)
{
// create Action Sheet
UIActionSheet * action = [[UIActionSheet alloc]
initWithTitle:#" "
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:#"Delete"
otherButtonTitles:nil];
[action addButtonWithTitle:#"Cancel"];
[action setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
[action showInView:self.view];
// change the font size of the title
CGRect oldFrame = [(UILabel*)[[action subviews] objectAtIndex:0] frame];
UILabel *addTitle = [[UILabel alloc] initWithFrame:oldFrame];
addTitle.font = [UIFont boldSystemFontOfSize:22];
addTitle.textAlignment = UITextAlignmentCenter;
addTitle.backgroundColor = [UIColor clearColor];
addTitle.textColor = [UIColor whiteColor];
addTitle.text = #"Are You Sure?";
[addTitle sizeToFit];
addTitle.frame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y,
oldFrame.size.width, addTitle.frame.size.height);
[action addSubview:addTitle];
}
Your best option is to implement your own custom action sheet-like control.
You need a simple view controller that has the two buttons and a label (for the title). Show the view controller in a popover. Make the view controller modal so it can only be dismissed by tapping one of the buttons. This also makes the background appear locked.
If you really need to dim the background as well, just before displaying the popover, add a screen sized UIView to the main window. Set this view's background to [UIColor whiteColor:0 alpha:0.7]. Adjust the alpha as needed to get the right dimming effect. You can even animate the alpha of the view so it fades in and out as needed.

UIBarButtonItem not centered

I've added a single button to the center of a toolbar using:
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:nil];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
self.toolbarItems = #[spacer, addButton, spacer];
But the added button is not quite centered:
What is going on here?
Don't add the same spacer twice in the array - the value may be different in each - make two spacers.
I'm starting to think it's some sort of an iOS-wide bug. That, or they got it wrong in many places. For example, paging dots on home page aren't centered. The Notification Center's top 3 buttons (Today, All, Missed) are also a few pixels off. Plenty more like that. So this may be corrected in the next update.
For now, I'd try to force it to center (say, in viewWillAppear). Pseudo-code below, no time to test :P:
self.toolbarItems[1].center = CGPointMake(self.bounds.size.width / 2.0f, self.bounds.size.height / 2.0f);

How to update UILabel programmatically in iOS

I am facing a problem with updating my labels.. it doesn't remove the old values so new values go on top of old ones.. any help with this will be appreciated..
timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(updateLabels)
userInfo:nil
repeats:YES];
-(void) updateLabels{
for (GraphView *graph in arr){
// retrieve the graph values
valLabel = [[UILabel alloc] initWithFrame:CGRectMake(i * 200, 0, 90, 100)];
valLabel.textColor = [UIColor whiteColor];
valLabel.backgroundColor = [UIColor clearColor];
valLabel.text = [NSString stringWithFormat:#"Value: %f", x];
i++;
}
}
If you set the text of your label you do not need to call setNeedsDisplay or clearContext etc.
In your code, I do not know what are your variables i and x?
The main problem is that you are creating and adding new labels on your view. When you call updateLabels method, may cause a Memory leak. Simply you have n times labels overlapped.
You need to remove the labels before you create and add new labels or you can reuse which you already have. To reuse your labels you need to save them to an array and update texts.
If you want to create new labels then you can do like this unless you have other labels in your view
-(void) updateLabels{
// remove all labels in your view
for (UIView *labelView in self.view.subviews) {
if ([labelView isKindOfClass:[UILabel class]]) {
[labelView removeFromSuperview];
}
for (GraphView *graph in arr){
// retrieve the graph values
valLabel = [[UILabel alloc] initWithFrame:CGRectMake(i * 200, 0, 90, 100)];
valLabel.textColor = [UIColor whiteColor];
valLabel.backgroundColor = [UIColor clearColor];
valLabel.text = [NSString stringWithFormat:#"Value: %f", x];
i++;
}
}
When you create new labels like this you need to add them to your view as subview
[self.view addSubview: valLabel];
if you have other labels in your view then you can save them in an array and remove just them
Your updateLabels method is actually creating new UILabel controls each time so they will simply appear "on top of" older ones. I'm guessing this is not what you want, although it's not perfectly clear so apologies if I've misunderstood what you're trying to do.
If I'm correct about that, create your UILabel controls just once maybe in your viewDidLoad or similar. Then just set their .text properties when your timer fires.
You need to call setNeedsDisplay so that the app knows it has changed and redraw it.
- (void)setNeedsDisplay
Set clearsContextBeforeDrawing property of your label to YES
you can set this from nib as well as code.
label.clearsContextBeforeDrawing = YES;

Resources