Hide dynamically created UILabels in IBAction - ios

I have declared UILabel in ViewController first like this:
#property (weak, nonatomic) IBOutlet UILabel *answerLabel;
Then I have created label in a loop:
//creating answer labels
i = 0;
int y=200;
while (i < numberOfAnswers) {
UILabel *answerLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, y, 300, 20)];
answerLabel.text = [NSString stringWithFormat:#"%# (%#)", questionBank[randomQuestionNumber][1][i][0],questionBank[randomQuestionNumber][1][i][1]];
answerLabel.hidden=NO;
[self.view addSubview:answerLabel];
i++;
y = y + 20;
}
In the IBAction I have this but it doesn't work. Any ideas where the mistakes is?
- (IBAction)nextQuestion:(id)sender {
//hiding labels
self.answerLabel.hidden=YES;
}

I would suggest first create view and then add those labels in this view.
Now when you need to hide, just hide this view.
Hope this answer.
For what you are doing, it is lengthy way. First white creating label you have to set tag. Then for hiding, again get label by tag and then hide accordingly.

Your code contains lots of issues.
First of all, when you are talking about multiple outlets, in the declaration it should be outletCollection like this:
#property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *answerLabels;
Again, as you are creating your labels dynamically, you just can't add them in your IBOuletCollection.
#FahimParkar is suggesting a good approach. But as you might need to work with individual labels, you might use following approach..
First declare an array of labels like this:
#property (strong, nonatomic) NSMutableArray *answerLabels;
Now when you are creating the label, alloc your array & add new labels in it like this:
i = 0;
int y=200;
self.answerLabels= [[NSMutableArray alloc]init]
while (i < numberOfAnswers) {
UILabel *answerLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, y, 300, 20)];
answerLabel.text = [NSString stringWithFormat:#"%# (%#)", questionBank[randomQuestionNumber][1][i][0],questionBank[randomQuestionNumber][1][i][1]];
answerLabel.hidden=NO;
[self.view addSubview:answerLabel];
[self.answerLabels addObject:answerLabel]
i++;
y = y + 20;
}
Now when you want to hide a particular label, you can do this by referring anyone of these three:
Array index.
labelText.
add tag for your label as suggested by Fahim & refer to it.. :)
Let me know if more info needed.. :)

Related

How to set UILabel height dynamically in Objective c?

