UITableViewCell and its ViewModel persistency in memory - ios

I noticed that my iOS app memory consumption is increasing while I'm scrolling table view. Using Allocations instrument I found out that some of table view cells are not retained and corresponding view models are not retained at all. What can be causing it? Memory leaks instrument didn't find any problems and I don't see any strong reference to the VM that can hold it into memory.
Here is code from tableView delegate/datasource:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
id<STReactiveView> cell = [tableView dequeueReusableCellWithIdentifier:_cellId];
STContact *contact;
if(!_searchController.active) {
contact = [[_arrangedData objectForKey:[_sectionTitles objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
}
else
contact = [_filteredData objectAtIndex:indexPath.row];
STContactsListItemViewModel *cellVM = [[STContactsListItemViewModel alloc] initWithContact:contact services:_services];
[cell bindViewModel:cellVM];
UITableViewCell *returnCell = (UITableViewCell *)cell;
return returnCell;
}
And from cell class:
#interface STContactViewCell()
#property (strong, nonatomic) IBOutlet UILabel *nameLabel;
#property (strong, nonatomic) IBOutlet UIButton *phoneButton;
#property (strong, nonatomic) IBOutlet UIButton *messageButton;
#property (strong, nonatomic) IBOutlet UILabel *statusLabel;
#property (strong, nonatomic) IBOutlet UIImageView *photoView;
#property (strong, nonatomic) IBOutlet UIImageView *statusImage;
#property (strong, nonatomic) STContactsListItemViewModel *viewModel;
#end
#implementation STContactViewCell
-(void)bindViewModel:(id)viewModel {
_viewModel = viewModel;
[self initialize];
}
-(void)initialize {
self.nameLabel.text = _viewModel.contact.name;
self.statusLabel.text = _viewModel.contact.statusText;
self.photoView.contentMode = UIViewContentModeScaleToFill;
if(_viewModel.contact.photo)
[self.photoView setImage:_viewModel.contact.photo];
else {
if(_viewModel.contact.url.length)
[self.photoView sd_setImageWithURL:[NSURL URLWithString:_viewModel.contact.url]];
else
[self.photoView setImage:[UIImage imageNamed:#"ContactPlaceholder"]];
}
[_statusImage setImage:[UIImage imageNamed:[NSString stringWithFormat:#"Status%#",_viewModel.contact.status]]];
[_phoneButton setImage:[UIImage imageNamed:[NSString stringWithFormat:#"Phone%#",_viewModel.contact.status]]forState:UIControlStateNormal];
[_phoneButton setImage:[UIImage imageNamed:[NSString stringWithFormat:#"Phone%#Dim",_viewModel.contact.status]]forState:UIControlStateHighlighted];
[_messageButton setImage:[UIImage imageNamed:[NSString stringWithFormat:#"Message%#",_viewModel.contact.status]]forState:UIControlStateNormal];
[_messageButton setImage:[UIImage imageNamed:[NSString stringWithFormat:#"Message%#Dim",_viewModel.contact.status]]forState:UIControlStateHighlighted];
_photoView.layer.cornerRadius = _photoView.frame.size.width/2;
_photoView.layer.masksToBounds = YES;
[_photoView setContentMode:UIViewContentModeScaleAspectFill];
_phoneButton.rac_command = _viewModel.executePhoneCall;
_messageButton.rac_command = _viewModel.executeMessageSend;
if([_viewModel.contact.status isEqualToString:#"Unavailable"]) {
[_phoneButton setEnabled:NO];
[_messageButton setEnabled:NO];
}
}
And last but not the least, screenshot of allocations:

Related

UIButton Label Resets When Clicked Inside A TableViewCell

I have a custom tableview cell, when I click the "quantity button" inside the cell, the value of the cell itself resets to the value defined the prototype cell on storyboard (which is "1"). So imagine I click the button under the image of the first cell, the label of the button changes from "5" to "1". I commented out all the code when button is pressed, so assume nothing ishapening there. Why is this?
My Custom Cell (.h)
#interface BLCartItemCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIImageView *imgView;
#property (weak, nonatomic) IBOutlet UILabel *title;
#property (weak, nonatomic) IBOutlet UIButton *quantityBtn;
#property (weak, nonatomic) IBOutlet UIButton *removeBtn;
#property (weak, nonatomic) IBOutlet UILabel *price;
#end
My Custom Cell (.m)
#implementation BLCartItemCell
#end
In my view controller:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// Section 0: Cart cells
static NSString *cartCellIdentifier = #"cartCell";
BLCartItemCell *cell = [tableView dequeueReusableCellWithIdentifier:cartCellIdentifier];
if (cell == nil) {
cell = [[BLCartItemCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cartCell"];
// [cell.removeBtn addTarget:self action:#selector(removeBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
// [cell.quantityBtn addTarget:self action:#selector(quantityBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
}
// Grab the cart item from cart and set the cell properties
BLCartItem *cartItem = [self.cart.items objectAtIndex:indexPath.row];
cell.title.text = cartItem.title;
cell.quantityBtn.titleLabel.text = [NSString stringWithFormat:#"%i", cartItem.quantity];
cell.price.text = [NSString stringWithFormat:#"$ %.2f", [cartItem totalPrice]];
NSData *image_data = [[NSData alloc] initWithContentsOfURL:cartItem.image];
cell.imgView.image = [UIImage imageWithData:image_data];
// Buttons will keep track of cell index
cell.quantityBtn.tag = indexPath.row;
cell.removeBtn.tag = indexPath.row;
return cell;
I removed the IBActions associated with the button, problem still happens.
I think it has problem when you set buttonTitle like that
cell.quantityBtn.titleLabel.text = [NSString stringWithFormat:#"%i", cartItem.quantity];
try :
[cell.quantityBtn setTitle: [NSString stringWithFormat:#"%i", cartItem.quantity] forState: UIControlStateNormal]];
Read more
Text change on UIButton doesn't stick
Apple Document

iOS UICollectionView memory leak

I've created UICollectionView through storyboard.
My cell is custom cell class that have 3 buttons with images.
My images are available as part of class GalleryItemInfo. I have an array of those objects
[GalleryDataProvider sharedInstance].itemInfo
There is code for cellForItemAtIndexPath (in one cell there are three buttons for three items in array):
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCellPreviewTriple *cell;
if (indexPath.row % 2 == 0 && !is_iPhone) {
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellOrangeRed" forIndexPath:indexPath];
if (is_Fingerprint_Version) {
cell.imageViewRope.image = [UIImage imageNamed:#"image-rope-1.png"];
}
} else {
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cellGreenBlue" forIndexPath:indexPath];
if (is_Fingerprint_Version) {
cell.imageViewRope.image = [UIImage imageNamed:#"image-rope-2.png"];
}
}
cell.previewCellDelegate = self;
cell.tag = indexPath.row;
NSInteger leftPreviedId = [cell firstPreviewId];
self.leftPreviewedID = leftPreviedId;
UIImage *image1 = ((GalleryItemInfo *)[[GalleryDataProvider sharedInstance].itemInfo objectAtIndex:leftPreviedId]).slotPreviewImage;
UIImage *image2;
UIImage *image3;
if (leftPreviedId + 1 < [[GalleryDataProvider sharedInstance].itemInfo count])
image2 = ((GalleryItemInfo *)[[GalleryDataProvider sharedInstance].itemInfo objectAtIndex:leftPreviedId + 1]).slotPreviewImage;
if (leftPreviedId + 2 < [[GalleryDataProvider sharedInstance].itemInfo count])
image3 = ((GalleryItemInfo *)[[GalleryDataProvider sharedInstance].itemInfo objectAtIndex:leftPreviedId + 2]).slotPreviewImage;
[cell setupWithImage1:image1 image2:image2 image3:image3];
if (self.isEditModeEnabled) {
[cell showRemoveButtons];
} else {
[cell hideRemoveButtons];
}
return cell;
}
Trouble: when I scroll my collection memory usage increases every swipe from right to left on about 1 megabyte.
Why memory is not released?
Update:
CollectionViewCellPreviewTriple code (created through storyboard):
#import <UIKit/UIKit.h>
#protocol UICollectionViewPreviewCellDelegate;
#interface CollectionViewCellPreviewTriple : UICollectionViewCell
#property (weak, nonatomic) IBOutlet UIButton *buttonSlot1;
#property (weak, nonatomic) IBOutlet UIButton *buttonSlot2;
#property (weak, nonatomic) IBOutlet UIButton *buttonSlot3;
#property (weak, nonatomic) IBOutlet UIButton *buttonRemove1;
#property (weak, nonatomic) IBOutlet UIButton *buttonRemove2;
#property (weak, nonatomic) IBOutlet UIButton *buttonRemove3;
#property (weak, nonatomic) IBOutlet UIImageView *imageViewRope;
#property (nonatomic, weak) id<UICollectionViewPreviewCellDelegate> previewCellDelegate;
- (void)setupWithImage1:(UIImage *)image1 image2:(UIImage *)image2 image3:(UIImage *)image3;
- (void)showRemoveButtons;
- (void)hideRemoveButtons;
- (NSInteger)firstPreviewId;
#end
#protocol UICollectionViewPreviewCellDelegate
- (void)collectionViewPreviewCell:(CollectionViewCellPreviewTriple *)collectionViewCell didSelectSubitemWithIndex:(NSInteger)subitemIndex;
- (void)collectionViewPreviewCell:(CollectionViewCellPreviewTriple *)collectionViewCell didEditModeRequestWithStatus:(BOOL)status;
- (void)collectionViewPreviewCell:(CollectionViewCellPreviewTriple *)collectionViewCell didRemoveRequestWithIndex:(NSInteger)subitemIndex;
- (void)slotButtonRequestsShadow:(UIButton *)slotButton;
#end
Update:
- (void)setupWithImage1:(UIImage *)image1 image2:(UIImage *)image2 image3:(UIImage *)image3
{
[self.buttonSlot1 setBackgroundImage:image1 forState:UIControlStateNormal];
[self.buttonSlot1 setBackgroundImage:image1 forState:UIControlStateHighlighted];
//if (image2) {
[self.buttonSlot2 setBackgroundImage:image2 forState:UIControlStateNormal];
[self.buttonSlot2 setBackgroundImage:image2 forState:UIControlStateHighlighted];
[self.buttonSlot2 setHidden:(image2 == nil)];
//}
//if (image3) {
[self.buttonSlot3 setBackgroundImage:image3 forState:UIControlStateNormal];
[self.buttonSlot3 setBackgroundImage:image3 forState:UIControlStateHighlighted];
[self.buttonSlot3 setHidden:(image3 == nil)];
//}
}
Profiling
link for screen
This may be related to the issue that many people have been suffering with where the cell's are not reused.
To test this, you should override the method prepareForReuse and in it write a very simple log:
NSLog(#"%# is being called as expected.", NSStringFromSelector(_cmd));
You should then run your app, scroll the collection view, and check the console to see if this log appears.
If this log does not appear, you may want to check this answer for help as to how to proceed. In my app cells are not reused in the simulator, but are reused on devices. It's odd.

Should I redesign this implementation or can I dynamically add cells to a StaticTableViewController

I have a contacts application and I have a view where the user can click to see "detailed" information on the user. In this detailed view, it will ONLY show fields that have a value, and hide the rest. When the user clicks "Edit", it will show ALL fields to allow the user to edit.
Let me show some screens of this
I am using a third party StaticDataTableViewController class to hide and show cells.
Here is my actual question
I made this post where I asked how to handle emails and phone numbers more dynamically instead of defining "work email", "home email", "work phone", "home phone".
I need to figure out a way to display and represent dynamically generated emails / phone numbers. If the user has 5 phone numbers, then I want to show 5 phone numbers plus their label (home,work). I will have all of these stored in an NSArray of NSDictionaries (key = label, value = email / phone) and there will be two of those NSArrays per contact.
I just need some assistance on how to be dynamic and static at the same time? I don't want to lose the functionality of hiding cells.
I will paste the class that handles my table view.
SingleContactViewController.h
#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import "PublicContactsViewController.h"
#import "Person.h"
#import "SingleContactTableViewCell.h"
#import "StaticDataTableViewController.h"
#import "DTAlertView.h"
#interface SingleContactViewController : StaticDataTableViewController <UITextFieldDelegate,UIAlertViewDelegate>
#property (nonatomic, strong) Person *person;
#property (strong, nonatomic) IBOutlet UIBarButtonItem *editButton;
// TextFields are embedded in the cell, was just easier to make an outlet
#property (strong, nonatomic) IBOutlet UITextField *firstNameTextField;
#property (strong, nonatomic) IBOutlet UITextField *lastNameTextField;
#property (strong, nonatomic) IBOutlet UITextField *homeEmailTextField;
#property (strong, nonatomic) IBOutlet UITextField *workEmailTextField;
#property (strong, nonatomic) IBOutlet UITextField *companyNameTextField;
#property (strong, nonatomic) IBOutlet UITextField *homePhoneNumberTextField;
#property (strong, nonatomic) IBOutlet UITextField *workPhoneNumberTextField;
#property (strong, nonatomic) IBOutlet UITextField *cellPhoneNumberTextField;
// Outlet to cells to hide/unhide
#property (weak, nonatomic) IBOutlet SingleContactTableViewCell *firstNameCell;
#property (weak, nonatomic) IBOutlet SingleContactTableViewCell *lastNameCell;
#property (weak, nonatomic) IBOutlet SingleContactTableViewCell *homeEmailCell;
#property (weak, nonatomic) IBOutlet SingleContactTableViewCell *workEmailCell;
#property (weak, nonatomic) IBOutlet SingleContactTableViewCell *companyNameCell;
#property (weak, nonatomic) IBOutlet SingleContactTableViewCell *homePhoneNumberCell;
#property (weak, nonatomic) IBOutlet SingleContactTableViewCell *workPhoneNumberCell;
#property (weak, nonatomic) IBOutlet SingleContactTableViewCell *cellPhoneNumberCell;
#property (strong, nonatomic) IBOutlet SingleContactTableViewCell *deleteContactCell;
- (IBAction)deleteContact:(UIButton *)sender;
#end
SingleContactViewController.m
#import "SingleContactViewController.h"
#import "Person.h"
#interface SingleContactViewController ()
//#property (strong, nonatomic) IBOutlet ADBannerView *banner;
#property (nonatomic, assign) BOOL isEditing;
- (IBAction)popBackToContacts:(UIBarButtonItem *)sender;
- (IBAction)editContact:(UIBarButtonItem *)sender;
#end
#implementation SingleContactViewController
#pragma mark - Lifecycle methods
- (void)viewWillAppear:(BOOL)animated
{
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:.498 green:0 blue:.0 alpha:1];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.firstNameTextField.delegate = self;
[self populateFieldsAndHideEmptyCells];
//Disable the highlight effect of clicking a table row
[self.firstNameCell setSelectionStyle:UITableViewCellSelectionStyleNone];
[self.lastNameCell setSelectionStyle:UITableViewCellEditingStyleNone];
[self.homeEmailCell setSelectionStyle:UITableViewCellEditingStyleNone];
[self.workEmailCell setSelectionStyle:UITableViewCellEditingStyleNone];
[self.companyNameCell setSelectionStyle:UITableViewCellEditingStyleNone];
[self.homePhoneNumberCell setSelectionStyle:UITableViewCellEditingStyleNone];
[self.workPhoneNumberCell setSelectionStyle:UITableViewCellEditingStyleNone];
[self.cellPhoneNumberCell setSelectionStyle:UITableViewCellEditingStyleNone];
[self.deleteContactCell setSelectionStyle:UITableViewCellEditingStyleNone];
[self.tableView setBackgroundColor:[UIColor lightGrayColor]];
}
#pragma mark - Editing Methods
- (IBAction)editContact:(UIBarButtonItem *)sender {
NSLog(#"User pressed 'Edit' button. Entered editContact method");
if ([self isEditing]) {
NSLog(#"Turning edit more off");
UIBarButtonItem *newButton = [[UIBarButtonItem alloc]initWithTitle:#"Edit" style:UIBarButtonSystemItemDone target:self action:#selector(editContact:)];
self.navigationItem.rightBarButtonItem = newButton;
_editButton = newButton;
[self updatePrivateContact];
self.isEditing = NO;
}
else {
NSLog(#"Turning edit mode on");
UIBarButtonItem *newButton = [[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonSystemItemEdit target:self action:#selector(editContact:)];
self.navigationItem.rightBarButtonItem = newButton;
_editButton = newButton;
self.isEditing = YES;
[self showAllFieldsForEditing];
}
}
#pragma mark - Hide/Show Table Cells
- (void)populateFieldsAndHideEmptyCells
{
self.hideSectionsWithHiddenRows = YES;
if([self.person.firstName length] == 0){
NSLog(#"firstName not present. Hide Cell");
[self cell:self.firstNameCell setHidden:YES];
}else{
self.firstNameTextField.text = [self.person firstName];
[self.firstNameTextField setClearButtonMode:UITextFieldViewModeNever];
[self.firstNameTextField setEnabled:NO];
}
if([self.person.lastName length] == 0){
NSLog(#"lastName not present. Hide Cell");
[self cell:self.lastNameCell setHidden:YES];
}else{
self.lastNameTextField.text = [self.person lastName];
[self.lastNameTextField setClearButtonMode:UITextFieldViewModeNever];
[self.lastNameTextField setEnabled:NO];
}
if([self.person.companyName length] == 0){
[self cell:self.companyNameCell setHidden:YES];
}else{
self.companyNameTextField.text = [self.person companyName];
[self.companyNameTextField setClearButtonMode:UITextFieldViewModeNever];
[self.companyNameTextField setEnabled:NO];
}
if([self.person.homeEmail length] == 0){
[self cell:self.homeEmailCell setHidden:YES];
}else{
self.homeEmailTextField.text = [self.person homeEmail];
[self.homeEmailTextField setClearButtonMode:UITextFieldViewModeNever];
[self.homeEmailTextField setEnabled:NO];
}
NSLog(#"person.workemail: %#",[self.person workEmail]);
if([self.person.workEmail length] == 0){
[self cell:self.workEmailCell setHidden:YES];
}else{
self.workEmailTextField.text = [self.person workEmail];
[self.workEmailTextField setClearButtonMode:UITextFieldViewModeNever];
[self.workEmailTextField setEnabled:NO];
}
if([self.person.homePhone length] == 0){
NSLog(#"home phone field not present. Hide Cell");
[self cell:self.homePhoneNumberCell setHidden:YES];
}else{
self.homePhoneNumberTextField.text = [self.person homePhone];
[self.homePhoneNumberTextField setClearButtonMode:UITextFieldViewModeNever];
[self.homePhoneNumberTextField setEnabled:NO];
}
if([self.person.workPhone length] == 0){
NSLog(#"work phone field not present. Hide Cell");
[self cell:self.workPhoneNumberCell setHidden:YES];
}else{
self.workPhoneNumberTextField.text = [self.person workPhone];
[self.workPhoneNumberTextField setClearButtonMode:UITextFieldViewModeNever];
[self.workPhoneNumberTextField setEnabled:NO];
}
if([self.person.cellPhone length] == 0){
NSLog(#"cell phone field not present. Hide Cell");
[self cell:self.cellPhoneNumberCell setHidden:YES];
}else{
self.cellPhoneNumberTextField.text = [self.person cellPhone];
[self.cellPhoneNumberTextField setClearButtonMode:UITextFieldViewModeNever];
[self.cellPhoneNumberTextField setEnabled:NO];
}
[self cell:self.deleteContactCell setHidden:YES]; // Only show on Edit
[self reloadDataAnimated:YES];
}
- (void) showAllFieldsForEditing
{
NSLog(#"showAllFieldsForEditing method entered");
self.hideSectionsWithHiddenRows = NO;
[self cell:self.firstNameCell setHidden:NO];
[self cell:self.lastNameCell setHidden:NO];
[self cell:self.companyNameCell setHidden:NO];
[self cell:self.homeEmailCell setHidden:NO];
[self cell:self.workEmailCell setHidden:NO];
[self cell:self.homePhoneNumberCell setHidden:NO];
[self cell:self.workPhoneNumberCell setHidden:NO];
[self cell:self.cellPhoneNumberCell setHidden:NO];
[self cell:self.deleteContactCell setHidden:NO];
[self.firstNameTextField setClearButtonMode:UITextFieldViewModeUnlessEditing];
[self.lastNameTextField setClearButtonMode:UITextFieldViewModeUnlessEditing];
[self.companyNameTextField setClearButtonMode:UITextFieldViewModeUnlessEditing];
[self.homeEmailTextField setClearButtonMode:UITextFieldViewModeUnlessEditing];
[self.workEmailTextField setClearButtonMode:UITextFieldViewModeUnlessEditing];
[self.homePhoneNumberTextField setClearButtonMode:UITextFieldViewModeUnlessEditing];
[self.workPhoneNumberTextField setClearButtonMode:UITextFieldViewModeUnlessEditing];
[self.cellPhoneNumberTextField setClearButtonMode:UITextFieldViewModeUnlessEditing];
[self.firstNameTextField setEnabled:YES];
[self.lastNameTextField setEnabled:YES];
[self.companyNameTextField setEnabled:YES];
[self.workEmailTextField setEnabled:YES];
[self.homeEmailTextField setEnabled:YES];
[self.homePhoneNumberTextField setEnabled:YES];
[self.workPhoneNumberTextField setEnabled:YES];
[self.cellPhoneNumberTextField setEnabled:YES];
[self reloadDataAnimated:YES];
}
#pragma mark - Navigation Methods
- (IBAction)popBackToContacts:(UIBarButtonItem *)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - Table View Methods
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
#pragma mark - Update Edit Data
- (void)updatePrivateContact
{
// Logic here to save to database
}
#pragma mark - Helper Methods
- (BOOL)isAnyEmailPresent
{
if([self.person homeEmail] != nil || [self.person workEmail] != nil){
return YES;
}else{
return NO;
}
}
- (Person *)populatePersonToSave
{
Person *person = [[Person alloc] init];
person.firstName = self.firstNameTextField.text;
person.lastName = self.lastNameTextField.text;
person.workEmail = self.workEmailTextField.text;
person.homeEmail = self.homeEmailTextField.text;
person.companyName = self.companyNameTextField.text;
person.homePhone = self.homePhoneNumberTextField.text;
person.workPhone = self.workPhoneNumberTextField.text;
person.cellPhone = self.cellPhoneNumberTextField.text;
return person;
}
#pragma mark - Table View Methods
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundColor = [UIColor lightGrayColor];
cell.textLabel.textColor = [UIColor whiteColor];
}
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
// Set the text color of our header/footer text.
UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view;
[header.textLabel setTextColor:[UIColor whiteColor]];
// Set the background color of our header/footer.
header.contentView.backgroundColor = [UIColor lightGrayColor];
// You can also do this to set the background color of our header/footer,
// but the gradients/other effects will be retained.
// view.tintColor = [UIColor blackColor];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
return nil;
} else {
return [super tableView:tableView titleForHeaderInSection:section];
}
}
#end
after looking over the code. The StaticDataTableViewController uses the tableview to display the cells you want it to display based on their own "OriginalRow" class.
These are held in a Mutable Array within their "OriginalSection" class under the property "rows".
The original sections are held in a mutable array on the "OriginalTable" class under a property called "sections"
The original table is your main definition for what your table should contain, and is held on the "StaticDataTableViewController" under a property called "originalTable"
All of the Business of determining what cells to show and what cells to hide is done in "-[OriginalTable prepareUpdates]" which iterates through the sections and each row within to determine what to show and what to hide.
The "-[OriginalTable sections]" array and "-[OriginalSection rows]" arrays continue to contain all sections and rows respectively regardless of their visibility or invisibility, therefore if you edit those arrays and call "-[StaticDataTableViewController reloadData]" you will obtain the actions you are looking for.
To accomplish this you will need to move the "#interface" for each class to the header so you will have access to it.
when you have moved the "#interface" for OriginalRow, OriginalSection and OriginalTable to the header, you are most of the way there.
The last thing to do is move the property from the private category for StaticDataTableViewController to the public interface.
#interface StaticDataTableViewController ()
#property (nonatomic, strong) OriginalTable * originalTable; // Cut this line.
#end
take the marked line and move it to the header in the public interface to make it a public property
#interface StaticDataTableViewController : UITableViewController // Paste after this line
After you have made those changes you should be able to add and remove Sections and Rows at will.
[[[[ThisStaticTable.originalTable sections] objectAtIndex:0] rows]
insertObject:myNewOriginalRow atIndex:2];
[ThisStaticTable reloadData];
This should get you well on your way.

Object from UIStoryboard become nil if I use setters

I have some labels on UITableviewcell I want to change the label font in the setter but from some odd reason in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
When I debugging I can see nothing inside the cell get allocated.
When I drop the setters everything work fine but with system font which I don't want to use.
Cell.h file
#import <UIKit/UIKit.h>
#interface CheckoutCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *labelQuantity;
#property (weak, nonatomic) IBOutlet UILabel *labelMainDescription;
#property (weak, nonatomic) IBOutlet UILabel *labelCountName;
#property (weak, nonatomic) IBOutlet UILabel *labelInchSize;
#property (weak, nonatomic) IBOutlet UILabel *labelMMsize;
#property (weak, nonatomic) IBOutlet UILabel *labelStaticTotal;
#property (weak, nonatomic) IBOutlet UILabel *labelTotalPrice;
#property (weak, nonatomic) IBOutlet UILabel *label_ItemPrice;
#property (weak, nonatomic) IBOutlet UIButton *btnBuyAnotherProduct;
#property (weak, nonatomic) IBOutlet UIButton *btnAddAnotherSet;
#end
cell.m file
#import "CheckoutCell.h"
#implementation CheckoutCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void) setLabelCountName:(UILabel *)labelCountName
{
[self setLabel:labelCountName];
}
-(void) setLabelMMsize:(UILabel *)labelMMsize
{
[self setLabel:labelMMsize];
}
-(void) setLabel_ItemPrice:(UILabel *)label_ItemPrice
{
[self setLabel:label_ItemPrice];
}
-(void) setLabelInchSize:(UILabel *)labelInchSize
{
[self setLabel:labelInchSize];
}
-(void) setLabelMainDescription:(UILabel *)labelMainDescription
{
[labelMainDescription setFont:[UIFont fontWithName:#"MuseoSans-500" size:14]];
}
-(void) setLabelQuantity:(UILabel *)labelQuantity
{
[labelQuantity setFont:[UIFont fontWithName:#"MuseoSans-500" size:18]];
}
-(void) setLabelTotalPrice:(UILabel *)labelTotalPrice
{
[labelTotalPrice setFont:[UIFont fontWithName:#"MuseoSans-500" size:14]];
}
-(void) setLabelStaticTotal:(UILabel *)labelStaticTotal
{
[labelStaticTotal setFont:[UIFont fontWithName:#"MuseoSans-500" size:14]];
}
//BTN setters
-(void) setBtnAddAnotherSet:(UIButton *)btnAddAnotherSet
{
[btnAddAnotherSet.titleLabel setFont:[UIFont fontWithName:#"MuseoSans-500" size:12]];
btnAddAnotherSet.titleLabel.textAlignment = UIBaselineAdjustmentAlignCenters;
}
-(void) setBtnBuyAnotherProduct:(UIButton *)btnBuyAnotherProduct
{
[btnBuyAnotherProduct.titleLabel setFont:[UIFont fontWithName:#"MuseoSans-500" size:12]];
btnBuyAnotherProduct.titleLabel.textAlignment = UIBaselineAdjustmentAlignCenters;
}
//generic setter
-(void) setLabel:(UILabel *)label
{
[label setFont:[UIFont fontWithName:#"MuseoSans-300" size:10]];
}
#end
I believe you should just set the text of the label not create and set the label again. for example
-(void) setLabelCountName:(UILabel *)labelCountName{
[self setLabel:labelCountName];
}
should be
-(void) setLabelCountName:(NSString *)labelCountName{
[self.labelCountName setText:labelCountName];
}
also you should change the Font in StoryBoard designer or in initWith... method.

Changing Image on selected state of UITablView cell

I have a created a custom cell and added one label and Image, I have 4 rows in my table each row has a different image and each row opens a different view controller, so, now what I need is on click of a particular row I want the image to change to do that I tried this, but its not working, so please help me out.
if(indexPath.row == 0)
{
if(cell.selected == true)
{
UIImage *cellImage = [UIImage imageNamed:#"abc.png"];
cell.icon.image = cellImage;
}
else
{
UIImage *cellImage = [UIImage imageNamed:#"abc.png"];
cell.icon.image = cellImage;
}
}
Regards
Ranjit
Try to do following when creating your cell or in tableView:willDisplayCell:forRowAtIndexPath: method:
cell.imageView.image = [UIImage imageNamed:#"abc.png"];
cell.imageView.highlightedImage = [UIImage imageNamed:#"abc.png"];
It will work for your icon property too if it is UIImageView
First create a property in your custom cell for uiImageview and synthesize it..
and the in didSelectRowAtIndexPath delegate method of UITabeView access the property and change the image something like :-
yourCell.yourImageView.image=[UIImage imageNamed:#"yourImage"]
For Sample I am giving my Code :-
#import <UIKit/UIKit.h>
#interface CustomizedCellProductDetails : UITableViewCell {
UILabel *sNO;
UILabel *abcWine;
UILabel *redWine;
UILabel *two;
UILabel *hundred;
UILabel *fourTwo;
UILabel *twoOne;
UIImageView *imgView;
UILabel *itemNo;
UILabel *itemName;
UILabel *itemDesc;
UILabel *department;
UILabel *qtyAvailable;
UIButton *check;
}
#property (nonatomic , retain) UILabel *sNO;
#property (nonatomic , retain) UILabel *abcWine;
#property (nonatomic , retain) UILabel *redWine;
#property (nonatomic , retain) UILabel *two;
#property (nonatomic , retain) UILabel *hundred;
#property (nonatomic , retain) UILabel *fourTwo;
#property (nonatomic , retain) UILabel *twoOne;
#property (nonatomic , retain) UIImageView *imgView;
#property (nonatomic , retain) UILabel *itemNo;
#property (nonatomic , retain) UILabel *itemName;
#property (nonatomic , retain) UILabel *itemDesc;
#property (nonatomic , retain) UILabel *department;
#property (nonatomic , retain) UILabel *qtyAvailable;
#property (nonatomic , retain) UIButton *check;
-(void) clicked;
#end
.m file synthesize it:-
#import "CustomizedCellProductDetails.h"
#implementation CustomizedCellProductDetails
#synthesize sNO,abcWine,redWine,two,hundred,fourTwo,twoOne,imgView,itemNo,itemName,itemDesc,department,qtyAvailable,check;
in tableview delegate :-
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
CustomizedCellProductDetails * cell = (CustomizedCellProductDetails )[tableView cellForRowAtIndexPath:indexPath];
[cell.imgView setImage:[UIImage imageNamed:#"wine.png"]];
}
Try to do following when creating your cell ...
In Implementation Block...
#implementation ABC
{
NSMutableArray *imageArray;
NSMutableArray *imageSelectedArray;
}
Do this In the below method
(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
[cell.imageView setImage:[UIImage imageNamed:[imageArray objectAtIndex:indexPath.row]]];
[cell.imageView setHighlightedImage:[UIImage imageNamed:[imageSelectedArray objectAtIndex:indexPath.row]]];
}

Resources