I want to do a loop across every nine outlets (UIButton's, called btn1, btn2, btn3... btn9) that I have, like:
for(int i = 0; i < 9; i++) {
[[btn(%#), i] setImage:someOne forState:UIControlStateNormal]; // I know that this is ridiculous, but it's just a way to demonstrate what I'm saying. :-)
}
Any tip?
Thanks a lot!
You may want to check out IBOutletCollection (apple doc here) which allows you to connect multiple buttons to the same outlet and access them as you would a regular NSArray.
Have all the outlets you want to loop to loop through on a separate view.
for(int subviewIter=0;subviewIter<[view.subviews count];subviewIter++)
{
UIbutton *button = (UIbutton*)[view.subviews objectAtIndex:subviewIter];
// Do something with button.
}
While creating UIButton, you can set tag property of button. Now there can be several ways of accessing that button, like one is -
NSArray *subViews = self.view.subviews;
for (int index = 0; index < [subViews count]; index++) {
if ([subViews objectAtIndex:index] isKindOfClass:[UIButton Class]) {
//Button is accessible now, Check for tag and set image accordingly.
}
}
If you would like to do that you should think what congregates all the UIView instances or in your case: buttons.
I would suggest you to add all the buttons to an array or any other kind of data format that helps you manage your objects.
Should you like to do that without using an external object for that purpose, I would suggest you to add all the buttons to a superview and then, you will be able to iterate over the subviews of the superview using: mySuperview.subviews property.
You could also give a unique ID number to each button (tag) right after when you initialize it, and then you can access tha button usIng the given tag:
myButton.tag = 1;
//Access the button using:
UIButton *b = (UIButton *) [superview viewWithTag:1];
Related
Okay so what I want to do is I have an app with many uiimageviews that you can move and do actions with them. Instead of creating many outlets for each, how can i create one variable that refers to all these outlets (not IBOutletCollection because i would have to use array and arrays dont have properties that uiimageviews do. Ive tried that if youre positive it works please show me the code). For example I have many uiimageviews, variable = all my uiimageviews
So then [variable move]; it moves all the uiimageviews. (NOT BITWISE & or && OPERATOR)
How about creating all of the UIImageView instances and wrapping them in a single transparent UIView. Then when you want to move all the UIImageViews you'd just need to move their wrapper (said UIView).
update
UIView *wrapper = [[UIView alloc] initWithFrame:bigFrame];
for (size_t i = 0; i<10; i++) {
UIImageView *iv = [[UIImageView alloc] initWithImage:someUIImage];
[wrapper addSubview:iv];
[iv release];
}
[self.view addSubview:wrapper];
[wrapper release];
This code creates an uiview that has 10 uiimageviews inside it. When you move that view (wrapper view) the child image views will move with it.
downPreView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
downPreView.tag = indexPath;
downPreView.frame = CGRectMake(75,28, 215,60);
downPreView.progress = 0.0;
[cell.contentView addSubview:downPreView];
Now how do I start animating downPreView with a tag of 2, etc?
Thanks!
You can grab a view with the viewWithTag method. Like [cell.contentView viewWithTag:1]
Update
First of all. You cant animate a progressView, you can show it, hide it, and you can edit it's progress level. If you want to edit it's progress, you have to set it like [downPreView setProgress:0.1]. If it's set to 1 the progrees indicator will be at the end.
However if you want just a spinner, you can use UIActivityIndicatorView.
If you cant get the cell, then you can use it's parent view. Like [self.view viewWithTag:1]
After this you have to cast UIProgressView on it to avoid warnings.
UIProgressView *progressView = (UIProgressView *)[self.view viewWithTag:1];
progressView.progress = 0.1;
For more info about UIActivityIndicatorView please see the documentation.
You cannot access an object by it's tag, you have to retain the object if you want access. Say if you have an array of progress views... you can enumerate it and ask
if (object.tag == tagWanted) {
doSomething;
}
I have a UIToolbar that I set up using IB with three buttons, left, middle and right. In some situations I would like to not display the middle button. Does anybody know of a way to hide a specific button on inside a UIToolBar? There is no hide property, all I can find is setEnable but this still leaves the button causing users to wonder what its purpose is. I would like to only display it in situations that it actually has a use.
Thanks in advance!
Reset the items:
-(void)setItems:(NSArray *)items animated:(BOOL)animated
You can get the current items using the items property, then just remove the one you don't want to show and pass in the new NSArray.
As you can see, you can also animate it to make it clear to the user.
Rather than guessing at the index, I added an IBOutlet for the UIBarButtonItem and then removed it by name:
NSMutableArray *toolBarButtons = [self._toolbar.items mutableCopy];
[toolBarButtons removeObject:self._selectButton]; // right button
[self._toolbar setItems:toolBarButtons];
And of course it helps to connect the outlets in the designer :)
This is how i did it.. too much headache but its the best i could come up with :
NSArray *toolBarArray = toolBar.items;
NSMutableArray *newToolBarArray = [NSMutableArray arrayWithArray:toolBarArray];
[newToolBarArray removeObjectAtIndex:2];
[newToolBarArray removeObjectAtIndex:1];
//remove whatever buttons you want to.
NSArray *finalTabBarArray =[[NSArray alloc] initWithObjects:newToolBarArray, nil];
[toolBar setItems:[finalTabBarArray objectAtIndex:0] animated:NO];
I know it is quite old thread for but those who look this page for solution, here you go :
With iOS7, you can use this approach to show/hide your toolbar button :
if(// your code Condition)
{ self.toolbarBtn1.enabled = YES;
self.toolbarBtn1.tintColor = nil; }
else
{ self.toolbarBtn1.enabled = NO;
self.toolbarBtn1.tintColor = [UIColor clearColor]; }
This does not work here because the array you are sending with setItem is not what the function expects.
I had to replace the line:
NSArray *finalTabBarArray = [[NSArray alloc] initWithObjects:newToolBarArray, nil];
with this one:
NSArray *finalTabBarArray = [newToolBarArray copy];
Then it works perfectly.
Mohit's answer is one that I have used, but you dont need to specifically make it a NSArray that the toolbar sets. You can just set the array of items as a NSMutableArray. No real advantage that I am aware off but its a few lines less code. And that way you can take the array and move about UIButton objects as you would any other array with objects and then just reset the toolbar with that mutable array.
[newToolBarArray removeObjectAtIndex:2];
[newToolBarArray removeObjectAtIndex:1];
[toolBar setItems:newToolBarArray];
I'm making a game that involves have buttons move across the screen until the user taps them. What I have so far is buttons moving across being generated randomly. My problem is when a new button is created, the last one stops moving. I'm trying to stick them into an array, but I'm not sure that's really gonna keep them moving.
-(void) generateStickFig:(NSTimer *)timer {
int x = random() % 100;
NSMutableArray *enemies = (NSMutableArray *)timer.userInfo;
if (x == 1) {
stickFig = [[UIButton alloc] initWithFrame:CGRectMake(0, 650, 50, 50)];
[stickFig setBackgroundColor:[UIColor blackColor]];
[stickFig addTarget:self action:#selector(tapFig:) forControlEvents:UIControlEventTouchUpInside];
// [enemies setObject:object forKey:[NSString stringWithFormat:#"object%i",i]];
[enemies addObject:stickFig];
int b = [enemies count];
[self.view addSubview:stickFig];
arrayNum++;
}
CGPoint oldPosition = stickFig.center;
stickFig.center = CGPointMake(oldPosition.x + 1 , oldPosition.y);
}
Where the buttons are stored is immaterial to moving them. You need to have a routine which animates them. You can do this by hand by moving them a small amount in response to a timer tick. The easiest method there would be fast enumeration over your array.
So you'd have the generation routine you have in your statement, a movement routine, and a touch IBAction handler which removes the button from the array. The generation routine, and the movement routine would both be called in your timer tick handler. (I tend to call that method "handleTick")
In high level psuedo-code it'd be something like this:
//tick handler
handleTick:
one out a hundred times, make a new button
give it a random starting location
store it in the buttons array
every time:
for button in buttons:
move button a few pixels
//button touch handler
buttonWasTouched:button :
[buttons removeObject: button];
I'm just getting into the system provided animation, so I don't know if your button can accept touches while being animated, but I wouldn't be surprised.
In order to know what button was touched from the array, you can use the tag option for the button:
- (IBAction) buttonTouched:(id) sender withEvent:(UIEvent *) event
{
UIButton *btn = (UIButton *)sender;
// in my case, I store the position on the array as a tag for the button
NSUInteger index = btn.tag;
UIControl *control = sender;
// Now you know what button was touched
// Apply actions on to it: remove from superview, animate explosion...
}
Cheers
Im creating and adding a grid of buttons to my custom view keyboardView as follows:
int offset = 0;
for (int row = 0; row<4; row++){
for (int col = 0; col<13;col++) {
offset +=1;
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
aButton.frame = CGRectMake(5+col*65+offset,5+row*65, 60, 60);
[aButton setTitle:myarray[row][col] forState:UIControlStateNormal];
[aButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[keyboardView addSubview: aButton];
}
}
I need certain buttons to be of different sizes, like the return key or space bar. How can i get a reference to a particular button programmatically, later on in the same method? Is there an easier way than setting the tag and then calling [keyboardView viewWithTag:t]? Becauseint's are going to get confusing.
Thanks.
You could make instance variables like UIButton *spaceBar. if you reach the Button in the two for-Iretations which is thought to be the spacebar just do spacebar = aButton.
So you can later in the method just use this instance Variable which refers to the specified button. ;-)
I hope it's more or less understandable. ^^
You can either do it with UIView tags (which don't have to get confusing, just create an enum), or if you have only a few "special" UIButtons, you can create ivars to keep references to them.