Custom TableViewCells Not Being Reused - ios

My chat application uses the following cellForRowAtIndexPath to setup the chat dialog history for the user:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
QBChatMessage *message = [[ChatService shared] messagsForDialogId:self.dialog.ID][indexPath.row];
if (message.attachments.count > 0) {
ImageTableViewCell *cell = [[ImageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ImageCellIdentifier message:message];
[cell fillWithStickerMessage:message];
cell.backgroundColor = [UIColor whiteColor];
}
return cell;
}
Here is the init method in my ImageTableViewCell.m file.
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier message:(QBChatMessage *)message {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
NSData *imageData = [FTWCache objectForKey:[NSString stringWithFormat:#"%#", [message.attachments[0] valueForKey:#"ID"]]];
if (imageData) {
UIImage *image = [UIImage imageWithData:imageData];
[self.cellImage setImage:image];
} else {
for(QBChatAttachment *attachment in message.attachments){
// download file by ID
[QBRequest TDownloadFileWithBlobID:[attachment.ID integerValue] successBlock:^(QBResponse *response, NSData *fileData) {
[FTWCache setObject:fileData forKey:[NSString stringWithFormat:#"%#", attachment.ID]];
UIImage *image = [UIImage imageWithData:imageData];
[self.cellImage setImage:image];
} statusBlock:^(QBRequest *request, QBRequestStatus *status) {
// handle progress
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];
}
}
self.nameAndDateLabel = [[UILabel alloc] init];
self.timeLabel = [[UILabel alloc] init];
self.cellImage = [[UIImageView alloc] init];
self.cellImage.opaque = YES;
if ((IS_IPHONE_4) || (IS_IPHONE_5)){
[self.nameAndDateLabel setFrame:CGRectMake(20, 5, 300, 20)];
} else if (IS_IPHONE_6) {
[self.nameAndDateLabel setFrame:CGRectMake(20, 5, 355, 20)];
} else if (IS_IPHONE_6_PLUS) {
[self.nameAndDateLabel setFrame:CGRectMake(20, 5, 394, 20)];
}
[self.nameAndDateLabel setFont:[UIFont boldSystemFontOfSize:15]];
[self.nameAndDateLabel setTextColor:[UIColor lightGrayColor]];
[self.contentView addSubview:self.nameAndDateLabel];
self.backgroundImageView = [[UIImageView alloc] init];
[self.backgroundImageView setFrame:CGRectZero];
[self.backgroundImageView addSubview:self.cellImage];
[self.contentView addSubview:self.backgroundImageView];
}
return self;
}
The problem is that when scrolling through the table view, the cells are constantly initialized in initWithStyle in the ImageViewCell.m file. Shouldn't that only happen if the cell hasn't been created already? What am I doing wrong?

You're missing a call in cellForRowAtIndexPath to
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
forIndexPath:(NSIndexPath *)indexPath
or
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
depending on whether you registered your UITableViewCell nib or class.
So for example in cellForRowAtIndexPath you would do:
ImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ImageCellIdentifier];
if (cell == nil) {
cell = [[ImageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ImageCellIdentifier message:message];
}

Related

The bubble image arrow is always on the right direction. How to change green bubbles' arrow direction to left?

In my JSQMessagesViewController, when I load text message bubbles, the arrow direction is always right side.
How to change arrow direction to left for green bubbles??
My Code:
#interface AckChatViewController (){
JSQMessagesBubbleImage *outgoingBubbleImageView;
JSQMessagesBubbleImage *incomingBubbleImageView;
JSQMessagesAvatarImage *currentUserAvatar, *friendAvatar;
NSMutableArray *messages;
}
#end
#implementation AckChatViewController
pragma mark - life cycle methods
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
self.navigationController.navigationBar.topItem.title = #"";
//initial things for JSQMessageViewController
[self setupBubbles];
messages = [NSMutableArray new];
AllUserDetailsModel *temp = [[AllUserDetailsModel alloc] initWithDictionary:[Neo_Constants getSavedDataFromUserDafaults:USER_INFO_DICTIONARY]];
self.senderId = [NSString stringWithFormat:#"%#",temp.user_id];
self.senderDisplayName = #"";
self.automaticallyScrollsToMostRecentMessage = YES;
//remove attachment button
self.inputToolbar.contentView.leftBarButtonItem = nil;
currentUserAvatar = [JSQMessagesAvatarImage avatarImageWithPlaceholder: [self cropAvatarImages:[UIImage imageNamed:[self defaultImageForGender:temp.userDetails.gender]]]];
friendAvatar = [JSQMessagesAvatarImage avatarImageWithPlaceholder: [self cropAvatarImages:[UIImage imageNamed:[self defaultImageForGender:self.friendUserDetails.userDetails.gender]]]];
NSString *imageUrlString = temp.userDetails.profile_pic;
[self avatarImagesForUrlString:imageUrlString andOnCompletion:^(UIImage *image) {
if(image){
currentUserAvatar.avatarImage = image;
}
}];
[self avatarImagesForUrlString:self.friendUserDetails.userDetails.profile_pic andOnCompletion:^(UIImage *image) {
if(image){
friendAvatar.avatarImage = image;
}
}];
//set profile pic and name on navigation bar
[self setNavigationBarTitleView];
[self loadPreviousChatWithPageCount:0];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
pragma mark - JSQ Setups
-(void)setupBubbles{
JSQMessagesBubbleImageFactory *bubbleImageFactory = [JSQMessagesBubbleImageFactory new];
outgoingBubbleImageView = [bubbleImageFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleBlueColor]];
incomingBubbleImageView = [bubbleImageFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
}
pragma mark Collection view JSQ
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return messages.count;
}
-(id<JSQMessageData>)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath{
return messages[indexPath.item];
}
-(id<JSQMessageBubbleImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath{
JSQMessage *message = messages[indexPath.item];
if([message.senderId isEqualToString:self.senderId]){
return outgoingBubbleImageView;
}else{
return incomingBubbleImageView;
}
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
JSQMessage *message = messages[indexPath.item];
if([message.senderId isEqualToString:self.senderId]){
[cell.textView setTextColor:[UIColor whiteColor]];
}else{
[cell.textView setTextColor:[UIColor blackColor]];
}
return cell;
}
-(id<JSQMessageAvatarImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath{
JSQMessage *message = messages[indexPath.item];
if([message.senderId isEqualToString:self.senderId]){
return currentUserAvatar;
}else{
return friendAvatar;
}
}
-(void)collectionView:(JSQMessagesCollectionView *)collectionView header:(JSQMessagesLoadEarlierHeaderView *)headerView didTapLoadEarlierMessagesButton:(UIButton *)sender{
}
//time stamp
-(NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath{
return nil;
}
-(CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath{
return 0;
}
#pragma mark - private functions
-(NSString *)defaultImageForGender:(NSString *)gender{
if([gender isEqualToString:#"M"] || [gender isEqualToString:#""]){
return #"no_image_male";
}else{
return #"no_image_female";
}
}
-(void)setNavigationBarTitleView{
UIView *whole = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width - 100, 100)];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(5, 20, 50, 50)];
[imageView.layer setCornerRadius:25.0f];
[imageView setClipsToBounds:YES];
[imageView setContentMode:UIViewContentModeScaleAspectFill];
if([self.friendUserDetails.userDetails.profile_pic isEqualToString:#""] || [self.friendUserDetails.userDetails.profile_pic isEqual:[NSNull null]]){
if([self.friendUserDetails.userDetails.gender isEqualToString:#"M"]){
[imageView setImage:[UIImage imageNamed:#"no_image_male"]];
}else{
[imageView setImage:[UIImage imageNamed:#"no_image_female"]];
}
}else{
[imageView sd_setImageWithURL:[NSURL URLWithString:self.friendUserDetails.userDetails.profile_pic]];
}
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(60, 20, [UIScreen mainScreen].bounds.size.width, 50)];
[nameLabel setText:self.friendUserDetails.userDetails.fname];
[whole addSubview:nameLabel];
[whole addSubview:imageView];
self.navigationItem.titleView = whole;
}
#pragma mark - Avtar images area
-(void)avatarImagesForUrlString:(NSString *)urlString andOnCompletion:(void(^)(UIImage *image))completion{
if([urlString isEqualToString:#""] || [urlString isEqual:[NSNull null]]){
completion(nil);
}else{
[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:urlString] options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
completion ([self cropAvatarImages:image]);
}];
}
}
-(UIImage *)cropAvatarImages:(UIImage *)image{
if(image){
return [JSQMessagesAvatarImageFactory circularAvatarImage:image withDiameter:48];
}else{
if([self.friendUserDetails.userDetails.gender isEqualToString:#"M"]){
return [UIImage imageNamed:#"no_image_male"];
}else{
return [UIImage imageNamed:#"no_image_female"];
}
}
}
#pragma mark - API calls
-(void)loadPreviousChatWithPageCount:(int)count{
[API fetchChatListOfUserWithParams:paramsDict andOnCompletion:^(NSDictionary *result, NSError *error){
if (!error) {
if ([[result objectForKey:#"status"] intValue]==1) {
NSArray *conversation_data = [result objectForKey:#"conversation_data"];
[messages removeAllObjects];
[conversation_data enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop){
JSQMessage *jsqMsg = [[JSQMessage alloc] initWithSenderId:obj[#"sender_id"] senderDisplayName:#"" date:obj[#"sent_date"] text:obj[#"message_content"]];
[messages insertObject:jsqMsg atIndex:idx];
}];
[self.collectionView reloadData];
}else{
[Neo_Constants showAlert:#"Error" Message:[result objectForKey:#"message"]];
}
}else{
[Neo_Constants showAlert:#"Error" Message:[error localizedDescription]];
}
}];
}
-(void)didPressSendButton:(UIButton *)button withMessageText:(NSString *)text senderId:(NSString *)senderId senderDisplayName:(NSString *)senderDisplayName date:(NSDate *)date{
// [JSQSystemSoundPlayer jsq_playMessageSentSound];
[API sendMessageFromUserWithParams:paramsDict andOnCompletion:^(NSDictionary *result, NSError *error){
if (!error) {
if ([[result objectForKey:#"status"] intValue]==1) {
[self loadPreviousChatWithPageCount:0];
[self.inputToolbar.contentView.textView setText:#""];
}else{
[Neo_Constants showAlert:#"Error" Message:[result objectForKey:#"message"]];
}
}else{
[Neo_Constants showAlert:#"Error" Message:[error localizedDescription]];
}
}];
}
#end
problem is in this code you initialise outgoing and incomming with the same method which is
outgoingMessagesBubbleImageWithColor
try incoming with
incomingMessagesBubbleImageWithColor
and outgoing with this
outgoingMessagesBubbleImageWithColor
this correct one
-(void)setupBubbles{
JSQMessagesBubbleImageFactory *bubbleImageFactory = [JSQMessagesBubbleImageFactory new];
outgoingBubbleImageView = [bubbleImageFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleBlueColor]];
incomingBubbleImageView = [bubbleImageFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
}

how to show messages and image in uitableviewcell in iOS

I am working on chat application. Actually i have 3 arrays. First array stores user name and second array stores chat message and third array stores images. I am picking image from photo gallery.
When user sends any message to the chat wall I display message in bubble.
So I'm writing some conditions like the below:
if arr2 value is not null then displaying chat message
if arr3 value is not null displaying image in chat bubble
if arr2 value is null then i want to hide lbldesc and show only imv gallery image
if arr3 value is null then hide imv gallery image and enable lblDesc
But i got exception like this:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** NSAllocateMemoryPages(4294967295) failed'`
Here is my code:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.selectionStyle=UITableViewCellSelectionStyleNone;
if (itemsDataArr.count>0) {
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(35, 3, 250, 80)];
imgView.image = [UIImage imageNamed:#"speech-bubble-2-hi.png"];
imgView.layer.borderColor = [UIColor clearColor].CGColor;
imgView.tag = 5;
[cell.contentView addSubview:imgView];
NSArray *arr1=[[NSArray alloc]init];
arr1=[itemsUserNameArr objectAtIndex:indexPath.row];
NSString *strval=[arr1 objectAtIndex:0];
lblTitle=[[UILabel alloc]initWithFrame:CGRectMake(50, 5, 150, 20)];
lblTitle.highlightedTextColor=[UIColor whiteColor];
[cell.contentView addSubview:lblTitle];
[lblTitle setFont:[UIFont boldSystemFontOfSize:14]];
lblTitle.text=strval;
[imgView addSubview:lblTitle];
NSArray *arr2=[[NSArray alloc]init];
arr2=[itemsDataArr objectAtIndex:indexPath.row];
NSArray *arr3=[[NSArray alloc]init];
arr3=[itemImgArray objectAtIndex:indexPath.row];
if(![arr2 isEqual:#""])
{
NSString *strmsg=[arr2 objectAtIndex:0];
lblDesc=[[UILabel alloc]initWithFrame:CGRectMake(50, 22, 300, 20)];
lblDesc.highlightedTextColor=[UIColor whiteColor];
lblDesc.font=[UIFont systemFontOfSize:12.0];
[cell.contentView addSubview:lblDesc];
[lblDesc setHidden:NO];
lblDesc.text=strmsg;
[imgView addSubview:lblDesc];
// imv.hidden=YES;
// [imv setHidden:true];
}
arr3=[itemImgArray objectAtIndex:indexPath.row];
if(![arr3 isEqual:nil])
{
NSString *strImg=[arr3 objectAtIndex:0];
NSData *data = [[NSData alloc] initWithData:[NSData dataFromBase64String:strImg]];
//Now data is decoded. You can convert them to UIImage
imv = [[UIImageView alloc]initWithFrame:CGRectMake(93,12, 50, 50)];
imv.image=[UIImage imageWithData:data];
[imgView addSubview:imv];
[lblDesc setHidden:YES];
// lblDesc.hidden=YES;
}
}
return cell;
}
I've used PTSMessagingCell from here:
I've used messages array for texts/images. This is a ruf sample that may help you.
#import "ViewController.h"
#import "PTSMessagingCell.h"
#interface ViewController ()
{
NSMutableArray *messages;
UITextView *sendMsg;
UITableView *chatTable;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
messages = [[NSMutableArray alloc] initWithObjects:#"Hello",[UIImage imageNamed:#"download.jpeg"],#"Check This Out", nil];
chatTable = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height-100)];
chatTable.delegate = self;
chatTable.dataSource = self;
chatTable.separatorColor = [UIColor clearColor];
[self.view addSubview:chatTable];
chatTable.backgroundColor = [UIColor clearColor];
sendMsg = [[UITextView alloc]initWithFrame:CGRectMake(0, chatTable.frame.size.height, self.view.frame.size.width-100, 100)];
sendMsg.textColor = [UIColor blackColor];
sendMsg.delegate = self;
sendMsg.backgroundColor = [UIColor whiteColor];
sendMsg.layer.cornerRadius = 3.0f;
[self.view addSubview:sendMsg];
UIButton *sendMsgbtn = [[UIButton alloc]initWithFrame:CGRectMake(sendMsg.frame.size.width, chatTable.frame.size.height, 100, 100)];
[sendMsgbtn setTitle:#"SEND" forState:UIControlStateNormal];
sendMsgbtn.backgroundColor = [UIColor redColor];
[sendMsgbtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[sendMsgbtn addTarget:self action:#selector(sendClicked) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sendMsgbtn];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapReceived:)];
[tapGestureRecognizer setDelegate:self];
[chatTable addGestureRecognizer:tapGestureRecognizer];
}
-(void)sendClicked{
[sendMsg resignFirstResponder];
[chatTable reloadData];
}
#pragma mark - TableView Delegate and DataSource Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
/*This method sets up the table-view.*/
static NSString* cellIdentifier = #"messagingCell";
PTSMessagingCell * cell = (PTSMessagingCell*) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[PTSMessagingCell alloc] initMessagingCellWithReuseIdentifier:cellIdentifier];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[messages objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]]) {
return [(UIImage *)[messages objectAtIndex:indexPath.row] size].height;
}
else{
const char *jsonString = [[NSString stringWithFormat:#"%#",[messages objectAtIndex:indexPath.row]] UTF8String];
NSData *jsonData = [NSData dataWithBytes:jsonString length:strlen(jsonString)];
NSString *goodMsg = [[NSString alloc] initWithData:jsonData encoding:NSNonLossyASCIIStringEncoding];
CGSize messageSize = [PTSMessagingCell messageSize:goodMsg];
NSLog(#"%f",messageSize.height + 2*[PTSMessagingCell textMarginVertical] + 40.0f);
return messageSize.height + 2*[PTSMessagingCell textMarginVertical] + 40.0f;
}
}
-(void)configureCell:(id)cell atIndexPath:(NSIndexPath *)indexPath {
if (messages.count>0) {
PTSMessagingCell* ccell = (PTSMessagingCell*)cell;
if ([[messages objectAtIndex:indexPath.row] isKindOfClass:[UIImage class]]) {
ccell.sent = YES;
ccell.avatarImageView.image = [UIImage imageNamed:[messages objectAtIndex:indexPath.row]];
ccell.messageLabel.text = #"";
}
else{
ccell.sent = YES;
const char *jsonString = [[NSString stringWithFormat:#"%#",[messages objectAtIndex:indexPath.row]] UTF8String];
NSData *jsonData = [NSData dataWithBytes:jsonString length:strlen(jsonString)];
NSString *goodMsg = [[NSString alloc] initWithData:jsonData encoding:NSNonLossyASCIIStringEncoding];
ccell.messageLabel.text = [messages objectAtIndex:indexPath.row];
}
ccell.timeLabel.text = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterFullStyle];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapReceived:)];
[tapGestureRecognizer setDelegate:self];
[ccell addGestureRecognizer:tapGestureRecognizer];
}
}
-(void)tapReceived:(UITapGestureRecognizer *)tapGestureRecognizer
{
// do something, like dismiss your view controller, picker, etc., etc.
[sendMsg resignFirstResponder];
}
Hope this helps.
Create a custom cell and load images in background thread will give better UI performance

How can I tag a button on a UITableView section according to its headerLabel?

I want every delete button to be tagged with its associated section's headerLabel.text.
This way, when pressing the delete button runs the deleteButtonPressed method, the deleteFromMatchCenter Parse function will use the section's headerLabel.text value as the parameter. I've tried to do it as below, but this doesn't seem to be recognizing the header title properly.
How can I properly associate each delete button with its respective sections header title, and send that over as the parameter?
MatchCenterViewController.m:
#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>
#interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UITableView *matchCenter;
#end
#implementation MatchCenterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewCellStyleSubtitle];
self.matchCenter.frame = CGRectMake(0,50,320,self.view.frame.size.height-100);
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
_matchCenterArray = [[NSArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
self.matchCenterArray = [[NSArray alloc] init];
[PFCloud callFunctionInBackground:#"MatchCenter"
withParameters:#{
#"test": #"Hi",
}
block:^(NSArray *result, NSError *error) {
if (!error) {
_matchCenterArray = result;
[_matchCenter reloadData];
NSLog(#"Result: '%#'", result);
}
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return _matchCenterArray.count;
}
//the part where i setup sections and the deleting of said sections
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 21.0f;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 21)];
headerView.backgroundColor = [UIColor lightGrayColor];
_searchTerm = [[[[_matchCenterArray objectAtIndex:section] objectForKey:#"Top 3"] objectAtIndex:3]objectForKey:#"Search Term"];
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 0, 250, 21)];
headerLabel.text = [NSString stringWithFormat:#"%#", _searchTerm];
headerLabel.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize]];
headerLabel.textColor = [UIColor whiteColor];
headerLabel.backgroundColor = [UIColor lightGrayColor];
[headerView addSubview:headerLabel];
UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
deleteButton.tag = section;
deleteButton.frame = CGRectMake(300, 2, 17, 17);
[deleteButton setImage:[UIImage imageNamed:#"xbutton.png"] forState:UIControlStateNormal];
[deleteButton addTarget:self action:#selector(deleteButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[headerView addSubview:deleteButton];
return headerView;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Initialize cell
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
// if no cell could be dequeued create a new one
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// No cell seperators = clean design
tableView.separatorColor = [UIColor clearColor];
// title of the item
cell.textLabel.text = _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Title"];
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
// price of the item
cell.detailTextLabel.text = [NSString stringWithFormat:#"$%#", _matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Price"]];
cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];
// image of the item
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:_matchCenterArray[indexPath.section][#"Top 3"][indexPath.row][#"Image URL"]]];
[[cell imageView] setImage:[UIImage imageWithData:imageData]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 65;
}
- (void)deleteButtonPressed:(id)sender
{
// Define the sections title
NSString *sectionName = [self titleForHeaderInSection:indexPath.section];
// Run delete function with respective section header as parameter
[PFCloud callFunctionInBackground:#"deleteFromMatchCenter"
withParameters:
#{#"searchTerm": sectionName,}
block:^(NSDictionary *result, NSError *error) {
if (!error) {
NSLog(#"Result: '%#'", result);
[_matchCenter reloadData];
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
You haven't linked your titleForHeaderInSection: method, but you're trying to pass indexPath.section when you don't have access to your indexPath.
Try this
UIButton *deleteButton = (UIButton *)sender;
NSString *sectionName = [self titleForHeaderInSection:deleteButton.tag];
or
NSString *sectionName = _searchTerm = [[[[_matchCenterArray objectAtIndex:deleteButton.tag] objectForKey:#"Top 3"] objectAtIndex:3]objectForKey:#"Search Term"];

UIImageView does not appear in custom UITableViewCell that is created dynamically

I am trying to integrate MSSlidingPanelController And I faced with problem. I want to have custom UITableViewCell that will contain image and text label.
I have TableViewItem inherited from UITableViewCell:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
// Initialization code
self.textLabel.font = [UIFont fontWithName:FONT_OPENSANS_BOLD size:15];
[self.imageView addSubview:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"corners"]]];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.frame = CGRectMake(45.0f, 30.0f, 16.0f, 16.0f);
self.textLabel.frame = CGRectMake(70.0f, 40, 240.0f, 20);
}
+ (TableViewItem *) tableViewItemWithUncheckableName:(NSString *)name
withLeftsideImageFromUrl:(NSString *)url
{
TableViewItem *item;
NSParameterAssert(name);
item = [[TableViewItem alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:g_LMVCCellIdentifier];
[[item textLabel] setText:name];
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];
if ( data != nil )
{
dispatch_async(dispatch_get_main_queue(), ^{
// WARNING: is the cell still using the same data by this point??
[[item imageView] setImage:[UIImage imageWithData: data]];
});
}
});
return (item);
}
Here how I use it:
- (TableViewSection *) fillingSectionUserInfo
{
TableViewItem *userInfoItem;
TableViewSection *section;
UserLogic * userLogic = [UserLogic instance];
NSString * userName = [NSString stringWithFormat:#"%# %#", [[userLogic currentUser] stringForKey:#"firstName"], [[userLogic currentUser]stringForKey:#"lastName"]];
userInfoItem = [TableViewItem tableViewItemWithUncheckableName:userName
withLeftsideImageFromUrl:[[userLogic currentUser] stringForKey:#"photo" ]];
[userInfoItem setActionWhenSelected:^(void){
}];
section = [TableViewSection tableViewSectionWitName:nil
selectionRule:SelectionRuleNone
andItems:userInfoItem, nil];
return section;
}
For each item I make setNeedsLayout in tableViewSectionWitName:selectionRule:andItems:

Cell Row Height based on JSON parsed image

I'm parsing image's from a JSON-file on my server. Right now I'm setting the heightForRowAtIndexPath to return 389. But some of the images get stretched now. I need the cell to adjust it's size based on the image height. Right now, my code looks like this:
#implementation Pictures
#synthesize tableView = _tableView, activityIndicatorView = _activityIndicatorView;
#synthesize btnFaceBook, btnTwitter, btnTwitter2;
#synthesize strURLToLoad;
#synthesize movies;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl setTintColor:[UIColor greenColor]];
[refreshControl addTarget:self action:#selector(refresh:) forControlEvents:UIControlEventValueChanged];
[self.tableView addSubview:refreshControl];
strURLToLoad = [[NSMutableString alloc] init];
[btnFaceBook setTitle:#"link-to-json.com/json.php" forState:UIControlStateDisabled];
[btnTwitter setTitle:#"link1-to-json.com/json.php" forState:UIControlStateDisabled];
[btnTwitter2 setTitle:#"link2-to-json.com/json.php" forState:UIControlStateDisabled];
[btnFaceBook setBackgroundImage:[UIImage imageNamed:#"tab_selected.png"] forState:UIControlStateNormal];
[btnFaceBook setBackgroundImage:[UIImage imageNamed:#"tab_unselected.png"] forState:UIControlStateSelected];
[btnTwitter setBackgroundImage:[UIImage imageNamed:#"tab_selected.png"] forState:UIControlStateNormal];
[btnTwitter setBackgroundImage:[UIImage imageNamed:#"tab_unselected.png"] forState:UIControlStateSelected];
[btnTwitter2 setBackgroundImage:[UIImage imageNamed:#"tab_selected.png"] forState:UIControlStateNormal];
[btnTwitter2 setBackgroundImage:[UIImage imageNamed:#"tab_unselected.png"] forState:UIControlStateSelected];
[self.navigationController setNavigationBarHidden:YES];
self.tableView.separatorColor = [UIColor clearColor];
// Setting Up Activity Indicator View
self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
self.activityIndicatorView.color = [UIColor greenColor];
self.activityIndicatorView.hidesWhenStopped = YES;
self.activityIndicatorView.center = self.view.center;
[self.view addSubview:self.activityIndicatorView];
[self.activityIndicatorView startAnimating];
self.tableView.separatorColor = [UIColor clearColor];
// Initializing Data Source
movies = [[NSMutableArray alloc] init];
[self btnFromTabBarClicked:btnFaceBook];
}
- (void)loadJSONFromCurrentURL
{
[self.activityIndicatorView startAnimating];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:strURLToLoad]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
[movies setArray:JSON];
[self.activityIndicatorView stopAnimating];
[self.tableView reloadData];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
- (IBAction)btnFromTabBarClicked:(UIButton *)sender
{
//Unselect all 3 buttons
btnFaceBook.selected = btnTwitter.selected = btnTwitter2.selected = NO;
//Select the button that was clicked
sender.selected = YES;
//Set the string of an NSMutableString property called strURLToLoad with the URL
//The URL is pre stored in the text of the UIButton in the Disabled text.
[strURLToLoad setString:[sender titleForState:UIControlStateDisabled]];
//Load the URL
[self loadJSONFromCurrentURL];
}
- (IBAction)showButtonMenu {
[self.frostedViewController presentMenuViewController];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (self.movies && self.movies.count) {
return self.movies.count;
} else {
return 0;
}
}
//here I want the cell to adjust it's size based on the image height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 389;
}
- (NSString *)getTextKey
{
return btnTwitter.selected?#"title":#"title";
}
- (NSString *)getPostedKey
{
return btnTwitter2.selected?#"uploaded":#"published";
}
- (NSString *)getTwitterName
{
return btnTwitter.selected?#"celebtag":#"celebname";
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 0) {
static NSString *Identifier1 = #"TableHeaderView";
TableHeaderView *cell = [tableView dequeueReusableCellWithIdentifier:Identifier1];
if (cell == nil) {
NSArray *nib= [[NSBundle mainBundle] loadNibNamed:#"TableHeaderView" owner:self options:nil];
cell = (TableHeaderView *)[nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];
return cell;
}
} else {
static NSString *simpleTableIdentifier = #"PicturesObject";
PicturesObject *cell = (PicturesObject *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"PicturesObject" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
NSString *strText = [movie objectForKey:[self getTextKey]];
NSURL *url = [[NSURL alloc] initWithString:[movie objectForKey:#"link"]];
[cell.pic setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeholder"]];
cell.published.text = [movie objectForKey:[self getPostedKey]];
cell.title.text = [movie objectForKey:#"title"];
cell.twitterName.text = [movie objectForKey:[self getTwitterName]];
return cell;
} return 0;
}
#end
At first you need some variable to save image height - array or dictionary, then when you get the image save the height and call [tableView reloadRowAtIndexPath:indexPath]
and in
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
return proper height saved before

Resources