Loop, generating buttons with functions from an array - ios

For my iOS app I have an array of text, and I want to generate inside of my UIScrollview a list of text on the right hand side and a list of buttons on the left hand side.
Whenever a user presses a UIButton from the right hand side the text from the left hand side will be copied to the user's device's clipboard...
I figured out how to generate the list of text in UILabels using a for loop and an NSArray. I have no clue how to programmatically generate UIButtons though and I also don't know how to make each button copy the respective string from the array (i.e. button #3 copies string #3 (objectAtIndex #2) from the array)
Here is my code so far:
NSArray *copyText;
copyText = [NSArray arrayWithObjects: #"text to copy 1", "text to copy 2", "text to copy 3", "text to copy 4", nil];
int i = 0;
while (i < [copyText count]) {
UILabel *copyLabels = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, (ScrollView1.frame.size.width*2/3), 25)];
copyLabels.center = CGPointMake(ScrollView1.frame.size.width*2/3, ((i*25)+15));
copyLabels.textAlignment = UITextAlignmentCenter;
copyLabels.textColor = [UIColor blackColor];
copyLabels.backgroundColor = [UIColor clearColor];
copyLabels.font = [UIFont fontWithName:#"System" size:(16.0)];
[ScrollView1 addSubview:copyLabels];
copyLabels.text = [NSString stringWithString:[copyLabels objectAtIndex:i]];
i ++;
}

Found my answer here: Add a multiple buttons to a view programmatically, call the same method, determine which button it was
The UIButton has a "tag" field in which numeric values can be assigned so my loop can keep track of which button is which. Genius.

Related

Create Two UILabels dynamically using Objective C

