I'm working with two custom UITableViewCell subclasses. They're both designed to hold the contents of a Tweet, one specific just to Tweets with text and the other for Tweets with text and an image. I'm creating both cells programatically in the subclasses and using PureLayout for auto-layout to avoid sizing issues.
Now when the tweets in the cells initially load, everything's fine and those with images in appear as they should using the right subclass and vice versa for those without images. But when I start to scroll the cells without text suddenly appear with the UIImageViews and images within them - even though there's not an actual image for the Tweet, they're loading images off the other Tweets.
I'm not sure what's going on, I believe it's an issue where i'm loading and setting up the cells in:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Although i'm also using SDWebImage to asynchronously load the images - however it works perfectly fine for the profile images with no issues on loading different images. This might be because both the TweetWithImageCell and TweetNormalCell have profile images.
Can anyone shed some light on the best method of doing this to make it work correctly?
Code is as below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *tweet = [tweetsArray objectAtIndex:indexPath.row];
if ([[tweet objectForKey:#"entities"] objectForKey:#"media"]) {
if ([[[tweet objectForKey:#"entities"] objectForKey:#"media"]isKindOfClass:[NSArray class]]) {
tweetMedia = [[tweet objectForKey:#"entities"] objectForKey:#"media"];
} else {
}
}
if ([tweetMedia objectAtIndex:0]) {
//Initial cell setup
StreamPhotoTableViewCell *cell = (StreamPhotoTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifierPhoto];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
if (cell == nil) {
cell = tweetPhotoCell;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
NSDictionary *tweetMediaFirst = [tweetMedia objectAtIndex:0];
NSString *tweetMediaUrl = [tweetMediaFirst objectForKey:#"media_url"];
[cell updateFonts];
cell.titleLabel.text = [[tweet objectForKey:#"user"] objectForKey:#"name"];
cell.userNameLabel.text = [NSString stringWithFormat:#"#%#",[[tweet objectForKey:#"user"] objectForKey:#"screen_name"]];
cell.bodyLabel.text = [tweet objectForKey:#"text"];
[cell.tweetImageView sd_setImageWithURL:[NSURL URLWithString:tweetMediaUrl]
placeholderImage:[UIImage imageNamed:#"tweetImagePlaceholder"]];
NSString *profileImageUrl = [[tweet objectForKey:#"user"] objectForKey:#"profile_image_url"];
NSString *profileImageCheck = [profileImageUrl substringFromIndex: [profileImageUrl length] - 4];
if([profileImageCheck isEqual:#".png"])
{
NSString *profileShort = [profileImageUrl substringToIndex:[profileImageUrl length] - 11];
profileImageUrlBigger = [NSString stringWithFormat:#"%#.png", profileShort];
}
else if([profileImageCheck isEqualToString:#"jpeg"])
{
NSString *profileShort = [profileImageUrl substringToIndex:[profileImageUrl length] - 12];
profileImageUrlBigger = [NSString stringWithFormat:#"%#.jpeg", profileShort];
}
else if([profileImageCheck isEqualToString:#".jpg"])
{
NSString *profileShort = [profileImageUrl substringToIndex:[profileImageUrl length] - 11];
profileImageUrlBigger = [NSString stringWithFormat:#"%#.jpg", profileShort];
}
[cell.profileImageView sd_setImageWithURL:[NSURL URLWithString:profileImageUrlBigger]
placeholderImage:[UIImage imageNamed:#"tweetImagePlaceholder"]];
//Reply button setup/action
[cell.replyButton addTarget:self action:#selector(replyButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell.replyButton setAccessibilityHint:[[tweet objectForKey:#"user"] objectForKey:#"screen_name"]];
//Retweet button setup/action
if([[tweet objectForKey:#"retweeted"] isEqual:#0]) {
[cell.retweetButton addTarget:self action:#selector(retweetButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell.retweetButton setImage:[UIImage imageNamed:#"retweetIcon"] forState:UIControlStateNormal];
[cell.retweetButton setAccessibilityHint:[tweet objectForKey:#"id_str"]];
}
else {
[cell.retweetButton addTarget:self action:#selector(retweetedButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell.retweetButton setImage:[UIImage imageNamed:#"retweetedIcon"] forState:UIControlStateNormal];
[cell.retweetButton setAccessibilityHint:[tweet objectForKey:#"id_str"]];
}
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
return cell;
}
else {
//Initial cell setup
StreamTableViewCell *cell = (StreamTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
if (cell == nil) {
cell = tweetCell;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
[cell updateFonts];
cell.titleLabel.text = [[tweet objectForKey:#"user"] objectForKey:#"name"];
cell.userNameLabel.text = [NSString stringWithFormat:#"#%#",[[tweet objectForKey:#"user"] objectForKey:#"screen_name"]];
cell.bodyLabel.text = [tweet objectForKey:#"text"];
NSString *profileImageUrl = [[tweet objectForKey:#"user"] objectForKey:#"profile_image_url"];
NSString *profileImageCheck = [profileImageUrl substringFromIndex: [profileImageUrl length] - 4];
if([profileImageCheck isEqual:#".png"])
{
NSString *profileShort = [profileImageUrl substringToIndex:[profileImageUrl length] - 11];
profileImageUrlBigger = [NSString stringWithFormat:#"%#.png", profileShort];
}
else if([profileImageCheck isEqualToString:#"jpeg"])
{
NSString *profileShort = [profileImageUrl substringToIndex:[profileImageUrl length] - 12];
profileImageUrlBigger = [NSString stringWithFormat:#"%#.jpeg", profileShort];
}
else if([profileImageCheck isEqualToString:#".jpg"])
{
NSString *profileShort = [profileImageUrl substringToIndex:[profileImageUrl length] - 11];
profileImageUrlBigger = [NSString stringWithFormat:#"%#.jpg", profileShort];
}
[cell.profileImageView sd_setImageWithURL:[NSURL URLWithString:profileImageUrlBigger]
placeholderImage:[UIImage imageNamed:#"tweetImagePlaceholder"]];
//Reply button setup/action
[cell.replyButton addTarget:self action:#selector(replyButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell.replyButton setAccessibilityHint:[[tweet objectForKey:#"user"] objectForKey:#"screen_name"]];
//Retweet button setup/action
[cell.retweetButton setAccessibilityHint:[tweet objectForKey:#"id_str"]];
if([[tweet objectForKey:#"retweeted"] isEqual:#0]) {
[cell.retweetButton addTarget:self action:#selector(retweetButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell.retweetButton setImage:[UIImage imageNamed:#"retweetIcon"] forState:UIControlStateNormal];
}
else {
[cell.retweetButton addTarget:self action:#selector(retweetedButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell.retweetButton setImage:[UIImage imageNamed:#"retweetedIcon"] forState:UIControlStateNormal];
}
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
return cell;
}
return nil;
}
This condition will be true if your array have elements in it. So the else part won't execute in that case.
if ([tweetMedia objectAtIndex:0])
Oddly enough this seemed to solve the problem:
if ([[[[tweetsArray objectAtIndex:indexPath.row] objectForKey:#"entities"] objectForKey:#"media"] objectAtIndex:0])
Rather than already assigning the contents of the NSDictionary *tweet and NSMutableArray *tweetMedia and deliberately accessing the main tweetsArray through indexPath of each cell.
Related
When my user searches for something inside a tableview, when no results are returned, my app shows the standard "No Results" placeholder inside the tableview. That said, when no results exist, I want to return one populated cell (cell populated with default data). How can I accomplish this? I tried the below, but I still get 'No Results' returned?
ViewController.m
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.searchDisplayController.searchResultsTableView) {
if ([searchResults count] == 0) {
return 1;
} else {
return [searchResults count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *NetworkTableIdentifier = #"sidebarCell";
self.sidetableView.separatorStyle = UITableViewCellSeparatorStyleNone;
sidebarCell *cell = (sidebarCell *)[tableView dequeueReusableCellWithIdentifier:NetworkTableIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"sidebarCell" owner:self options:nil];
cell = nib[0];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
NSDictionary *userName = searchResults[indexPath.row];
NSString *first = userName[#"first name"];
NSString *last = userName[#"last name"];
[[cell username] setText:[NSString stringWithFormat:#"%# %#", first, last]];
NSDictionary *userlast = searchResults[indexPath.row];
[[cell lastName] setText:userlast[#"last name"]];
NSDictionary *userBio = searchResults[indexPath.row];
[[cell userDescription] setText:userBio[#"userbio"]];
NSString *area = userName[#"neighbourhood"];
NSString *city = userName[#"city"];
[[cell areaLabel] setText:[NSString stringWithFormat:#"%#, %#", area, city]];
NSString *profilePath = searchResults[indexPath.row][#"photo_path"];
[cell.usermini sd_setImageWithURL:[NSURL URLWithString:profilePath]];
if ([searchResults count] == 0) {
NSLog(#"SEARCH RESULTS ARE %#", searchResults);
[[cell username] setText:[NSString stringWithFormat:#"%#", self.searchBar.text]];
[[cell lastName] setText:userlast[#""]];
[[cell userDescription] setText:#"This friend is not on the app (yet!) Tap to invite them."];
[[cell areaLabel] setText:[NSString stringWithFormat:#""]];
NSString *profileDefault = #"http://url.com/user.png";
[cell.usermini sd_setImageWithURL:[NSURL URLWithString:profileDefault]];
return cell;
}
return cell;
}
I don't really recommend doing this, as you should return an empty list, if there are no search results. That is consistent with User Interface Guidelines. But, if you insist, you could create a default object and initialize your searchResults array with that object and return 1 from the numberOfRows method. Something like this:
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
if ([searchResults count] == 0) {
NSDictionary *dict = [NSDictionary dictionaryWithObjects:#[#“Enter First Name”, #“Enter Last Name”, #“Enter User Bio”, #“Enter Neighborhood”, #“Enter City”, #“Enter Photo Path”]
forKeys: #[#“first_name”, #“last_name, #“userbio”, #“neighbourhood”, #“city”, #“photo_path”];
searchResults = [NSArray arrayWithObjects: dict, nil];
return 1;
}
else {
return [searchResults count];
}
}
And, you can greatly simplify your cellForRowAtIndexPath code as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *NetworkTableIdentifier = #"sidebarCell";
self.sidetableView.separatorStyle = UITableViewCellSeparatorStyleNone;
sidebarCell *cell = (sidebarCell *)[tableView dequeueReusableCellWithIdentifier:NetworkTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"sidebarCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
//Note, I like to name my local variables the same as the dictionary keys just to eliminate any confusion
NSDictionary *userObject = [searchResults objectAtIndex:indexPath.row];
NSString *first_name = [userObject objectForKey:#"first name"];
NSString *last_name = [userObject objectForKey:#"last name"];
NSString *userbio = [userObject objectForKey:#“userbio”];
NSString *neighbourhood = [userObject objectForKey:#“neighbourhood”];
NSString *city = [userObject objectForKey:#“city”];
NSString *photo_path = [userObject objectForKey:#“photo_path”];
[[cell username] setText:[NSString stringWithFormat:#"%# %#", first_name, last_name]];
[[cell lastName] setText:last_name];
[[cell userDescription] setText:userbio];
[[cell areaLabel] setText:[NSString stringWithFormat:#"%#, %#", neighbourhood, city]];
[[cell usermini] sd_setImageWithURL:[NSURL URLWithString:photo_path]];
}
return cell;
}
I did something like this in my app. It's ugly and I'm not recommending you following this way. I did it only because I was kind of lazy about layouts and placing the placeholder in the correct place in the view hierarchy and handle all those hide/show situations. My view controller has a very complex hierarchy of views and the table view was one that has already had all I needed (resize automatically when the status or toolbar is showing).
What I suggest you is to hide the table view when there is an empty search result and substitute it with your placeholder.
Try this it's working:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSInteger numOfSections = 0;
if (arrData.count>0)
{
self.TblView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
numOfSections = 1;
self.TblView.backgroundView = nil;
}
else
{
UILabel *noDataLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.TblView.bounds.size.width, self.TblView.bounds.size.height)];
noDataLabel.text = #"No Results";
noDataLabel.textColor = [UIColor blackColor];
noDataLabel.textAlignment = NSTextAlignmentCenter;
self.TblView.backgroundView = noDataLabel;
self.TblView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
return numOfSections;
}
I have two collectionViews. A collectionViewController and another collectionView in the header. When I scroll down the collectionViewController, the collectionView cells of the the header collectionView disappear. There is also a segControl in the header that changes the collectionViewController cells and this also makes the header collectionView cells disappear. When the controller appears all the cells are present, BUT when i wither scroll of select the segControl the header Collection View cells disappear. The collectionViewController works fine, just the one in the header is messed up.
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if (collectionView == self.collectionView) {
return [self.dataArray count];
}
return [self.groupArray count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
if (collectionView != self.collectionView) {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"socialCell" forIndexPath:indexPath];
PFObject *group = [self.groupArray objectAtIndex:indexPath.row];
UILabel *label = (UILabel *) [cell viewWithTag:55];
label.text = [group objectForKey:#"Title"];
return cell;
}
userPostCell *postCell = (userPostCell *) [collectionView dequeueReusableCellWithReuseIdentifier:#"postCell" forIndexPath:indexPath];
userPictureCell *pictureCell = (userPictureCell *) [collectionView dequeueReusableCellWithReuseIdentifier:#"pictureCell" forIndexPath:indexPath];
userEventCell *eventCell = (userEventCell *) [collectionView dequeueReusableCellWithReuseIdentifier:#"eventCell" forIndexPath:indexPath];
PFObject *temp = [self.dataArray objectAtIndex:indexPath.row];
if (self.dataArray == self.postsArray) {
postCell.postLabel.text = [temp objectForKey:#"stringPost"];
[self changeToCircle:postCell.profileImage];
if ([temp objectForKey:#"Event"] == nil) {
[postCell.noEventNameButton setTitle:[temp objectForKey:#"User_Name"] forState:UIControlStateNormal];
postCell.noEventNameButton.tag = indexPath.row;
postCell.nameButton.hidden = true;
postCell.noEventNameButton.hidden = false;
}
else{
[postCell.nameButton setTitle:[temp objectForKey:#"User_Name"] forState:UIControlStateNormal];
postCell.nameButton.tag = indexPath.row;
postCell.noEventNameButton.hidden = true;
postCell.nameButton.hidden = false;
//[postCell.eventButton addTarget:self action:#selector(eventPage:) forControlEvents:UIControlEventTouchUpInside];
}
[postCell.eventButton setTitle:[temp objectForKey:#"Event"] forState:UIControlStateNormal];
NSString *createdTime = [NSDateFormatter localizedStringFromDate: temp.createdAt dateStyle: NSDateFormatterNoStyle timeStyle: NSDateFormatterShortStyle];
[postCell.timeButton setTitle:createdTime forState:UIControlStateNormal];
PFFile *imageFile = [temp objectForKey:#"profileImage"];
NSData *data = [imageFile getData];
postCell.profileImage.image = [UIImage imageWithData:data];
NSArray *likeArray = [temp objectForKey:#"likes"];
NSString *likeString = [NSString stringWithFormat:#"%lu Likes", (unsigned long)likeArray.count];
if ([likeArray containsObject:[PFUser currentUser].objectId]) {
postCell.likeButton.hidden = true;
}
else{
postCell.likeButton.hidden = false;
}
NSArray *commentArray = [temp objectForKey:#"Comments"];
NSString *commentString = [NSString stringWithFormat:#"%lu Comments", (unsigned long)commentArray.count];
[postCell.likesButton setTitle:likeString forState:UIControlStateNormal];
[postCell.commentsButton setTitle:commentString forState:UIControlStateNormal];
postCell.eventButton.tag = indexPath.row;
postCell.likeButton.tag = indexPath.row;
postCell.commentsButton.tag = indexPath.row;
postCell.likesButton.tag = indexPath.row;
[postCell.likesButton addTarget:self action:#selector(likesPage:) forControlEvents:UIControlEventTouchUpInside];
[postCell.likeButton addTarget:self action:#selector(like:) forControlEvents:UIControlEventTouchUpInside];
[postCell.commentsButton addTarget:self action:#selector(commentsPage:) forControlEvents:UIControlEventTouchUpInside];
[postCell setUserInteractionEnabled:YES];
return postCell;
}
if (self.dataArray == self.personImages) {
UIImage *personImage = [self.dataArray objectAtIndex:indexPath.row];
pictureCell.userImage.image = personImage;
return pictureCell;
}
if (self.dataArray == self.eventsArray) {
[eventCell.userEvent setTitle:[temp objectForKey:#"Title"] forState:UIControlStateNormal];
eventCell.userEvent.tag = indexPath.row;
[eventCell.userEvent addTarget:self action:#selector(eventPage:) forControlEvents:UIControlEventTouchUpInside];
[eventCell.userGroup setTitle:[temp objectForKey:#"Group_Name"] forState:UIControlStateNormal];
eventCell.userGroup.tag = indexPath.row;
[eventCell.userGroup addTarget:self action:#selector(groupPage:) forControlEvents:UIControlEventTouchUpInside];
return eventCell;
}
return postCell;
}
The Seg Method:
- (IBAction)segControl:(id)sender {
UISegmentedControl *segment = (UISegmentedControl *) sender;
if (segment.selectedSegmentIndex == 0) {
self.dataArray = self.postsArray;
[self.collectionView reloadData];
}
if (segment.selectedSegmentIndex == 1) {
self.dataArray = self.personImages;
[self.collectionView reloadData];
}
if (segment.selectedSegmentIndex == 2) {
self.dataArray = self.eventsArray;
[self.collectionView reloadData];
}
}
it's late but this will help for others
i also had similar problem , i just replaced [self.myCollectionView reloadData] with [self.myCollectionView reloadSections:[NSIndexSet indexSetWithIndex:0]]; to refresh the collectionview and it shows all cells, you can try it.
I have the following code that loads an image from a web service, I want to check if the image is loaded and then populate a button with an image (button is already in place)
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FeedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTableViewCellIdentifier forIndexPath:indexPath];
if (!cell) {
cell = [[FeedTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kTableViewCellIdentifier];
}
// Configure the cell...
cell.post_time.font = [UIFont fontWithName:#"ProximaNova-Bold" size:12];
cell.post_price.font = [UIFont fontWithName:#"ProximaNova-Semibold" size:13];
cell.post_address.font = [UIFont fontWithName:#"ProximaNova-Regular" size:13];
cell.post_attributes.font = [UIFont fontWithName:#"ProximaNova-Regular" size:11];
House * house = [Posts objectAtIndex:indexPath.row];
//cell.post_image.clipsToBounds = YES;
//cell.post_image.contentMode = UIViewContentModeScaleAspectFill;
//cell.post_image.contentMode = UIViewContentModeScaleAspectFit;
cell.post_time.text = house.house_ts;
// [cell.post_image setImageWithURL:[NSURL URLWithString:house.house_aws_image_id]];
[cell.post_image setImageWithURL:[NSURL URLWithString:house.house_aws_image_id] placeholderImage:[UIImage imageNamed:#"splash_image_gray"]];
cell.post_attributes.text = [self decodeAttributes:house.house_bed_rms :house.house_bath_rms :house.house_house_siz];
[cell.post_playButton addTarget:self action:#selector(showVideo:) forControlEvents:UIControlEventTouchUpInside];
cell.post_share.tag = indexPath.row;
[cell.post_share addTarget:self action:#selector(shareoptions:) forControlEvents:UIControlEventTouchUpInside];
//[cell.post_playButton setImage:[UIImage imageNamed:#"feed_play_but_pink.png"] forState:UIControlStateHighlighted];
//[cell.post_playButton setBackgroundImage:[UIImage imageNamed:#"heart_btn"] forState:UIControlStateNormal];
[cell.post_playButton setTag:indexPath.row];
[cell.post_playButton setBackgroundImage:[UIImage imageNamed:#"feed_play_but"] forState:UIControlStateNormal];
return cell;
}
Any ideas how to achieve this? Thanks in advance.
Assuming your getting your data form the web service as array, you should parse the array and copy it mutable (or parse it as mutable array directly).
Then you can do this:
id imageObject = [[[self dataArray] objectAtIndex:[indexPath row]] objectForKey:#"imageURL"];
if ([imageObject isKindOfClass:[NSString class]]) {
NSURLConnection *connection = [NSURLConnection ...];
// replace image url in array so that you don't start connections too often.
[[[self dataArray] objectAtIndex:[indexPath class]] setObject:connection forKey:#"imageURL"];
// when connection finishes, replace the connection by the instance of UIImage and reload the corresponding cell
}
else if ([imageObject isKindOfClass:[UIImage class]]) {
[[cell imageView] setImage:imageObject];
}
You can use the JWURLConnection class for easy block programming. If you do so, you can easily use this code (which is from one of my apps and works just fine):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath];
NSMutableDictionary *post = [[self dataSource] objectAtIndex:[indexPath row]];
id memberCloseup = [post objectForKey:#"image"];
if ([memberCloseup isKindOfClass:[NSString class]]) {
JWURLConnection *connection = [JWURLConnection connectionWithGETRequestToURL:[NSURL URLWithString:memberCloseup] delegate:nil startImmediately:NO];
[connection setFinished:^(NSData *data, NSStringEncoding encoding) {
[post setObject:[UIImage imageWithData:data] forKey:#"image"];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}];
[teamMemberMeta setObject:connection forKey:#"so_team_member-image_close"];
[post setObject:connection forKey:#"image"];
[connection start];
}
else if ([memberCloseup isKindOfClass:[UIImage class]]) {
[[cell imageView] setImage:memberCloseup];
}
return cell;
}
EDIT
You would have to move your loading logic to the view controller. Letting the cell loading itself is wrong, because your cells are getting reused, so one cell represents various data objects and / or images. My solution saves a lot of memory and data usage.
Can anyone suggest a tutorial which can achieve following 3 tasks for one ViewController.
1. Search names in tableView.
2. Each cell in tableView has checkBoxes.
3. Retain checked cells [state of `UIButtons`] if the user searches the name.
So far I have achieved first two tasks from this lengthly code
but unable to achieve 3rd point. Any help will be sincerely appreciated. Thanks.
There are many ways to do this. You can't expect tutorials to do exactly what you are doing.
There are many ways of doing this. One of the ways is to store the state of the checked cells in an NSArray and then load the state in cellForRowAtIndexPath data source method.
Solved my own issue with the following code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//static NSString *cellId = #"CheckBoxedCell";
NSString *cellId = [NSString stringWithFormat:#"S%1dR%1d",indexPath.section,indexPath.row];
CheckBoxedCellClass *cell = (CheckBoxedCellClass *)[self.tableViewContact dequeueReusableCellWithIdentifier:cellId];
if(!cell)
{
NSArray *nib;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"CheckBoxedCellClass" owner:self options:nil];
}
else if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"CheckBoxedCellClass_iPad" owner:self options:nil];
}
for (id object in nib)
{
if([object isKindOfClass:[CheckBoxedCellClass class]])
{
cell = (CheckBoxedCellClass *)object;
break;
}
}
cell = [nib objectAtIndex:0];
}
//set fonts
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
[cell.companyLabel setFont:[UIFont italicSystemFontOfSize:10.0]];
}
else
{
[cell.companyLabel setFont:[UIFont italicSystemFontOfSize:14.0]];
}
//handling check box
NSInteger rowNumber = 0;
for(NSInteger i = 0; i < indexPath.section ; i++)
{
rowNumber += [self tableView:self.tableViewContact numberOfRowsInSection:i];
}
rowNumber += indexPath.row;
SaveCheckBoxedView *saveContact;
if(isFiltered == YES)
{
saveContact = [filterdArray objectAtIndex:indexPath.row];
cell.nameLabel.text = saveContact.nameString;
cell.companyLabel.text = saveContact.companyString;
}
else
{
saveContact = [mutableArray objectAtIndex:indexPath.row];
cell.nameLabel.text = [[objectsForCharacters objectForKey:[arrayOfCharacters objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.companyLabel.text = [NSString stringWithFormat:#"%#", [companyArray objectAtIndex:rowNumber]];
}
cell.invIdLabel.text = [NSString stringWithFormat:#"%#", saveContact.invitId];
UIButton *checkBox;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(7, 8, 30, 30)];
}
else
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(15, 13, 30, 30)];
}
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
[checkBox addTarget:self action:#selector(checkBoxClicked:event:) forControlEvents:UIControlEventTouchUpInside];
// handle check box view reset when scrolled
if(isFiltered == YES)
{
NSLog(#"filtered");
BOOL buttonPress = [[boolDictForSearch objectForKey:[filteredArrayOfIds objectAtIndex:indexPath.row]] boolValue];
NSLog(#"button press = %d", buttonPress);
[checkBox setSelected:buttonPress];
if(buttonPress)
{
[checkBox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
}
else
{
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
}
checkBox.tag = indexPath.row;
}
else
{
BOOL buttonPressed = [[boolDict objectForKey:[NSString stringWithFormat:#"%d", rowNumber]] boolValue];
NSLog(#"button pressED = %d", buttonPressed);
NSLog(#"Row number = %d", rowNumber);
[checkBox setSelected:buttonPressed];
if(buttonPressed)
{
[checkBox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
}
else
{
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
}
checkBox.tag = rowNumber;
}
[cell.contentView addSubview:checkBox];
return cell;
}
-(void)checkBoxClicked:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableViewContact];
NSIndexPath *indexPath = [self.tableViewContact indexPathForRowAtPoint: currentTouchPosition];
NSLog(#"value of indexPath.section %d ,indexPath.row %d",indexPath.section,indexPath.row);
UIButton *tappedButton = (UIButton*)sender;
NSLog(#"Tag number = %d", [sender tag]);
if([tappedButton.currentImage isEqual:[UIImage imageNamed:#"checkBox.png"]])
{
[sender setImage:[UIImage imageNamed: #"checkBoxMarked.png"] forState:UIControlStateNormal];
NSUserDefaults *buttonDefault = [NSUserDefaults standardUserDefaults];
[buttonDefault setBool:YES forKey:#"CHECKMARKEDKEY"];
[self.boolDict setObject:[NSNumber numberWithBool:YES] forKey:[NSString stringWithFormat:#"%d", [sender tag]]];
//[self.boolDictForSearch setObject:[NSNumber numberWithBool:YES] forKey:[NSString stringWithFormat:#"%#", saveContact.nameString]];
if(isFiltered == YES)
{
NSString *addId = [filteredArrayOfIds objectAtIndex:indexPath.row];
[self.boolDictForSearch setObject:[NSNumber numberWithBool:YES] forKey:addId];
NSLog(#"filterd id = %#", addId); //get filtered array here
[arrayOfIds addObject:addId];
}
else
{
NSString *finalIntId = [mutableArrayOfIds objectAtIndex:tappedButton.tag];
[self.boolDictForSearch setObject:[NSNumber numberWithBool:YES] forKey:finalIntId];
NSLog(#"Tagged checked button id = %#", finalIntId);
[arrayOfIds addObject:finalIntId];
}
}
else
{
[sender setImage:[UIImage imageNamed:#"checkBox.png"]forState:UIControlStateNormal];
NSLog(#"UnChecked");
[self.boolDict setObject:[NSNumber numberWithBool:NO] forKey:[NSString stringWithFormat:#"%d", [sender tag]]];
//[self.boolDictForSearch setObject:[NSNumber numberWithBool:NO] forKey:[NSString stringWithFormat:#"%#", saveContact.nameString]];
if(isFiltered == YES)
{
[arrayOfIds removeObjectIdenticalTo:[filteredArrayOfIds objectAtIndex:tappedButton.tag]];
[self.boolDictForSearch setObject:[NSNumber numberWithBool:NO] forKey:[filteredArrayOfIds objectAtIndex:tappedButton.tag]];
}
else
{
[arrayOfIds removeObjectIdenticalTo:[mutableArrayOfIds objectAtIndex:tappedButton.tag]];
[self.boolDictForSearch setObject:[NSNumber numberWithBool:NO] forKey:[mutableArrayOfIds objectAtIndex:tappedButton.tag]];
}
}
}
The result of Build and Analyze Showing me this line.
Potential leak of an object allocated on line 923 and stored into 'cell'
This is the code Iam using.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CustomizedCell *cell =(CustomizedCell*) [tableView dequeueReusableCellWithIdentifier:#"CustomizedCell"];
HolidayAppDelegate *delegatObj = (HolidayAppDelegate *)[UIApplication sharedApplication].delegate;
NSLog(#"cellForRowAtIndexPath %d",indexPath.row);
if (cell == nil) {
cell = [[CustomizedCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"CustomizedCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
[cell.mainBtn addTarget:self action:#selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.redBtn addTarget:self action:#selector(Fourthbuttonclick:) forControlEvents:UIControlEventTouchUpInside];
[cell.greenBtn addTarget:self action:#selector(Firstbuttonclick:) forControlEvents:UIControlEventTouchUpInside];
[cell.bluebtn addTarget:self action:#selector(Secondbuttonclick:) forControlEvents:UIControlEventTouchUpInside];
[cell.yellowbtn addTarget:self action:#selector(Thirdbuttonclick:) forControlEvents:UIControlEventTouchUpInside];
[cell.blackbtn addTarget:self action:#selector(Fifthbuttonclick:) forControlEvents:UIControlEventTouchUpInside];
[cell setBackgroundView:[[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"backround#2x.png"]] autorelease]];
}
if(buttonClicks[indexPath.row] == YES){
NSLog(#"button click is yes row is %d",indexPath.row);
cell.redBtn.hidden = NO;
cell.greenBtn.hidden = NO;
cell.bluebtn.hidden = NO;
cell.yellowbtn.hidden=NO;
cell.blackbtn.hidden=NO;
}
else {
cell.redBtn.hidden = YES;
cell.greenBtn.hidden = YES;
cell.bluebtn.hidden = YES;
cell.yellowbtn.hidden=YES;
cell.blackbtn.hidden=YES;
}
if ([[delegatObj.Favoritearray objectAtIndex:indexPath.row] isEqual:#"1"]) {
[cell.mainBtn setBackgroundImage:[UIImage imageNamed:#"starSelected2.png"] forState:UIControlStateNormal];
}
else if ([[delegatObj.Favoritearray objectAtIndex:indexPath.row] isEqual: #"2"]) {
[cell.mainBtn setBackgroundImage:[UIImage imageNamed:#"starSelected4.png"] forState:UIControlStateNormal];
}
else if ([[delegatObj.Favoritearray objectAtIndex:indexPath.row] isEqual: #"3"]) {
[cell.mainBtn setBackgroundImage:[UIImage imageNamed:#"starSelected1.png"] forState:UIControlStateNormal];
}
else if ([[delegatObj.Favoritearray objectAtIndex:indexPath.row] isEqual: #"0"]) {
[cell.mainBtn setBackgroundImage:[UIImage imageNamed:#"starSelected.png"] forState:UIControlStateNormal];
}
else if ([[delegatObj.Favoritearray objectAtIndex:indexPath.row] isEqual: #"5"]) {
[cell.mainBtn setBackgroundImage:[UIImage imageNamed:#"starSelected3.png"] forState:UIControlStateNormal];
}
else {
[cell.mainBtn setBackgroundImage:[UIImage imageNamed:#"starSelected.png"] forState:UIControlStateNormal];
}
cell.mainBtn.buttonIndex = indexPath.row;
cell.redBtn.buttonIndex = indexPath.row;
cell.greenBtn.buttonIndex = indexPath.row;
cell.bluebtn.buttonIndex = indexPath.row;
cell.yellowbtn.buttonIndex = indexPath.row;
cell.blackbtn.buttonIndex = indexPath.row;
cell.cellNameLabel.text=[delegatObj.Holidaynamearray objectAtIndex:indexPath.row];
NSString *myString =[delegatObj.Datearray objectAtIndex:indexPath.row];
if ([myString length]==16) {
NSRange stringRange = {0, MIN([myString length],11)};
stringRange = [myString rangeOfComposedCharacterSequencesForRange:stringRange];
// Now you can create the short string
NSString *shortString = [myString substringWithRange:stringRange];
cell.cellDateLabel.text=shortString;
}
if ([myString length]==15) {
NSRange stringRange = {0, MIN([myString length],10)};
stringRange = [myString rangeOfComposedCharacterSequencesForRange:stringRange];
// Now you can create the short string
NSString *shortString = [myString substringWithRange:stringRange];
cell.cellDateLabel.text=shortString;
}
if ([myString length]==14) {
NSRange stringRange = {0, MIN([myString length],9)};
stringRange = [myString rangeOfComposedCharacterSequencesForRange:stringRange];
// Now you can create the short string
NSString *shortString = [myString substringWithRange:stringRange];
cell.cellDateLabel.text=shortString;
//[shortString release];
}
if ([myString length]==13) {
NSRange stringRange = {0, MIN([myString length],8)};
stringRange = [myString rangeOfComposedCharacterSequencesForRange:stringRange];
// Now you can create the short string
NSString *shortString = [myString substringWithRange:stringRange];
cell.cellDateLabel.text=shortString;
}
if ([myString length]==12) {
NSRange stringRange = {0, MIN([myString length],7)};
stringRange = [myString rangeOfComposedCharacterSequencesForRange:stringRange];
// Now you can create the short string
NSString *shortString = [myString substringWithRange:stringRange];
cell.cellDateLabel.text=shortString;
}
if ([myString length]==11) {
NSRange stringRange = {0, MIN([myString length],6)};
stringRange = [myString rangeOfComposedCharacterSequencesForRange:stringRange];
// Now you can create the short string
NSString *shortString = [myString substringWithRange:stringRange];
cell.cellDateLabel.text=shortString;
}
cell.cellDayLabel.text=[delegatObj.Dayarray objectAtIndex:indexPath.row];
NSString *countynamestrng=[delegatObj.Countryarray objectAtIndex:indexPath.row];
cell.cellcountryLabel.text=countynamestrng;
NSLog(#"%#",countynamestrng);
cell.c1.image=[UIImage imageNamed:[NSString stringWithFormat:#"%#.png", countynamestrng]];
return cell;
}
How and Where to release Customize UITableViewCell?
Thanks
Right after the line:
cell = [[CustomizedCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"CustomizedCell"];
do this:
[cell autorelease];