Change a label on cells of UITableView? - objective-c

I've added 3 labels and a button on cell of UITableView like this image
when i click on checkbox i change the label 'Due in 0 days' in some other stuff. it is ok with this code
[statusText setTextColor:[UIColor colorWithRed:0.0/255.0 green:51.0/255.0 blue:102.0/255.0 alpha:1.0]];
[statusText setFont:[UIFont boldSystemFontOfSize:16.0]];
statusText.tag = 100;
[statusText setBackgroundColor:[UIColor clearColor]];
[checkBoxBtn setBackgroundImage:[UIImage imageNamed:#"check_normal.png"] forState:UIControlStateNormal];
[checkBoxBtn addTarget:self action:#selector(showAlert:) forControlEvents:UIControlEventTouchUpInside];
checkBoxBtn.tag = indexPath.row;
[cell.contentView addSubview:checkBoxBtn];
this is my checkBoxAction and showAlert methods
-(void) checkBoxAction: (UIButton *)sender
{
NSInteger i =sender.tag + 1;
float perc = (i*100/18.0);
//NSLog(#"%.2f",perc);
NSString* percentageStr = [[NSString alloc] initWithFormat:#"%3.2f%%(%d out of 18)",perc, i];
barTitle.text = percentageStr;
barFGImage.hidden = NO;
if (perc == 100.00) {
[barFGImage setFrame:CGRectMake(barFGImage.frame.origin.x, barFGImage.frame.origin.y, 276.0, barFGImage.frame.size.height)];
}
else
[barFGImage setFrame:CGRectMake(barFGImage.frame.origin.x, barFGImage.frame.origin.y, 280*perc/100, barFGImage.frame.size.height)];
[sender setBackgroundImage:[UIImage imageNamed:#"check_select.png"] forState:UIControlStateNormal];
sender.userInteractionEnabled = NO;
NSString *currentDate = [formatter stringFromDate:[NSDate date]];
NSString* statusStr = [[NSString alloc] initWithFormat:#"Completed on %#",currentDate];
UILabel *tempLabel = (UILabel *)[[button superview] viewWithTag:100];
tempLabel.textColor = [UIColor colorWithRed:243.0/255.0 green:134.0/255.0 blue:48.0/255.0 alpha:1.0];
tempLabel.text = statusStr;
}
- (void) showAlert:(id)sender
{
button = (UIButton *)sender;
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"" message:#"Do you really want to complete this training?" delegate:self cancelButtonTitle:#"Yes, I've completed it" otherButtonTitles: #"No", nil];
[alert show];
}
Now i want that if i press checkBox on row (say)3rd then 'Due in 0 days' label of row 3rd, 4th and so on should changed.Any suggestion or sample code will be appreciated.
Thanks.

I am afraid my suggestion is not going to be a simple suggestion or code sample, but rather I would invite you to spend some time reading about MVC (Model View Controller).
From what I can tell from your code, your data seems to be 'stored' in your view objects. This is a very bad idea in general, this is a terrible idea with table views, as cells are being reused, and your data would just disappear as you scroll through large tables.
What you need to do is define model classes to hold your data, the controller objects will then access those model objects and display their data in the various views they control.
Once you implement this kind of pattern, checking something in one cell will update your model objects. Then all you will need to do is to make a simple [tableView reloadData]; call to update ALL your cells at once.

Related

Scrollable calender month view: title text of custom button in collection view gets overwritten

I want to create a custom, scrollable month view, in which the user is able to scroll through all months of the corresponding year (just like the iPad calendar).
So I created one array for all the date components I need. There are 12 subarrays in this array, one for each month. I already managed to fill my subarrays with the correct date components of the corresponding year.
I set the number of sections in my collectionView to be 12 (one for each month) and the items in my section to have the same number as the number of days in the current month.
In order to label my button titles within the collection view cell with the date components, I wrote this method to get the String for the title label:
- (NSString *)getDayOfMonthFromComponent: (NSDateComponents *)components{
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *newDate = [gregorian dateByAddingComponents:components toDate:self.currentDate options:0];
NSDateFormatter *dateFormatterDayOfMonth = [[NSDateFormatter alloc]init];
[dateFormatterDayOfMonth setDateFormat:#"d"]; // filter day of month
NSString *dayOfMonth = [dateFormatterDayOfMonth stringFromDate:newDate];
return dayOfMonth;
}
That's how I label my custom button:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
EMMonthCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MonthCell" forIndexPath:indexPath];
EMBorderlessButton *button;
#pragma mark - dateLabel sort algorithm iPhone
if (IS_IPHONE){
#pragma mark - dateLabel sort algorithm iPad
} else if (IS_IPAD){
button = [[EMBorderlessButton alloc]initWithFrame:CGRectMake(110, 10, 30, 30)];
NSString *titleText;
NSLog(#"index path: %ld of section: %ld", (long)indexPath.row, (long)indexPath.section);
if (indexPath.row < [[self.daysThisMonthArray objectAtIndex:indexPath.section] intValue]){
titleText = [self getDayOfMonthFromComponent:self.dateComponents [indexPath.section] [indexPath.row]];
}
[button setTitle:titleText forState:UIControlStateNormal];
[button setUserInteractionEnabled:NO];
[button setSelected:FALSE];
[button setTag:indexPath.row];
[cell addSubview:button];
[self.buttonArray addObject:button];
[cell bringSubviewToFront:button];
}
return cell;
}
The labeling basicly works, but as soon as I start scrolling, the titleLabels get overwritten.
How can I solve this issue? Thanks in advance for your help.
Solved it. The solution was pretty simple: with interface builder I just dragged a button in my collection view cell and assigned it to my custom button class. I addition, I connected the created button as outlet to my custom collection view cell class.
Afterwards I changed the code like this:
#pragma mark - dateLabel sort algorithm iPad
} else if (IS_IPAD){
NSLog(#"check content: %#", self.daysThisMonthArray);
EMBorderlessButton *theLabel = (EMBorderlessButton *)[cell viewWithTag:100];
[theLabel setTitleColor:[UIColor em_darkViolett] forState:UIControlStateNormal];
if (indexPath.row < [[self.daysThisMonthArray objectAtIndex:indexPath.section] intValue]){
[cell.dateButton setTitle:[self getDayOfMonthFromComponent:self.dateComponents [indexPath.section] [indexPath.row]] forState:UIControlStateNormal];
if ([[self getDayOfMonthFromComponent:self.dateComponents [indexPath.section] [indexPath.row]] isEqualToString:#"1"]){
[cell.dateButton setTitle:[NSString stringWithFormat:#"%#. %#", [self getDayOfMonthFromComponent:self.dateComponents [indexPath.section] [indexPath.row]], [self getMonthNameFromComponents:self.dateComponents [indexPath.section] [indexPath.row]]] forState:UIControlStateNormal];
}
}
[self.buttonArray addObject:theLabel];
}
return cell;
}

Still Dismissing Alert

I am trying to keep this UIAlertView up after the presses either of the buttons (1 & 2).
Once i click on the "+" button or the "-" button, I can see the UILabel text increment, then it closes the UIAlertView.
This is what i currently am using:
#pragma Alert View Methods
-(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
{
[self dismissWithClickedButtonIndex:buttonIndex animated:animated];
}
#pragma count functions
-(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1 || buttonIndex == 2) {
return;
}
else{
[self dismissWithClickedButtonIndex:buttonIndex animated:YES];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1) {
self.currentCountButtonCount++;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",self.countButtonCount + 1]];
}if (buttonIndex == 2) {
self.currentCountButtonCount--;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",self.countButtonCount - 1]];
}
}
- (IBAction)countClick:(id)sender {
// tallies and keeps current count number
if (!self.currentCountButtonCount)
self.currentCountButtonCount = 0;
NSString *alertMessage = [NSString stringWithFormat:#"%d", self.countButtonCount];
self.countAlert = [[UIAlertView alloc]initWithTitle:#"Count" message:alertMessage delegate:self cancelButtonTitle:#"end" otherButtonTitles:#"+",#"-", nil];
[self.countAlert show];
}
On my last question someone told me to do it custom and this is what im trying now and it still dismisses the UIAlert.
How can i keep it up while the label changes until they touch the end button?
What are you using is default button of AlertView and after click on that button it will automatically dismissed the alertview.
So you have to create your buttons programatically and add that buttons in your alertview like:
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[btn setTitle:#"+" forState:UIControlStateNormal];
[countAlert addSubview:btn ];
on this btn call your method.
So you have to create two custom button with "+" and "-". and add that buttons in AlertView.
-(void)setAlertValue:(id)sender{
switch ([sender tag]) {
case 1:
{
// currentCountButtonCount++;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",++countButtonCount]];
}
break;
case 2:
{
//currentCountButtonCount--;
[self.countAlert setMessage:[NSString stringWithFormat:#"%d",--countButtonCount]];
}
break;
default:
break;
}
}
- (IBAction)countClick:(id)sender {
// tallies and keeps current count number
if (!currentCountButtonCount)
currentCountButtonCount = 0;
NSString *alertMessage = [NSString stringWithFormat:#"%d", countButtonCount];
self.countAlert = [[UIAlertView alloc]initWithTitle:#"Count" message:alertMessage delegate:self cancelButtonTitle:#"end" otherButtonTitles:nil, nil];
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(10, 50, 40, 20)];
[btn addTarget:self action:#selector(setAlertValue:) forControlEvents:UIControlEventTouchUpInside];
[btn setBackgroundColor:[UIColor greenColor]];
btn.tag = 1;
[btn setTitle:#"+" forState:UIControlStateNormal];
UIButton *btn1 = [[UIButton alloc] initWithFrame:CGRectMake(230, 50, 40, 20)];
[btn1 addTarget:self action:#selector(setAlertValue:) forControlEvents:UIControlEventTouchUpInside];
[btn1 setBackgroundColor:[UIColor redColor]];
btn1.tag = 2;
[btn1 setTitle:#"-" forState:UIControlStateNormal];
[countAlert addSubview:btn];
[countAlert addSubview:btn1];
[self.countAlert show];
}
I don't want to rain in your parade, but if you think that an alert view is the best way to handle an increment/decrement of a variable, I would suggest you to reconsider your design.
UIAlertViews are meant for transient information and simplified decision making. A simple "Are you sure?" is the text-book example of an alert view usage.
From the user stand point, it's much more comforting being able to modify all the attributes in sliders or any other form of permanent input, and then, when sure, hit the confirm button with an alert view (or confirmation screen). Doing it in an Alert view is not only error prone, but counter-intuitive compared in the way that the rest of iOS works.
If you're having trouble on fitting another form of input in your application, please read on how to perform animations and reveal control as they are needed, hiding the input inside an UIAlertView is simply the easiest solution for you, but not the best for the user.

Table View Cell Button Not Responding with it index position

I have Custom Table View Cell In That I Have Two UIButton and One Text Field Named As edit and cancel and one textField. When I Click on edit at same time TextFeild Interaction is Enabled And Cancel Button Image Should Change. Its Working Fine For Me!!
But When I am Clicking On Edit Button Another Cells Cancel bitton Image id Changed Automatically! I know that this happening because I'm reusing the cell!! But I'm not able to find a solution...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
simpleTableIdentifier = #"MenuNameCell";
cell = (MenuNameCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (!cell) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MenuNameCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
NSLog(#"---------new cell agin");
}
else
{
for (UIView *view in [cell.contentView subviews])
[view removeFromSuperview];
NSLog(#"---------older use");
// _checkButton = (UIButton *)[cell.contentView viewWithTag:indexPath.row];
// _cancelButton = (UIButton *)[cell.contentView viewWithTag:indexPath.row];
}
// Creating Label Menu Name
_nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 11, 82, 21)];
_nameLabel.backgroundColor = [UIColor clearColor];
_nameLabel.text = [_hotel._orderedMenus objectAtIndex:indexPath.row];
// Creating Label Menu Cost
_amountMenu = [[UILabel alloc] initWithFrame:CGRectMake(167, 13, 44, 21)];
_amountMenu.backgroundColor = [UIColor clearColor];
_amountMenu.text = [[_hotel._menuPrices objectAtIndex:indexPath.row] stringValue];
// Creating Text Field For Order Quantity
_textFieldQuantity = [[UITextField alloc] initWithFrame:CGRectMake(125,14,42,21)];
_textFieldQuantity.userInteractionEnabled = NO;
_textFieldQuantity.text = [[_hotel._selectedQuantity objectAtIndex:indexPath.row] stringValue];
// Creating Button For Check Order
_checkButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_checkButton setFrame:CGRectMake(232, 13, 25, 28)];
[_checkButton setBackgroundImage:[UIImage imageNamed:#"edit.png"]forState:UIControlStateNormal];
[_checkButton addTarget:self action:#selector(editQuantity:) forControlEvents:UIControlEventTouchUpInside];
[_checkButton setTag:indexPath.row];
// Creating Button For CANCEL Order
_cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_cancelButton setFrame:CGRectMake(265, 13, 25, 28)];
[_cancelButton setBackgroundImage:[UIImage imageNamed:#"cancel.png"] forState:UIControlStateNormal];
[_cancelButton addTarget:self action:#selector(cancelOreder:) forControlEvents:UIControlEventTouchUpInside];
[_cancelButton setTag:indexPath.row];
// Adding All To Call Content View
[cell.contentView addSubview:_nameLabel];
[cell.contentView addSubview:_amountMenu];
[cell.contentView addSubview:_textFieldQuantity];
[cell.contentView addSubview:_checkButton];
[cell.contentView addSubview:_cancelButton];
return cell;
}
Edit:
-(void)editQuantity:(id)sender
{
_textFieldQuantity.userInteractionEnabled = YES;
button = (UIButton *)sender;
row = button.tag;
NSLog(#"Check Button index is %d",row);
UIImage *buttonImage = [UIImage imageNamed:#"edit_over.png"];
[_checkButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
UIImage *buttonImageCancel = [UIImage imageNamed:#"check.png"];
[_cancelButton setBackgroundImage:buttonImageCancel forState:UIControlStateNormal];
_cancelButton.tag = 0;
}
-(void)cancelOreder:(id)sender{
button = (UIButton *)sender;
row = button.tag;
NSLog(#"The Row Selected iS At Cancel Order ISSSS----%d", row);
if (_cancelButton.tag == 0){
_textFieldQuantity.userInteractionEnabled = NO;
UIImage *buttonImageCancel = [UIImage imageNamed:#"check_over.png"];
[_cancelButton setBackgroundImage:buttonImageCancel forState:UIControlStateNormal];
UIImage *buttonImageCancel1 = [UIImage imageNamed:#"cancel.png"];
[_cancelButton setBackgroundImage:buttonImageCancel1 forState:UIControlStateNormal];
UIImage *buttonImage = [UIImage imageNamed:#"edit.png"];
[_checkButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
_cancelButton.tag = 1;
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"iHomeDelivery" message:#"Do You Want To Cancel the Order" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
Your problem is that _textFieldQuantity (and the others) is an instance variable. When editQuantity: and cancelOreder: are called the instance varialbe still has the same value that was set last time when adding a cell within cellForRowAtIndexPath: .
What could you do to fix it?
1st:
You could set the row in the tag of the button. Then, when the button is tapped on and the action is invoced get the tag and fetch the cell (you can call the table's cellForRowAtIndexPath method to get it. That is different from the delegate method that you implement) and then find the appropriate textField.
2nd:
A bit more work but probably smarter could be to implment a subclass of your table cell. Move the action methods to that very cell class. Doing so each button's action refers to an individual object wich is then the cell class and not the view controller. The cell class can have its own textField instance variables. It shoud even provide properties to the textField and other UIItems so that you can set their values in cellForRowAtIndexPath.
I would suggest the first solution as a quick starter. But for future use I strongly suggest to go the second way. That way will help you in similar situations in the future.

UILabel text not changing?

Unable to change text in lMenu_time (this is a UILabel) after it was initially set.
The call back is executed, I tested this, but the text won't change.
?? I am passing around the pointer and making adjustments to the UILabel. ??
lMenu_time and numerous others are defined in the header file. (not seen here)
UILabel *lMenu_time;
...
-(void) NewNumber: (UIButton*) btn {
if (btn.tag == 102){
iTime++;
[lbl setText:#"time"];
if(iTime > 20){iTime=1;}
[lMenu_time setText:[NSString stringWithFormat: #"Hold: %d", iTime]];
}
....
}
- (void) menuItem: (UIView*)vMenu menuButton:(UIButton*)bMenu menuLabel: (UILabel*)lMenu menuPosX: (double)posX menuLenX: (double)lenX menuTagNum: (int)tagNum menuText: (NSString*)txtMenu{
bMenu = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[bMenu setFrame:CGRectMake(posX,0,lenX,25)];
[bMenu setTag: tagNum];
[bMenu addTarget:self action:#selector(NewNumber:) forControlEvents:UIControlEventTouchUpInside];
[vMenu addSubview:bMenu];
lMenu = [[[UILabel alloc] initWithFrame:CGRectMake(posX,0,lenX,25)] retain];
[lMenu setBackgroundColor:[UIColor lightGrayColor]];
[lMenu setText:[NSString stringWithFormat: txtMenu]];
[lMenu setFont:[UIFont systemFontOfSize:14 ]];
[lMenu setTextAlignment:UITextAlignmentCenter];
[vMenu addSubview: lMenu];
}
- (void) menuBuild{
pSelf = self;
theString = #"";
UIView *vMenu = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,25)];
[pSelf.view addSubview:vMenu];
[vMenu setBackgroundColor:[UIColor grayColor]];
iTime = 2;
[self menuItem:vMenu menuButton:bMenu_time menuLabel:lMenu_time menuPosX:240+20 menuLenX:60 menuTagNum:102 menuText:[NSString stringWithFormat: #"Hold: %d", iTime]];
...
}
Just before you try to set the next, try adding
NSLog(#"My label is %#",lMenu_time);
Then, if your console outputs "My label is (nil)" you'll know that the problem is that the pointer to lMenu_time isn't being passed around properly.
Did you bind the label object to the controller in Interface builder? If not I would bet this is an retention issue. You do not post the code that builds the UILabel object, so if that is not done in IB, ensure you call retain or it will certainly be out of scope when you try and modify it.

Custom AlertView With Background

Everybody, I need to set one image on UIAlertView..
I have attached my UIAlertview with image prob..
i have used this code lines..
UIAlertView *theAlert = [[[UIAlertView alloc] initWithTitle:#"Atention"
message: #"YOUR MESSAGE HERE", nil)
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] autorelease];
[theAlert show];
UILabel *theTitle = [theAlert valueForKey:#"_titleLabel"];
[theTitle setTextColor:[UIColor redColor]];
UILabel *theBody = [theAlert valueForKey:#"_bodyTextLabel"];
[theBody setTextColor:[UIColor blueColor]];
UIImage *theImage = [UIImage imageNamed:#"Background.png"];
theImage = [theImage stretchableImageWithLeftCapWidth:16 topCapHeight:16];
CGSize theSize = [theAlert frame].size;
UIGraphicsBeginImageContext(theSize);
[theImage drawInRect:CGRectMake(0, 0, theSize.width, theSize.height)];
theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[theAlert layer] setContents:[theImage CGImage]];
please solve this issue..
i need only image with alert..
Try this...
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"UIAlert View" message:#"hello" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:#"Close",nil];
UIImage *alertImage = [UIImage imageNamed:#"plus.png"];
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:alertImage];
backgroundImageView.frame = CGRectMake(0, 0, 282, 130);
backgroundImageView.contentMode = UIViewContentModeScaleToFill;
[alert addSubview:backgroundImageView];
[alert sendSubviewToBack:backgroundImageView];
[alert show];
[alert release];
You should consider to not use UIAlertView, but have your own AlertView see TSAlertView for an alternative implementation, that is not derived from UIAlertView.
TSAlertView is allowing you to set your own background image.
Another solution that I am not recommending could be:
You can use introspection: Loop over the UIAlertViews subviews, identify the one that holds the background image set it hidden and place your own backroundimage at an index below/over the original image view.
I found this project: Subclass UIAlertView to customize the look of an alert. It is not working for iOS 4.2+, but with my introspection idea you can make it work again:
change the -layoutSubviews of JKCustomAlert to:
- (void) layoutSubviews {
for (UIView *v in [self subviews]) {
if ([v class] == [UIImageView class]) {
[v setHidden:YES];
}
}
alertTextLabel.transform = CGAffineTransformIdentity;
[alertTextLabel sizeToFit];
CGRect textRect = alertTextLabel.frame;
textRect.origin.x = (CGRectGetWidth(self.bounds) - CGRectGetWidth(textRect)) / 2;
textRect.origin.y = (CGRectGetHeight(self.bounds) - CGRectGetHeight(textRect)) / 2;
textRect.origin.y -= 30.0;
alertTextLabel.frame = textRect;
alertTextLabel.transform = CGAffineTransformMakeRotation(- M_PI * .08);
}
I am NOT promising, that this trick will work in future versions of iOS
A solution I like to use for this is to add a UIView to the ViewController, which mimics the appearance of an alert.
The other property of a UIAlertView is that no other part of the app can be used until the alert is dismissed. This can easily be mimicked by making your UIView a subview of another UIView (with a clear background), which takes up the entire screen.
If you don't want to implement that yourself, here's a Custom Alert View class you could use: https://github.com/shivsak/CustomAlertView