Access every button in a UIView on the iPhone - iphone

What I want to do is ideally loop through all buttons in a UIView (I have a lot, over 40 buttons), and depending on the tag, change the image that the button is displaying. Does anyone know how I can do this?
Thanks!!!!

I would say use the subviews property, as devilaether said, but do an additional check to make sure the subview is a UIButton before you do anything else with it:
for(UIView *view in [rootView subviews]) {
if([view isKindOfClass:[UIButton class]]) {
if([view tag] == 0) {
// First image
} /* ... */
else {
NSLog(#"didn't recognize tag");
}
} else {
NSLog(#"view is not a button");
}
}
You could also make your life easier if you stored an NSArray somewhere with the UIButtons you wanted to iterate over; this would take out the isKindOfClass: check. See the NSObject protocol for more info.

Use the subview property of the UIView containing the buttons. For each UIView element in that NSArray, inspect the tag property. If the tag matches what your logic needs, change the image displayed in that UIView instance - which in this case is one of the buttons.

for(i=0; i<numberOfTags; i++){
UIButton *tempBtn = [yourView viewWithTag:i];
[tempBtn setImage:yourImage];
}

Related

How To disable the userinteraction of a view except one object?

In My view there is reset button .i need userinteraction disabled except for that button .how can i do that can any one share the code.thanks in advance?
btn1 is your button, self.view - your view
for (UIView *view in self.view.subviews)
view.userInteractionEnabled=NO;
btn1.userInteractionEnabled=YES;
For all the elements there is a property userinteractionenabled. Set it to false
yourelement.userInteractionEnabled = NO;
Also place your UIButton on top of your view hierachy.
Other option is to place a tranparent UIButton on your entire view and your UIButton on top of this view. This way only your UIButton is touch enalbed. Other touches would be taken in by the transparent button which does nothing.
Sligthly better approach, define a "magic value" that will help you :
#define kDontDisableUserInteraction 3928473
then set this value as the tag of your button you don't want disabled:
[resetButton setTag:kDontDisableUserInteraction];
you can now create a function in your superview's class :
- (void)setInterfaceEnabled:(BOOL)newEnabled {
for (UIView *subview in self.subviews) {
if (subView.tag != kDontDisableUserInteraction)
continue;
subView.userInteractionEnabled = newEnabled;
}
}
That allows you to create other non-disableable buttons simply by giving them the right tag (which can be whatever int value you want, not only 3928473, depends on your #define).

Possible to check number of objects in touch location?

Is it possible to check number of objects in a certain touch location?
I have tagged all objects with a number, but couldn't think of a way it would work.
Basically what I want to do is add uiimageview to touch point, BUT when there is already an other uiimageview, I would do nothing.
Thanks!
You've got a good idea to start. All the objects that you add on a view are already kept in an array called [myview subviews]. It was a good idea to tag them because then you can easily access them with [myview viewWithTag: kFirstViewTag].
So to answer the second part, when your checking touch locations, check if the touch location intersects with any of your subviews.
For example:
for (UIView* view in [myView subviews]) {
if (CGRectContainsPoint([view frame], touchPoint) {
//do something
}
}
I can assume you probably don't need to go trough all the subviews, so you can just cycle to ones limited with tags from kFirstViewTag to kLastViewTag with for loop, like:
for (int i = kFirstViewTag; i <= kLastViewTag; i++) {
UIView *view = [myView viewWithTag: i];
if (CGRectContainsPoint([view frame], touchPoint) {
//do something
}
}

Positioning A Button

How can I position a button on my view dynamically?
Try this code
for(UIView * view in self.view.subviews)
{
if([view isKindOfClass:[UIButton class]])
{
// view is button
}
}
You can also use tags
Set the tag property of the UIButton (e.g. in interface builder, or programatically). Then you can walk the children of the owning view:
for (UIView *view in myView.subviews) {
if (view.tag == 101 /*or whatever you set it to*/) {
// things...
}
}
Ok, now we understand the question better...
You can place a button/UIComponent at runtime by settings its frame. This will place it at a given coordinate within the view containing the button.
myButton.frame = CGRectMake(newX, newY, myButton.frame.width, myButton.frame.height);
If you wish to do a linear style animation (no curves), look up CATransitions, see iPhone UIView Animation Best Practice. If you need to support pre-iOS4 devices, you can't use CATransitions, and have to do it the old way using UIView animations.
To do more complex animations, you might have to mess around with timers, which can slightly juddery effects if you're trying to do complicated animation paths.
Get a array of all the subviews of a view using:
[myView subviews]
iterate through that array and check for your butotn by some unique characteristic. (You can set the button's tag attribute to some unique value and check for that value)

iPhone: How to remove all objects from a UIScrollView

Basically I want to remove all objects from a UIScrollView and I haven't yet found a solution to it because a simple "removeAllObjects" command doesn't work. Does anyone have an idea how to do it?
Even easier:
[[scrollView subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
The easiest way:
for(UIView *subview in [scrollView subviews]) {
[subview removeFromSuperview];
}
Two solutions would be, without removing the scrollbars:
Add a tag to all of your subviews, remove them by using those tags.
Implementation:
Place this above your class
#define XPScrollViewSubviewStartTag 100
When you add the objects
for(NSInteger = 0;i<[viewArray count];i++){
UIView* view = [viewArray objectAtIndex:i];
view.tag = XPScrollViewSubviewStartTag + i;
[scrollView addSubview:view];
}
When you later want to delete the views use
for(UIView* view in [scrollView subviews]){
if(view.tag >= XPScrollViewSubviewStartTag)
[view removeFromSuperview];
}
Create a custom UIView class
When you want to remove the views
for(id view in [scrollView subviews]){
if(![view isKindOfClass:[CustomView class]])
continue;
//not necessary, but just to make things understandable
CustomView* customView = (CustomView*)view;
[customView removeFromSuperview];
}
Oritm's solution is nice, but if you don't want to bother using tags, you can manually remove which views you want to remove from the scrollview. This will assume that you know which view to remove. For example, my scrollview only has UILabels so when I run the following:
// This will remove the scrollview but the scrollbars will remain
for (UIView *subview in [self.detailsExpander.scrollView subviews]) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UILabel"])
[subview removeFromSuperview];
}
This will only remove all the labels but keep the scrollbars (which are image views). Note: this won't work if you want to keep specific image views while at the same time you want to keep the scrollbars.

Custom Delete button On Editing in UITableView Cell

I have gone through this question that shows the following code:
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{
return #"Sagar";
}
What if I want a custom image instead of the default red button?
Implement this method in custom cell
- (void)willTransitionToState:(UITableViewCellStateMask)state{
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask) {
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
UIImageView *deleteBtn = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 64, 33)];
[deleteBtn setImage:[UIImage imageNamed:#"delete.png"]];
[[subview.subviews objectAtIndex:0] addSubview:deleteBtn];
[deleteBtn release];
}
}
}
}
This is a late reply but I hope someone may find this helpful. So the accepted answer seems sort of complicated for me, and #user1684899's answer only works if you just want to change the look of the delete button. I want to completely change the appearance of the delete button (i.e. its frame, position, etc.), so my solution is to add my own delete button to my custom cell and keep it initially hidden, and only show it when the cell is in edit mode. What's more important, I want to hide iOS's original delete button and support backward compatibility, and here's my trick:
- (void)willTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask)
{
if (!IS_IOS_7){
for (UIView *subview in self.subviews)
{
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"])
{
// hide original button
[[subview.subviews objectAtIndex:0] setHidden:YES];
// show my custom button
[self.deleteButton setHidden:NO];
}
}
} else {
for (UIView *subview in self.subviews) {
for (UIView *subview2 in subview.subviews) {
if ([NSStringFromClass([subview2 class]) rangeOfString:#"Delete"].location != NSNotFound) {
// hide original button
[subview2 setHidden:YES];
// show my custom button
[self.deleteButton setHidden:NO];
}
}
}
}
} else {
// hide my custom button otherwise
[self.deleteButton setHidden:YES];
}
}
And don't forget to add:
[cell.deleteButton addTarget:self action:#selector(deleteEntryAtIndexPath:) forControlEvents:UIControlEventTouchUpInside];
in cellForRowAtIndexPath, so that you can add any thing you want when your delete button is clicked. Here is my result:
The systemwide standard for the intended list-dive-in action, as you said in the comment on luvieere's answer, would be to use the detail-disclosure (blue circled arrow) cell accessory, not the swipe gesture.
That said, if you still want to use the swipe action for this, there's no way to provide your own button without manually intercepting and completely reimplementing the swipe gesture, like what Tweetie does.
luvieere is right -- if you want that same "delete" metaphor, you want to keep it at the red button that Apple provides. Why change it? Its globally recognizable as the standard for delete buttons.
Although, if you want something like Tweetie, where you completely change the behavior of swiping, you could use something like ABTableViewCell where you just draw in your own view. Make a custom table view, override -touchesBegan:withEvent:, and check for touches. Calculate the delta of the two touches (in touchesMoved:withEvent:) and move your own view around.