How do remove all buttons in the UITextView? - iphone

I have an UITextView in my iPhone app which is editable.
New button is created inside the UITextView whenever user select a specific function.
I want to "clear" all buttons in the UITextView.
The code below is the way I add my button in the text view. How do I remove all the buttons in the text view?
Does anybody have any ideas or has anybody else achieved anything similar?
Thanks
....
....
....
for(int i = 0; i < array.count; i++)
{
object = [array objectAtIndex:i];
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont fontWithName:#"Helvetica" size:12];
[button setTitle:object.name forState:UIControlStateNormal];
button.tag = object.ID;
[button addTarget:self action:#selector(deleteTag:)
[txtTagView addSubview:button];
}
....
....
....

for (UIView *subview in [txtTagView subviews]){
if ([subview isKindOfClass:[UIButton class]]){
[subview removeFromSuperview];
}
}

for(id subview in [self subviews]) {
[subview removeFromSuperview];
}

Remove your buttons from their super view (in your case the super view is the textView for the buttons). [yourButton removeFromSuperview]; So run that in a loop just like how you do while creating them.

I think you can do this for removing all buttons:
for (UIButton* tempButton in txtTagView) {
[tempButton removeFromSuperView];
}
hope this will help you :)

Related

Change frame of cancel button in UISearchBar