In one array I have one string and one more array I want to display this dynamically in custom cell. My array structure is given below. It will change according to data coming from web service.
{
subDescription = (
"Worship Hours 5.00am to 12.30pm & 4.00pm to 10.00pm",
"The temple is open all days of the week"
);
subHeading = Hours;
}
And i tried like this using this format i can display subHeading Value only how to display subDescription array
float xCoordinate=10.0,yCoordinate=30.0,width=320,height=40;
float ver_space=20.0;
for (int i = 0; i <test.count; i++)
{
NSDictionary *lanuage=[test objectAtIndex:i];
NSString *work=[lanuage objectForKey:#"subHeading"];
NSArray *er=[lanuage objectForKey:#"subDescription"];
UILabel *label = [[UILabel alloc] initWithFrame:
CGRectMake(xCoordinate,yCoordinate,width,height)];
label.text = work;
[events.contentView addSubview:label];
yTCoordinate=yTCoordinate+heightT+ver_space;
}
I am not sure that I understand, but why dont you use CollectionView instead of a label. There you can define header cell and sub cells. I think this fits your problem.
In case that you do not want to use collection view you can adjust your code and iterate with loop through your sub items array.
for (NSString *item in er) {
UILabel *label = [[UILabel alloc] initWithFrame:
CGRectMake(xCoordinate,yCoordinate,width,height)];
label.text = item;
[events.contentView addSubview:label];
yCoordinate=yCoordinate+height+ver_space;
}

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"

Displaying Array in Text Label

I'm still sort of new to Xcode, so please be patient with me. Anyway, I'm having a bit of trouble trying to display the whole contents of an array in a UILabel. I'm able to display it by simply using the code
wordList.text = [NSString stringWithFormat:#"List of Words:\n %#", listA];
However upon running, the label ends up displaying a parenthesis and the words on their own lines, as well as quotation marks around the words, and the ending quotation mark and a comma in the line between each word. Example:
List of Words:
(
"apple
",
"banana
",
"etc.
While I do want the words to be displayed in their own lines, I do not want the parenthesis and the closing quotation mark and comma being displayed in a separate line. I would also prefer removing the parenthesis, quotation marks, and commas all together, but I wouldn't mind too much if I'm unable to.
Could anyone please explain why its being displayed as such, and to help me correctly display each word of an array in its own line in a UILabel?
Use this:
NSArray *listOfWords = #[#"One", #"Two", #"Three"];
NSString * stringToDisplay = [listOfWords componentsJoinedByString:#"\n"];
wordList.text = stringToDisplay;
Will Display:
One
Two
Three
The parentheses, quotation marks, and commas are being added because providing an array as an argument to the format specifier %# causes the -(NSString *)description method to be sent to the array. NSArray overrides NSObject's implementation of description and returns a string that represents the contents of the array, formatted as a property list. (As opposed to just returning a string with the array's memory address.) Hence, the extra characters.
You Can use this Code
NSArray *listOfWords = [NSArray arrayWithObjects:
#"one.",
#"two.",
nil];
for (NSString *stringToDisplay in matters)
{
//frame, setting
labelFrame.origin.x = 20.0f;
UILabel *stringToDisplayLabel = [[UILabel alloc] initWithFrame:labelFrame];
stringToDisplayLabel.backgroundColor = [UIColor clearColor];
stringToDisplayLabel.font = [UIFont boldSystemFontOfSize:12.0f];
stringToDisplayLabel.lineBreakMode = NSLineBreakByWordWrapping;
stringToDisplayLabel.numberOfLines = 0;
stringToDisplayLabel.textColor = [UIColor whiteColor];
stringToDisplayLabel.textAlignment = NSTextAlignmentLeft;
//set up text
stringToDisplayLabel.text = stringToDisplay;
//edit frame
[stringToDisplayLabel sizeToFit];
labelFrame.origin.y += stringToDisplayLabel.frame.size.height + 10.0f;
[self.view addSubview:stringToDisplayLabel];
[matterLabel release];
}

Make only part of a sentence a link (add selector)

so I am trying to implement the following. I have a view, which has a sentence. Only part of the sentence links to another view. This is what it looks like:
I am a cat. Learn More
The Learn More would be a link (blue in color), which when clicked would open another view.
Currently I am using a UILabel to write "I am a cat". I realize that the best way to add selectors is to use a button, so "Learn More" should be a button?
Is there any way to write this sentence out without using two different UIComponents?
If not, then how do I make the UILabel and the UIButton completely horizontally aligned with each other?
The following is my code for the label in -layoutSubviews:
CGSize labelSize = [_label.text sizeWithFont:_label.font constrainedToSize:bounds.size lineBreakMode:_label.lineBreakMode];
_label.frame = CGRectMake(0, 0, bounds.size.width - kMarginForText, labelSize.height);
_label.center = CGPointMake(horizontalCenter, CGRectGetMaxY(_previousLabel.frame) + kDistanceBetweenPreviousAndCurrentLabel);
And the code for the label itself.
_label = [[UILabel alloc] initWithFrame:CGRectZero];
_label.text = "I am a cat";
_label.font = [UIFont systemFontOfSize:14];
_label.textAlignment = NSTextAlignmentCenter;
_label.numberOfLines = 0;
_label.lineBreakMode = UILineBreakModeWordWrap;
[self addSubview:_label];
Any help would be appreciated!
To answer your question about a single UIComponent, you could use a UILabel in conjunction with a UITapGestureRecognizer to create the intended effect. Granted this would make the whole label tappable... but having a bigger tap target area is almost never a bad thing.
In particular you would use an NSAttributedString to set the label text (NSAttributedString change color at end of string):
UILabel *label = [[UILabel alloc] init];
//Use initwithframe or setup your constraints after initialization here
label.attributedText = (your nsattributed string here)
Then to initialize the tap recognizer onto the UILabel you would do something like this:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(userDidTapLearnMore)];
label.userInteractionEnabled = YES;
[label addGestureRecognizer:tap];
What you want to do is to align them by their baselines, which you can easily do in Interface Builder by selecting them and choosing Editor > Align > Baselines, as shown in this illustration:

Identify UIImageView and UITextView created in loop iOS

I'm working in Xcode and i have a loop cycle in which i dynamically create UIImageViews and UITextviews and insert them in a UIScrollView. In every row, i create 4 UIImageViews and 2 UITextViews, so the code looks like this:
for (int i=0; i<dim; i++){
UITextView *textView1= [[UITextView alloc] initWithFrame:CGRectMake(0, 0, screenWidth/2, 37)];
UITextView *textView2= [[UITextView alloc] initWithFrame:CGRectMake(screenWidth/2, 0, screenWidth/2, 37)];
UIImageView *imageView1 = [[UIImageView alloc] initWithFrame:CGRectMake(0,50,screenWidth/4,100)];
UIImageView *imageView2 = [[UIImageView alloc] initWithFrame:CGRectMake(screenWidth/4,50,screenWidth/4,100)];
UIImageView *imageView3 = [[UIImageView alloc] initWithFrame:CGRectMake(screenWidth/2,50,screenWidth/4,100)];
UIImageView *imageView4 = [[UIImageView alloc] initWithFrame:CGRectMake(screenWidth*3/4,50,screenWidth/4,100)];
}
The code to set images in UIImageViews, text in UITextViews and show them in the UIScrollView works great and i don't post it because it's too long.
My problem is: when i click on an image, i call methods in which i want to make change to the ImageViews and TextViews of the same row, how can i identify them?
Detecting the image clicked is not a problem using the recognizer.view, to detect other images of the same row i tried to set a tag to the views and then call "viewWithTag" to find them, but i have problems because the elements of the same row have the same tag value and i make confusion.
My target is for example:
When i click on imageView1 in the first row should change image in imageView3 of the same row.
When i click on imageView3 in the fourth row should change text in textView2 of the same row.
And so on..
Is there any alternative method without using the tag attribute?
I hope I explained myself
You can use the tag property, but without using the same tag more then once. Some little math should do the trick to identify views in the same row by their tags...
BUT:
I wouldn't recommend using tags. Make yourself a custom view class, e.g. MyRow, containing the 6 views belonging together as subviews. From there you can go anywhere.
Got a problem, invent an object. Always works.
BIGGER BUT: I'd strongly recommend to go with UICollectionView or UITableView.
UIView has a "tag" property, which you can use for anything you want. The default value is 0 and it doesn't do anything at all, except store the value.
Typically you would set the tag to be an array index.
So you could do:
textView1.tag = i;
textView2.tag = i;
imageView1.tag = i;
imageView2.tag = i;
imageView3.tag = i;
imageView4.tag = i;
Or perhaps something more clever, like:
textView1.tag = 1000000 + i;
textView2.tag = 2000000 + i;
imageView1.tag = 3000000 + i;
imageView2.tag = 4000000 + i;
imageView3.tag = 5000000 + i;
imageView4.tag = 6000000 + i;
Or maybe you could have an array property mapping them:
#property NSMutableArray tagMap;
textView1.tag = self.tagMap.count;
[self.tagMap addObject:#{#"var": #"textView1", #"index":[NSNumber numberWithInteger:i]}];

Resources