UIImageView does not appear in custom UITableViewCell that is created dynamically - ios

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:

Related

Custom TableViewCells Not Being Reused

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];
}

UITableView image loading with json is not loading properly

I am using this to display some labels and images by JSON parsing in to tableView but images are not coming at the first launch when scrolling the tableview images are coming and dancing i mean not coming in order format help me with this
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
self.customCellClass = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (self.customCellClass == nil)
{
self.customCellClass = [[CellCustom alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
self.customCellClass.nameLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"name"]; // label
self.customCellClass.cityLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"region"]; // label
NSString * stripped = [[[arrayData objectAtIndex:indexPath.row] objectForKey:#"summary"] stripHtml]; //label
self.customCellClass.detailLabel.text = stripped;
self.customCellClass.mainImage.image = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]];
UIImage *image = [UIImage imageWithData:data0];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
self.customCellClass.mainImage.image = image;
});
});
return self.customCellClass;
}
Replace below code in UITableView's cellForRowAtIndexPath method :
//Check if cell has image or not
if(!self.customCellClass.mainImage.image)
{
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(q, ^{
NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]];
UIImage *image = [UIImage imageWithData:data0];
//Get main queue
dispatch_async(dispatch_get_main_queue(), ^{
/* This is the main thread again, where we set the tableView's image to be what we just fetched. */
self.customCellClass.mainImage.image = image;
});
});
}
Good solution is if you are using AFNetworking then use UIImageView+AFNetworking category
NSURL *imageURL = [NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]
[self.customCellClass.mainImage setImageWithURL:imageURL placeholderImage:nil];
You are assigning image=nil every time when cell is loading and downloading the same image.
You can user following class to do this seamlessly.
AsyncImageView.h
#import <UIKit/UIKit.h>
#interface AsyncImageView : UIView {
NSURLConnection *connection;
NSMutableData *data;
NSString *urlString; // key for image cache dictionary
}
-(void)loadImageFromURL:(NSURL*)url;
-(void)loadBackgroundImage:(UIImage *)image;
-(UIImage*)loadImageFromURLForGetIamge:(NSURL*)url;
-(BOOL)getCachedImageWithUrl:(NSString*)url;
#end
and AsyncImageView.m
#import "AsyncImageView.h"
#import "ImageCacheObject.h"
#import "ImageCache.h"
//
// Key's are URL strings.
// Value's are ImageCacheObject's
//
static ImageCache *imageCache = nil;
#define SPINNY_TAG 5555
#implementation AsyncImageView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
}
- (void)dealloc {
[connection cancel];
}
-(void)loadBackgroundImage:(UIImage *)image
{
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.layer.masksToBounds=YES;
//imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout];
[self setNeedsLayout];
imageView=nil;
}
-(void)loadImageFromURL:(NSURL*)url
{
if (connection != nil) {
[connection cancel];
connection = nil;
}
if (data != nil) {
data = nil;
}
if (imageCache == nil) // lazily create image cache
imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024]; // 2 MB Image cache
// NSLog(#"Value of the url here = %#",url);
urlString = [[url absoluteString] copy];
UIImage *cachedImage = [imageCache imageForKey:urlString];
if (cachedImage != nil)
{
if ([[self subviews] count] > 0)
{
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:cachedImage];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.layer.masksToBounds=YES;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
[self setNeedsLayout];
imageView=nil;
return;
}
UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinny.tag = SPINNY_TAG;
spinny.frame=CGRectMake(self.frame.size.width/2-10, self.frame.size.height/2-10, 20, 20);
spinny.center = self.center;
[spinny startAnimating];
[self addSubview:spinny];
[self bringSubviewToFront:spinny];
spinny=nil;
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(BOOL)getCachedImageWithUrl:(NSString*)url
{
BOOL isIamgeCached=NO;
if (imageCache == nil)
imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024]; // 2 MB Image cache
UIImage *cachedImage = [imageCache imageForKey:url];
if (cachedImage != nil)
{
isIamgeCached=YES;
}
return isIamgeCached;
}
-(UIImage*)loadImageFromURLForGetIamge:(NSURL*)url
{
if (connection != nil)
{
[connection cancel];
connection = nil;
}
if (data != nil)
{
data = nil;
}
if (imageCache == nil) // lazily create image cache
imageCache = [[ImageCache alloc] initWithMaxSize:2*1024*1024]; // 2 MB Image cache
// NSLog(#"Value of the url here = %#",url);
urlString = [[url absoluteString] copy];
UIImage *cachedImage = [imageCache imageForKey:urlString];
if (cachedImage != nil)
{
if ([[self subviews] count] > 0)
{
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:cachedImage];
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
[self setNeedsLayout];
imageView=nil;
return cachedImage;
}
UIActivityIndicatorView *spinny = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinny.tag = SPINNY_TAG;
spinny.frame=CGRectMake(self.frame.size.width/2-10, self.frame.size.height/2-10, 20, 20);
//spinny.center = self.center;
[spinny startAnimating];
[self addSubview:spinny];
[self bringSubviewToFront:spinny];
spinny=nil;
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:20.0];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
return cachedImage;
}
- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)incrementalData {
if (data==nil)
{
data = [[NSMutableData alloc] initWithCapacity:2048];
}
[data appendData:incrementalData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
{
connection = nil;
UIView *spinny = [self viewWithTag:SPINNY_TAG];
[spinny removeFromSuperview];
if ([[self subviews] count] > 0)
{
[[[self subviews] objectAtIndex:0] removeFromSuperview];
}
UIImage *image = [UIImage imageWithData:data];
[imageCache insertImage:image withSize:[data length] forKey:urlString];
UIImageView *imageView = [[UIImageView alloc]
initWithImage:image];
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.autoresizingMask =
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
[imageView setNeedsLayout]; // is this necessary if superview gets setNeedsLayout?
[self setNeedsLayout];
imageView=nil;
data = nil;
}
#end
You use dispatch_async to load image from remote, that means the images to be displayed in tableview cells are loaded asynchronously. And you use a instance variable to record current cell, which cause the problem you met.
After a image being loaded finished (may take few minutes), it want to be displayed in a cell (written in this code),
dispatch_sync(dispatch_get_main_queue(), ^(void) {
self.customCellClass.mainImage.image = image;
});
only to find that the self.customCellClass points to a wrong cell (the - (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath was called several times during the image being loaded, and each calling changes the pointing of self.customCellClass to other cell).
So, the order of images is wrong.
Try this:
Use a locality variable to keep the cell get from dequeueReusableCellWithIdentifier. Like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
CellCustom *customCellClass = (CellCustom *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (customCellClass == nil)
{
customCellClass = [[CellCustom alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
customCellClass.nameLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"name"]; // label
customCellClass.cityLabel.text = [[arrayData objectAtIndex:indexPath.row] objectForKey:#"region"]; // label
NSString * stripped = [[[arrayData objectAtIndex:indexPath.row] objectForKey:#"summary"] stripHtml]; //label
customCellClass.detailLabel.text = stripped;
customCellClass.mainImage.image = nil;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
NSData *data0 = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[arrayData objectAtIndex:indexPath.row]objectForKey:#"images"]objectForKey:#"logo"]]];
UIImage *image = [UIImage imageWithData:data0];
dispatch_sync(dispatch_get_main_queue(), ^(void) {
customCellClass.mainImage.image = image;
});
});
return customCellClass;
}
Besides, take a look at the difference between - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier and - (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath.

UIActivityIndicatorView Not Appearing

I am trying to show a UIActivityIndicatorView while my table view is loading data and have it disappear once loading is finished. The loading indicator never appears. What am I doing wrong?
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define storeURL [NSURL URLWithString: #"https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=25&playlistId=PL9DC706DCCCE00188&key=AIzaSyBS4do208_KPGHAhszfVkHadSvtfSgr7Mo"]
#import "BBYoutubeVideosTableViewController.h"
#import "Reachability.h"
#import "TSMessage.h"
#import "TSMessageView.h"
#import "YoutubeCell.h"
#import "KFBYoutubeVideoView.h"
#import "KFBAppDelegate.h"
#interface BBYoutubeVideosTableViewController ()
{
UIActivityIndicatorView *loadingIndicator;
}
#end
#implementation BBYoutubeVideosTableViewController
#synthesize title, videoID, thumbURL, descriptionString, url, titleArray, videoIDArray, thumbArray, descriptionArray;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStylePlain target:nil action:nil];
UIImageView *backgroundImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"plain_app-background.png"]];
CGFloat width = [[UIScreen mainScreen]bounds].size.width;
CGFloat height = [[UIScreen mainScreen]bounds].size.height;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
loadingIndicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(width / 2, height / 2, 37, 37)];
loadingIndicator.center = CGPointMake(width / 2, height / 2 - 37);
}
else
{
loadingIndicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(142, 365, 37, 37)];
}
loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
loadingIndicator.hidesWhenStopped = YES;
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if(networkStatus == NotReachable)
{
[TSMessage showNotificationWithTitle:#"Network Error" subtitle:#"No active network connection!" type:TSMessageNotificationTypeError];
[loadingIndicator stopAnimating];
}
else {
[self.tableView addSubview:loadingIndicator];
[loadingIndicator startAnimating];
}
self.title = #"Bluegrass & Backroads";
self.tableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStyleGrouped];
self.tableView.backgroundView = backgroundImage;
url = [NSURL URLWithString:#"https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=25&playlistId=PL9DC706DCCCE00188&key=AIzaSyBS4do208_KPGHAhszfVkHadSvtfSgr7Mo"];
dispatch_async(kBgQueue, ^{
NSData *data = [NSData dataWithContentsOfURL:url];
if (data == nil)
{
NSLog(#"data is nil");
}
else
{
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
}
});
}
- (void)viewDidDisappear:(BOOL)animated
{
[loadingIndicator stopAnimating];
}
- (void)fetchedData:(NSData *)responseData
{
NSError *error;
titleArray = [[NSMutableArray alloc]init];
videoIDArray = [[NSMutableArray alloc]init];
thumbArray = [[NSMutableArray alloc]init];
descriptionArray = [[NSMutableArray alloc]init];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
NSArray *items = [json objectForKey:#"items"];
for (NSDictionary *item in items)
{
NSDictionary *snippet = [item objectForKey:#"snippet"];
title = [snippet objectForKey:#"title"];
videoID = [[snippet objectForKey:#"resourceId"] objectForKey:#"videoId"];
thumbURL = [[[snippet objectForKey:#"thumbnails"] objectForKey:#"default"] objectForKey:#"url"];
descriptionString = [snippet objectForKey:#"description"];
[titleArray addObject:title];
[videoIDArray addObject:videoID];
UIImage *thumbnailImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:thumbURL]]];
[thumbArray addObject:thumbnailImage];
[descriptionArray addObject:descriptionString];
}
[self.tableView reloadData];
[loadingIndicator stopAnimating];
}
- (IBAction)morePressed:(id)sender
{
NSURL *kyfbVideos = [NSURL URLWithString:#"https://www.youtube.com/playlist?list=PL9DC706DCCCE00188"];
[[UIApplication sharedApplication] openURL:kyfbVideos];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [titleArray count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 215;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 60;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UIColor *kfbBlue = [UIColor colorWithRed:8.0/255.0f green:77.0/255.0f blue:139.0/255.0f alpha:1];
UIView *footerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height)];
footerView.backgroundColor = [UIColor clearColor];
CGFloat width = footerView.frame.size.width;
UIButton *moreButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
moreButton.backgroundColor = [UIColor clearColor];
[moreButton setTitle:#"More" forState:UIControlStateNormal];
[moreButton setTitleColor:kfbBlue forState:UIControlStateNormal];
moreButton.titleLabel.textAlignment = NSTextAlignmentCenter;
moreButton.titleLabel.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:25.0];
moreButton.frame = CGRectMake(width / 2 - 25, 0, 50, 50);
moreButton.layer.cornerRadius = 25.0;
moreButton.layer.borderWidth = 2.0f;
moreButton.layer.borderColor = kfbBlue.CGColor;
moreButton.clipsToBounds = YES;
moreButton.backgroundColor = [UIColor clearColor];
[moreButton addTarget:self action:#selector(morePressed:) forControlEvents:UIControlEventTouchUpInside];
[footerView addSubview:moreButton];
return footerView;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIColor *kfbBlue = [UIColor colorWithRed:8.0/255.0f green:77.0/255.0f blue:139.0/255.0f alpha:1];
YoutubeCell *cell = [tableView dequeueReusableCellWithIdentifier:#"youtubeCell"];
if (!cell)
{
NSArray *nibs =[[NSBundle mainBundle] loadNibNamed:#"YoutubeCell" owner:self options:NULL];
cell = [nibs firstObject];
}
cell.videoTitle.text = [titleArray objectAtIndex:indexPath.row];
cell.videoDescription.text = [descriptionArray objectAtIndex:indexPath.row];
cell.videoThumbnail.image = [thumbArray objectAtIndex:indexPath.row];
cell.videoTitle.textColor = kfbBlue;
cell.videoDescription.textColor = kfbBlue;
cell.videoTitle.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:22.0];
cell.videoDescription.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:16.0];
cell.backgroundColor = [UIColor clearColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
KFBYoutubeVideoView *videoView = [[KFBYoutubeVideoView alloc]init];
videoView.videoIDString = [videoIDArray objectAtIndex:indexPath.row];
videoView.videoTitle = [titleArray objectAtIndex:indexPath.row];
videoView.videoDescription = [descriptionArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController:videoView animated:YES];
}
else
{
KFBYoutubeVideoView *videoView = [[KFBYoutubeVideoView alloc]initWithNibName:nil bundle:nil];
videoView.videoIDString = [videoIDArray objectAtIndex:indexPath.row];
videoView.videoTitle = [titleArray objectAtIndex:indexPath.row];
videoView.videoDescription = [descriptionArray objectAtIndex:indexPath.row];
NSMutableArray *details = [self.splitViewController.viewControllers mutableCopy];
UINavigationController *detailNav = [[UINavigationController alloc]initWithRootViewController:videoView];
[details replaceObjectAtIndex:1 withObject:detailNav];
KFBAppDelegate *appDelegate = (KFBAppDelegate *)[[UIApplication sharedApplication]delegate];
appDelegate.splitViewController.viewControllers = details;
appDelegate.window.rootViewController = self.splitViewController;
appDelegate.splitViewController.delegate = videoView;
[appDelegate.splitViewController viewWillAppear:YES];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I figured it out. tableView was being initialized after adding loadingIndicator as a subview.

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"];

iOS UITableView content not loading - Property access result unused

I'm trying to load a table with content from Twitter. The table is in a UIView and being created in the drawRect()...but I keep getting a warning:
Property access result unused - getters should not be used for side effects
on each.
Nothing show up in my table.
Here's my .h file:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import <Twitter/Twitter.h>
#import "ColorController.h"
#interface TwitterController : UIView <UITableViewDelegate, UITableViewDataSource> {
UIButton* btnCloseView;
UITableView* tblTweets;
UIImageView* imgTwitterIcon;
ColorController* colorManager;
NSMutableArray* tweetsArray;
NSString* twitterID;
}
#property (nonatomic, retain) NSString* twitterID;
- (void) getTweets;
- (void) closeWin;
#end
and my .m
#import "TwitterController.h"
#implementation TwitterController
#synthesize twitterID;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
colorManager = [ColorController new];
}
return self;
}
- (void)drawRect:(CGRect)rect {
imgTwitterIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"imgTwitterBird"]];
CGRect twitterIconFrame = [imgTwitterIcon frame];
twitterIconFrame.origin.x = 50.0;
twitterIconFrame.origin.y = 20.0;
tblTweets = [[UITableView alloc] initWithFrame:CGRectMake(50.0, 25.0, 220.0, 500.0)];
tblTweets.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
tblTweets.separatorColor = [colorManager setColor:176.0:196.0:222.0];
tblTweets.layer.borderWidth = 1.0;
tblTweets.rowHeight = 20.0;
tblTweets.scrollEnabled = YES;
tblTweets.delegate.self;
tblTweets.dataSource.self;
UIImage* imgCloseButton = [UIImage imageNamed:#"btnCloseWindow.png"];
CGSize imageSize = imgCloseButton.size;
btnCloseView = [[UIButton alloc] initWithFrame: CGRectMake(220.0, 550.0, imageSize.width, imageSize.height)];
[btnCloseView setImage:[UIImage imageNamed:#"btnCloseWindow.png"] forState:UIControlStateNormal];
[btnCloseView addTarget:self action:#selector(closeWin:) forControlEvents:UIControlEventTouchUpInside];
[self getTweets];
[self addSubview:tblTweets];
[self addSubview:imgTwitterIcon];
[self addSubview:btnCloseView];
}
- (void) getTweets {
//array to hold tweets
tweetsArray = [[NSMutableArray alloc] init];
///set up a NSURL to the twitter API
NSURL* twitterAPI = [NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=%#&count=10", twitterID]];
//get last 10 tweets (max is 20)
TWRequest *twitterRequest = [[TWRequest alloc] initWithURL:twitterAPI
parameters:nil requestMethod:TWRequestMethodGET];
// Notice this is a block, it is the handler to process the response
[twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
// The response from Twitter is in JSON format
// Move the response into a dictionary and print
NSError *error;
NSDictionary *tweetsDict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
for(NSDictionary* thisTweetDict in tweetsDict) {
[tweetsArray addObject:[thisTweetDict objectForKey:#"text"]];
}
[tblTweets reloadData];
}
else
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
}
#pragma mark Table Management
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [tweetsArray count];
NSLog(#"%i", [tweetsArray count]);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tweetsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"tableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.textColor = [UIColor colorWithRed:66.0/255.0 green:66.0/255.0 blue:66.0/255.0 alpha:1];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size: 13.0];
cell.textLabel.text = [tweetsArray objectAtIndex:indexPath.row];
CGRect cellFrame = [cell frame];
cellFrame.size.height = 25.0;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* thisTweet = [tweetsArray objectAtIndex:indexPath.row];
}
#pragma mark Close Window
- (void) closeWin {
NSMutableDictionary* userData = [[NSMutableDictionary alloc] init];
[userData setObject:#"closeTwitter" forKey:#"theEvent"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"theMessenger" object:self userInfo: userData];
}
#end
drawRect is used to draw stuff inside this views, using drawing functions
You should move your views additions to the layoutSubviews
Instead of - (void)drawRect:(CGRect)rect use - (void)layoutSubviews
This may or may not solve your issues, but nevertheless its the correct approach

Resources