I have the following code to change the appearance of the UISearchBar in my application and it can be seen in the image below also:
for(int i = 0; i < [[searchBar subviews] count]; i++){
UIView *subView = [[searchBar subviews] objectAtIndex:i];
if([[NSString stringWithFormat:#"%#", [subView class]] isEqualToString:#"UINavigationButton"]){
UIButton *cancelButton = (UIButton *)subView;
CGRect buttonFrame = cancelButton.frame;
buttonFrame.size.height = 52;
[cancelButton setFrame:buttonFrame];
[cancelButton setTitle:#"Cancel" forState:UIControlStateNormal];
[cancelButton setBackgroundImage:[UIImage imageNamed:#"cancel.png"] forState:UIControlStateNormal];
[cancelButton setBackgroundImage:[UIImage imageNamed:#"cancel_pressed.png"] forState:UIControlStateHighlighted];
}
}
As you can see I am trying to change the height of the button contained in the UISearchBar with no luck. I do get reference to the button as I can change the text and the background Image is changed just not the height of the frame. I would just like the height of the button to be the same as the search box at 52px.
EDIT:
I have found a really hacky solution, but it's not very elegant of adding a UIButton as the subview of the Cancel Button. It does the job but as I say it's not very nice.
Actually you could use method below to access the cancel Button:
UIBarButtonItem *cancelButton = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];
So I override -layoutSubViews with this, but theres 2 issues I have
I hate iterating through the views to find the matching view, and it messes up the animation a little bit
- (UIButton *)cancelButton {
for (UIView *v in self.subviews) {
if ([v isKindOfClass:[UIButton class]]) {
NSString *caption = [[((UIButton *)v) titleLabel] text];
if ([caption isEqualToString:#"Cancel"] )
return (UIButton *)v;
}
}
return nil;
}
- (BOOL)cancelButtonIsShowing {
return ([self cancelButton] != nil);
}
- (void)layoutSubviews {
[super layoutSubviews];
if ([self cancelButtonIsShowing]) {
UIButton *cancelButton = [self cancelButton];
UIImage *i = [UIImage imageNamed:#"Cancel_BTN"];
CGRect f = CGRectMake(267, 5, i.size.width, i.size.height);
cancelButton.frame = f;
}
}

How to save a reference to a control added programmatically?

I added 3 buttons programmatically to my view, then I added the buttons to an array so that I can access them at a later time:
for (i = 0; i < 3; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[view addSubview:button];
[_buttons addObject:button];
}
If I reference the button in my array and change the image of the button, it does not change the button on screen.
UIButton* button = [_buttons objectAtIndex: 0];
[button setImage:thumb forState:UIControlStateNormal];
I've found a way to change the image of the button by looping through all the subviews in my view, but is there a better way?
for (UIView* subView in ((UIView*)[self.view.subviews objectAtIndex:0]).subviews){
if ([subView isKindOfClass:[UIButton class]]){
UIButton *button = (UIButton*)subView;
if (button.tag == self.selected){
[button setImage:thumb forState:UIControlStateNormal];
}
}
}
A common reason for this is that your array has not been initialized. When this happens, Objective C does not complain or throw excetions: instead, it behaves as if the calls to add elements never happened. It also returns nil when you try getting items back.
Add this line to your viewDidLoad method:
_buttons = [NSMutableArray array];
This should solve the problem.
Possible this could help on a click event:
-(void)clickEvent:(id)sender
{
[sender setImage:thumb forState:UIControlStateNormal];
}
If this is how you are picking up the event.
When you do addSubview, view retains subview you are adding. Also addObject retains it. Hence both are different ojbects. Changing properties of object in array will not affect object retained by view.
You can avoid loop by using tags. While adding buttons on view set unique tags to them. And when you want to access them, get it using tag directly.
//set tags for buttons
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setTag:999];
[view addSubview:button];
//access using tag
UIButton *button = (UIButton*)[view viewWithTag:999];
[button setImage:thumb forState:UIControlStateNormal];
Add a tag to the button after creating it. And later use that tag to get that button.
for (i = 0; i < 3; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = i+1;
[view addSubview:button];
[_buttons addObject:button];
}
Then you can access it like:
UIButton *button1 = (UIButton *)[self.view viewWithTag:1];
UIButton *button2 = (UIButton *)[self.view viewWithTag:2];
UIButton *button3 = (UIButton *)[self.view viewWithTag:3];
While adding UIControl programatically to use reference later add tag to it which should be different like:
yourBtn.tag = 111;
Now get reference of UIButton like this:
UIButton *button = (UIButton*)[yourViewWhereYouAdded viewWithTag:111];

how do I only allow one selected button at a time? / make button know if i click somewhere else

how do i make these buttons so that only one can be used at a time? Im not getting any errors right now when i run btw. Im just looking for a solution to my challenge. Thanks for any help
they are generated in a for loop like this:
for (int l=0; l<list.length; l++) {
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTag:l];
CGRect buttonRect = CGRectMake(11+charact*20, -40 + line*50, 18, 21);
aButton.frame = buttonRect;
[aButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[aButton setTitle:#" " forState:UIControlStateNormal];
[gameScroll addSubview:aButton];
}
And then the action for when a button is clicked is:
- (void) buttonClicked:(UIButton *)sender {
int tag = sender.tag;
if (sender.selected == TRUE) {
[sender setSelected:FALSE];
[sender setBackgroundColor:[UIColor clearColor]];
}
else if (sender.selected == FALSE) {
[sender setSelected:TRUE];
[sender setBackgroundColor:[UIColor redColor]];
}
}
right now everything works but i want it to know if theres already a button selected and deselect that other button, or else to automatically deselect any time the user clicks outside of the range of that button
thanks in advance
I would suggest to put all ur buttons to Array in your button initialisation
NSMutableArray* buttons = [NSMutableArray arrayWithCapacity: list.length];
for (int l=0; l<list.length; l++) {
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTag:l];
CGRect buttonRect = CGRectMake(11+charact*20, -40 + line*50, 18, 21);
aButton.frame = buttonRect;
[aButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[aButton setTitle:#" " forState:UIControlStateNormal];
[gameScroll addSubview:aButton];
[buttons addObject: aButton];
}
and every time buttonClicked triggered, then do your logic:
for (UIButton* button in buttons)
{
if (button != sender)
{
[button setSelected: FALSE];
[button setBackgroundColor:[UIColor redColor]];
}
}
int tag = sender.tag;
if (sender.selected == TRUE) {
[sender setSelected:FALSE];
[sender setBackgroundColor:[UIColor clearColor]];
}
else if (sender.selected == FALSE) {
[sender setSelected:TRUE];
[sender setBackgroundColor:[UIColor redColor]];
}
hope helps :)
You can store currently selected button in a separate variable and deselect it in buttonClicked: method:
- (void) buttonClicked:(UIButton *)sender {
int tag = sender.tag;
currentButton.selected = NO;
if (currentButton != sender){
currentButton = sender;
currentButton.selected = YES;
}
else{
currentButton = nil;
}
}
Also you can specify background colour for each state in button itself so you actually don't need to change it each time manually
If you also want to deselect your button when user just touches the screen you can implement touchesEnded:withEvent: in your view controller and reset currentButton in it (that method will get called if no other control intercept the touch event - so it may not be sufficient in all cases)
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event{
currentButton.selected = NO;
currentButton = nil;
}

remove all UIButton's from subview

i'm programmatically adding a couple UIButtons to my view. After clicking one of the buttons they all should be 'removeFromSuperView' or released, not just one.
for (int p=0; p<[array count]; p++) {
button = [[UIButton alloc] initWithFrame:CGRectMake(100,100,44,44)];
button.tag = p;
[button setBackgroundImage:[UIImage imageNamed:#"image.png"] forState:UIControlStateNormal];
[self.view addSubview:button];
[button addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
}
Now this is the part where all buttons should be removed. Not just one.
-(void) action:(id)sender{
UIButton *button = (UIButton *)sender;
int pressed = button.tag;
[button removeFromSuperview];
}
I hope someone can help me with this one!
A more efficient way would be to add each button to an array when you create it, and then when a button is pressed, have all the buttons in the array call the -removeFromSuperView method like this:
[arrayOfButtons makeObjectsPerformSelector:#selector(removeFromSuperView)];
Then after that, you can either keep the buttons in the array and reuse them, or call removeAllObjects to have them released. Then you can start populating it again later.
This saves you from having to walk through the entire view hierarchy looking for buttons.
Another answer just for reference:
for (int i = [self.view.subviews count] -1; i>=0; i--) {
if ([[self.view.subviews objectAtIndex:i] isKindOfClass:[UIButton class]]) {
[[self.view.subviews objectAtIndex:i] removeFromSuperview];
}
}
NSMutableArray *buttonsToRemove = [NSMutableArray array];
for (UIView *subview in self.view.subviews) {
if ([subview isKindOfClass:[UIButton class]]) {
[buttonsToRemove addObject:subview];
}
}
[buttonsToRemove makeObjectsPerformSelector:#selector(removeFromSuperview)];
EDIT:
I have edited my answer to a better solution.
Now the objects are not removed from the array while enumerating it...
Also try this it's very simple :
for (UIButton *btn in self.view.subviews){
[btn removeFromSuperview]; //remove buttons
}

UIButton how to remove from UIView?

I've set up a Button and add it to a view. I want to add a "done" button to the UIKeyboardTypeNumberPad. Here's my code.
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setImage:[UIImage imageNamed:#"DoneUp.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:#"DoneDown.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:#selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
// locate keyboard view
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
UIView* keyboard;
for(int i=0; i<[tempWindow.subviews count]; i++) {
keyboard = [tempWindow.subviews objectAtIndex:i];
// keyboard view found; add the custom button to it
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES)
[keyboard addSubview:doneButton];
}
Everything works great until I want to remove the button if I've got a Kayboard of type NumbersAndPunctuation for example.
If I click the button I use [(UIButton)*sender removeFromSuperview];
to prevent memory leaks.
But how do I remove the button from within an other function?
Thanks a lot!
Some other guys did ask that question somewhere else but didn't get a answer. I'am sure you can help :)
// Where self is a UIView subclass
NSLog(#"subviews: %#",self.subviews);
for(id view in self.subviews ){
if ([view isKindOfClass:[UIButton class]]) {
NSLog(#"Removing a button!");
[view removeFromSuperview];
}
}
You should store a reference to the button, instead of using a local variable. For example:
Header file:
#interface myObject : NSObject {
UIButton *doneButton;
...
Implementation file:
doneButton = [UIButton buttonWithType: UIButtonTypeCustom
...
To remove it (assuming you're in the same object:
[doneButton removeFromSuperview];
However, Apple may not take kindly to you adding buttons to their keyboard.
you can declare your button in your .h file, so you will be able to get access from all class methods