I am new in iOS and I am facing problem regarding to create UILabel dynamically. I need to change its hight and the Y position according to data from webservice.
My code is like this
NSMutableArray *remarkarray =[[NSMutableArray alloc] init];
remarkarray=[responsedict valueForKey:#"Key"];
NSString *RemarkString=[NSString stringWithFormat:#"%#",[remarkarray objectAtIndex:0]];
remarklbl.text=RemarkString;
remarklbl.numberOfLines=0;
[remarklbl sizeToFit];
I have create UILabel like this
But its Y Position is fix. I need to create a UILabel in which I can change the height and the Y position according to text in it. Like this
Thanks in Advance!
You can do it very easily by declaring two labels in Storyboard.
Here are steps.
Drag two UILabels in your viewController and select the first one and set constraints like below image.
Select the second label and add following constraints.
Select both labels and set numberOfLines to zero.
Now u can set text dynamically from code.
All you have to do is:
float x=10.0,y=10.0,height=40;
float verticalSpace=20.0;
for (int i = 0; i < 10; i++)
{
UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake(x, y,50,height)];
label.text = #"dummy text";// It could be from array as well if you want to add different text for each label. Eg: label.text = [arr objectAtIndex:i];
[self.view addSubview:label];
y = y +height+ verticalSpace;
}
You could search around with key word "auto layout dynamic label height"

ASCollectionNode full-width layout for CellNode

I want to make cells full-width in ASCollectionNode, but I'll get CellNodes sized by content.
I have implemented layoutSpecThatFits:.
See the image
My way to achieve that is adding extra node with full width inside ASStaticLayoutSpec.
In header:
#property (strong, nonatomic) ASDisplayNode *stretchNode;
In init
_stretchNode = [ASDisplayNode new];
[self addSubnode:_stretchNode];
layoutSpecThatFits:
- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize {
_stretchNode.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(CGSizeMake(constrainedSize.max.width, 0.5f));
NSArray *children = #[];
ASStackLayoutSpec *mainStackLayoutSpec = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionVertical spacing:0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsStart children:children];
ASStaticLayoutSpec *mainStaticLayoutSpec = [ASStaticLayoutSpec staticLayoutSpecWithChildren:#[mainInsetsLayoutSpec, _stretchNode]];
return mainStaticLayoutSpec;
}
Important part here is to wrap your layout and stretchNode in ASStaticLayoutSpec. You can replace StackLayout with anything you want.

iOS: setting alphas of multiple buttons at once

Okay, so I don't really know if NSDictionary is the correct approach to this, but I am using a fade animation to take different groups of buttons on and off a screen. I want to "compartmentalize" them, so to speak, into different groups so I can do this in one or two lines without having to rewrite all the buttons names every time (there are a good amount). Any ideas on how to do this?
[UIView animateWithDuration: 1.5
animations: ^(void)
{
//As an example i just called them button1, button2, etc.
self.button1.alpha = 1;
self.button2.alpha = 1;
self.button3.alpha = 1;
self.button4.alpha = 1;
self.button5.alpha = 1;
}
];
I included the above as an example of what I am asking. Is there a way to put all the buttons in an NSDictionary and write one line (where the buttons are currently located) that changes all of their alphas?
The preferred mechanism nowadays for buttons you've added in Interface Builder would be an IBOutletCollection:
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *buttons;
Clearly, in Interface Builder you would connect the individual buttons to the outlet collection. For a discussion of IBOutletCollection, see NSHipster's IBAction / IBOutlet / IBOutlet​Collection article.
If you're not using Interface Builder, but rather have created these buttons programmatically, you could just have an NSArray:
#property (strong, nonatomic) NSArray *buttons;
Which you'd then populate yourself:
self.buttons = #[self.button1, self.button2, self.button3, self.button4, self.button5, self.button6];
Regardless of how you build this array (either outlet collection or manually populated), you can then iterate through that array as you update a property of the buttons:
for (UIButton *button in self.buttons) {
button.alpha = 1;
}
Or, even simpler, you can update all of them with setValue:forKey::
[self.buttons setValue:#1 forKey:#"alpha"];
You can use button tags to accomplish this. Set the same tag for multiple buttons (your groups) and do:
button.tag = 1;
then:
for (UIButton *btn in button) {
if(btn.tag == 1)
{
// do something
break; // don't need to run the rest of the loop
}
}

Why i can't move image and set text in label at the same time

I want to move background to the left like my character is walking and show number of walking but it can't do that at the same time. this method leftfootButton can only set text in label
- (IBAction)leftfootButton:(id)sender {
_bgGround.center = CGPointMake(_bgGround.center.x -50, _bgGround.center.y);
i = i+1;
self.show.text = [NSString stringWithFormat:#"%d",i];
}
If i comment the code that sets the text out then it can move background
- (IBAction)rightfootButton:(id)sender {
_bgGround.center = CGPointMake(_bgGround.center.x - 50, _bgGround.center.y);
i = i+1;
//self.show.text = [NSString stringWithFormat:#"%d",i];
}
what should i do?
You should not change frames directly when you use auto layout because layoutSubviews method will return frames to their previous position. This method is called by system in many cases. You could override it to set the frame rectangles of your subviews directly. But I recommend you to change constraints of your background view. Even if you did not set constraints to your views, they was added automatically.
When you use Layout Constraint then you should never change the frame, you should try to change the constraint, e.g.
Create a IBOutlet for x contraint for the view like below, make sure it's correctly connected.
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *xContraint;
Then in your action
- (IBAction)leftfootButton:(id)sender {
self.xContraint.constant -= 50;
i = i + 1;
self.show.text = [NSString stringWithFormat:#"%d", i];
}

Make changes to a number of buttons programatically

I have a view with 10 buttons and I want to use information from an array to set how many of the buttons are visible and what their title is.
The buttons are named option1BTN...option10BTN. The array has different data and size depending on what the user selects and I want to buttons to also reflect the changes.
The code below shows a for-do loop, that sets which button is visible and the button title
for (int i=0; i == [optionsArray count]; i++) {
self.option1BTN.hidden = NO;
[self.option1BTN setTitle:[optionsArray objectAtIndex:i] forState:UIControlStateNormal];
}
How can I change the button name (programatically) in the loop so that depending on the size of the array it changes to option1BTN then option2BTN...optionXBTN and so on?
NSArray *buttons = #[self.option1BTN, self.option2BTN]; // add all the buttons here
for (int i=0; i < buttons.count; i++) {
UIButton *button = buttons[i];
button.hidden = NO;
[button setTitle:[optionsArray objectAtIndex:i] forState:UIControlStateNormal];
// the previous line can be re-written as
//[button setTitle:optionsArray[i] forState:UIControlStateNormal];
}
The difference between this approach and using an IBOutletCollection (as Jeff suggests in his answer) is that the outlet collection does not guarantee the order of its items. If the order is important to you, you need to specify it yourself, like in my code snippet above.
You have two main options, one is to use an IBOutletCollection (if your buttons are created in Interface Builder). Each UIButton will be stored in the collection and you can retrieve the right button in the loop from the collection.
Example:
#property (nonatomic, strong) IBOutletCollection(UIButton) NSArray *buttons;
In IB, you will need to link each button to the IBOutletCollection. Then in your code you will be able to do:
for (int i = 0; i < optionsArray.count; i++) {
UIButton *tempButton = self.buttons[i];
tempButton.hidden = NO;
[tempButton setTitle:[optionsArray objectAtIndex:i] forState:UIControlStateNormal];
tempButton.hidden = NO;
}
The ordering of an IBOutletCollection is not always guaranteed so you may need to use a combination of IBOutletCollection and view tagging (see end of post). For more information on IBOutletCollection's see NSHipster's article
Second option is if your buttons are created programmatically, store each button in an NSMutableArray as you create it:
#property (nonatomic, strong) NSMutableArray *buttons;
UIButton *myButton;
// Do something...
[self.buttons addObject:option1BTN];
Then use the same loop as before.
A third (not recommended option), would be to tag each UIButton and then you can use the viewWithTag: method to retrieve the button. E.g. using the above code again but getting the button with:
UIButton *tempButton = [self.view viewWithTag:i];

Resources