I'm trying to show a button on certain cells in my tableview depending on type of image showing in that cell
soo i have two NSMutableArray's one holding the thumbnail image URL's and the other NSMutableArray holding the type of the url if it was image or video
the problem is the button doesn't show on all the video type cells
here is my code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TVCustomCell";
TVCustom *cell = (TVCustom *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TVCustom" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[TVCustom class]]) {
cell = (TVCustom *) currentObject;
break;
}
}
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *imgURL = [arrayImagesURL objectAtIndex:indexPath.row];
NSURL *imageURL = [NSURL URLWithString:imgURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
cell.thumbImg.image = image;
});
});
NSString *MediaType = [NSString stringWithFormat:#"%#", [arrayType objectAtIndex:indexPath.row]];
if ([MediaType isEqualToString:#"video"]) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(120, 319, 50, 30);
[button setTitle:#"Play" forState:UIControlStateNormal];
button.tag = indexPath.row;
[button addTarget:self action:#selector(PlayBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor= [UIColor clearColor];
[cell.contentView addSubview:button];
}
return cell;
}
i don't know what i'm doing wrong, any idea ?
I see different problems here.
First
Your code creates new buttons every time the user scrolls in the tableView. This is because you use dequeueReusableCellWithIdentifier which is great and returns existing cells instead of creating new ones.
But then you add a new button on cells which already exist (and may or may not have a button)
[cell.contentView addSubview:button];
I suggest you add the button in your TVCustom class:
In the TVCustom.h
#property (strong, nonatomic) UIButton *viedoButton;
In TVCustom.m
- (UIButton *)videoButton
{
if (!_videoButton) {
_videoButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
_videoButton.frame = CGRectMake(120, 319, 50, 30);
[_videoButton setTitle:#"Play" forState:UIControlStateNormal];
[_videoButton addTarget:self action:#selector(PlayBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
_videoButton.backgroundColor= [UIColor clearColor];
[self.contentView _videoButton];
}
return _videoButton;
}
Then in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath you only do :
if ([MediaType isEqualToString:#"video"]) {
cell.videoButton.hidden = NO;
} else {
cell.videoButton.hidden = YES;
}
This way every cell will have only one button and it will be visible only when you need it but not re-allocated every time. But PlayBtnClicked will have to be in your TVCustom class and call your viewController through a delegate.
Second
You should not handle the loading of your image in the cellForRowAtIndexPath method. Encapsulate it your TVCustom class:
In TVCustom.h
#property (strong, nonatomic) NSString *imgURL;
In TVCustom.m
- (void)setImgURL:(NSString *)imgURL
{
_imgURL = imgURL;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *imageURL = [NSURL URLWithString:imgURL];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
self.thumbImg.image = image;
});
});
}
Then in cellForRowAtIndexPath it will look like :
cell.imgURL = [arrayImagesURL objectAtIndex:indexPath.row];
Third
I do not know if you have any particular reason for this:
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TVCustom" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[TVCustom class]]) {
cell = (TVCustom *) currentObject;
break;
}
}
}
But a good way to do this is in your viewController's viewDidLoad (or other method):
NSString *identifier = #"TVCustomCell";
NSString *nibName = #"TVCustom";
UINib *cellNib = [UINib nibWithName:nibName];
[self.tableView registerNib:cellNib forCellReuseIdentifier:identifier];
Your final code should look like :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"TVCustomCell";
TVCustom *cell = (TVCustom *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.imgURL = [arrayImagesURL objectAtIndex:indexPath.row];
if ([MediaType isEqualToString:#"video"]) {
cell.videoButton.hidden = NO;
} else {
cell.videoButton.hidden = YES;
}
return cell;
}
Related
I have two UIViewControllers with tableview. When the first cell loads in the second UIViewController it calls the cellForRowAtIndexPath in the same class but when it loads the second cell it calls the first viewControllers cellForRowAtIndexPath.
My code as follows:
SecondViewController:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NotificationsTableViewCell *cell = [self.notificationsTableView dequeueReusableCellWithIdentifier:#"NotificationCell"];
if(cell == nil)
{
cell = [[NotificationsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"NotificationCell"];
}
NSMutableDictionary *cellData = [self.databaseCall transactionFromDatabase:indexPath.row];
NSLog(#"%#", cellData);
cell.goalNameLabel.text = [cellData objectForKey:#"categoryName"];
NSString *cardTypeId = [cellData objectForKey:#"cardTypeId"];
NSString *tipsId = [cellData objectForKey:#"tipsId"];
if([self.defaultCardTypeId containsObject:cardTypeId])
{
NSUInteger index = [self.defaultCardTypeId indexOfObject:cardTypeId];
[self.defaultCardTypeId replaceObjectAtIndex:index withObject:cardTypeId];
}
else{
[self.defaultCardTypeId addObject:cardTypeId];
}
if([self.defaultTipId containsObject:tipsId])
{
NSUInteger index = [self.defaultCardTypeId indexOfObject:cardTypeId];
[self.defaultTipId replaceObjectAtIndex:index withObject:cardTypeId];
}
else{
[self.defaultTipId addObject:tipsId];
}
if([cardTypeId isEqualToString:#"1"])
{
UIImage *cellImage = [UIImage imageNamed:#"icon2.jpg"];
cell.cardTypeImage.image = cellImage;
cell.cardTypeLabel.text = #"GOOD TO KNOW";
cell.cardTypeLabel.textColor = [UIColor colorWithRed:252/255.0 green:171/255.0 blue:19/255.0 alpha:1];
}
if([cardTypeId isEqualToString:#"2"])
{
UIImage *cellImage = [UIImage imageNamed:#"icon1.jpg"];
cell.cardTypeImage.image = cellImage;
cell.cardTypeLabel.text = #"TO CONSIDER";
cell.cardTypeLabel.textColor = [UIColor colorWithRed:0/255.0 green:191/255.0 blue:243/255.0 alpha:1];
}
cell.notificationCard.layer.cornerRadius = 5;
// Configure the cell...
return cell;
}
FirstViewController:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
GoalsCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"GoalsListCell" forIndexPath:indexPath];
if(cell == nil)
{
cell = [[GoalsCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"GoalsListCell"];
}
NSInteger indexOfCategory = [self.databaseCall.arrColumnName indexOfObject:#"CategoryName"];
NSInteger indexOfImage = [self.databaseCall.arrColumnName indexOfObject:#"CategoryImage"];
NSInteger indexOfActive = [self.databaseCall.arrColumnName indexOfObject:#"coulmn"];
//Assigning the contents of cell
cell.goalName.text = [NSString stringWithFormat:#"%#", [[self.arrCategoryTitle objectAtIndex:indexPath.row] objectAtIndex:indexOfCategory]];
NSString *categoryImage = [NSString stringWithFormat:#"%#", [[self.arrCategoryTitle objectAtIndex:indexPath.row] objectAtIndex:indexOfImage]];
NSString *activeStatus = [NSString stringWithFormat:#"%#", [[self.arrCategoryTitle objectAtIndex:indexPath.row] objectAtIndex:indexOfActive]];
UIImage *cellImage = [UIImage imageNamed:categoryImage];
cell.goalImage.image = cellImage;
[cell.favouriteButton addTarget:self action:#selector(favouriteButtonPressed:) forControlEvents:UIControlEventTouchDown];
NSMutableString *selectedRowImage = [[NSMutableString alloc] initWithString:#""];
//Checking whether the category is selected by user or not
if([activeStatus isEqualToString:#"yes"])
{
selectedRowImage = [NSMutableString stringWithFormat:#"starsel.png"];
}
else
{
selectedRowImage = [NSMutableString stringWithFormat:#"stardef.png"];
}
UIImage *favouriteIconImage = [UIImage imageNamed:selectedRowImage];
[cell.favouriteButton setBackgroundImage:favouriteIconImage forState:UIControlStateNormal];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Configure the cell...
return cell;
}
Thanks in advance.
First of all i would say sorry for this stupid question.
The problem is due to the tableview datasource as specifies by #Paulw11, #Onik IV, #Kannan Vora. The secondViewController tableView has the datasource of firstViewController.
I am making an app in which i am getting data from server and in data image path is also coming but when i am setting image to my tableview cell app will become too much heavy may b i am not setting image properly below is my sample code thanx in advance :)
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *tableviewidentifier = #"cell";
tablecellTableViewCell *cell= [self.activitiesTableView_ dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[tablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}if(indexPath.row == [self tableView:tableView numberOfRowsInSection:indexPath.section] - 1){
// [[cell textLabel] setText:#"Load more records"];
}
UILabel *valuedate = (UILabel *)[cell viewWithTag:21];
UILabel *msg = (UILabel *)[cell viewWithTag:22];
UILabel *date = (UILabel *)[cell viewWithTag:23];
UILabel *time = (UILabel *)[cell viewWithTag:24];
valuedate.text=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerTitle"];
msg.text=#"How are you?";
NSString *img=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerPhoto"];// here i am getting image path
UIImage *img1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:img]]];
cell.imageView.image=img1;// here i am setting image due to which app is so heavy and stuck
return cell;
}
Dont use imageWithData: for setting images. It is synchronous and will make your app run slow.
Instead of that Use SDWebImage
You just need to do following things:
Dump SDWebImage folder into your project.
Import UIImageView+WebCache.h.
Set the image using: sd_setImageWithURL:
OR
by GCD (Grand Central Dispatch) and sending asynchronous requests. Code copied from HERE.
First implement following method.
- (void)downloadImageWithURL:(NSURL *)url completionBlock:(void (^)(BOOL succeeded, UIImage *image))completionBlock
{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if ( !error )
{
UIImage *image = [[UIImage alloc] initWithData:data];
completionBlock(YES,image);
} else{
completionBlock(NO,nil);
}
}];
}
and then in your cellForRowAtIndexPath
[self downloadImageWithURL:your_url completionBlock:^(BOOL succeeded, UIImage *image) {
if (succeeded) {
// change the image in the cell
cell.imageView.image = image;
}
}];
try this below code, hope this helps u .
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
__block tablecellTableViewCell *cell= [self.activitiesTableView_ dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[tablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}
if(indexPath.row == [self tableView:tableView numberOfRowsInSection:indexPath.section] - 1)
{
// [[cell textLabel] setText:#"Load more records"];
}
UILabel *valuedate = (UILabel *)[cell viewWithTag:21];
UILabel *msg = (UILabel *)[cell viewWithTag:22];
UILabel *date = (UILabel *)[cell viewWithTag:23];
UILabel *time = (UILabel *)[cell viewWithTag:24];
valuedate.text=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerTitle"];
msg.text=#"How are you?";
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSString *img=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerPhoto"];// here i am getting image path
NSURL *url = [NSURL URLWithString:img];
NSData * imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_sync(dispatch_get_main_queue(), ^{ //in main thread update the image
cell.imageView.image = image;
cell.textLabel.text = #""; //add this update will reflect the changes
});
});
return cell;
}
EDIT
in order to reuse the downloaded image u can either save them on disk or just for save them some where for example in dictionary for temporary using
in below code i took one example dictionary, and strong the download images with row as key
#interface ViewController ()
{
NSMutableDictionary *imagesDictionary; //lets declare a mutable dictionary to hold images
}
in this method just initialise it
- (void)viewDidLoad {
[super viewDidLoad];
// rest of your code
//...........
//
imagesDictionary = [[NSMutableDictionary alloc]init]; //initilise
}
in index this method just add the downloaded images to dictionary for corresponding row as key
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
__block tablecellTableViewCell *cell= [self.activitiesTableView_ dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[tablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}
if(indexPath.row == [self tableView:tableView numberOfRowsInSection:indexPath.section] - 1)
{
// [[cell textLabel] setText:#"Load more records"];
}
__block NSString *row = [NSString stringWithFormat:#"%d",indexPath.row]; //add this
UILabel *valuedate = (UILabel *)[cell viewWithTag:21];
UILabel *msg = (UILabel *)[cell viewWithTag:22];
UILabel *date = (UILabel *)[cell viewWithTag:23];
UILabel *time = (UILabel *)[cell viewWithTag:24];
// valuedate.text=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerTitle"];
msg.text=#"How are you?";
if(![[imagesDictionary allKeys] containsObject:row]) //if image not found download and add it to dictionary
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// NSString *img=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"offerPhoto"];// here i am getting image path
NSURL *url = [NSURL URLWithString:img];
NSData * imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_sync(dispatch_get_main_queue(), ^{ //in main thread update the image
[imagesDictionary setObject:image forKey:row]; //sorry, while editing to your code i forgot to add this
cell.imageView.image = image;
cell.textLabel.text = #""; //add this update will reflect the changes
NSLog(#"loading and addig to dictionary");
});
});
}
else
{
cell.imageView.image = [imagesDictionary objectForKey:row];
NSLog(#"retriving from dictioary");
}
return cell;
}
First of all you are calling dataWithContentsOfURL: function which will make the app non responsive because you are calling it on main thread. To make it responsive you need to create a custom cell YourCell and declare a method in YourCell.h
#interface YourCell : UITableViewCell
{
UIImage *_cImage;
}
- (void)downloadImageFromURL:(NSURL *)imageUrl;
#end
Now in YourCell.m you need to do like this:
- (void)downloadImageFromURL:(NSURL *)imageUrl
{
if (_cImage != nil)
{
self.imageView.image = _cImage;
}
else
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
_cImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageUrl]];
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image = _cImage;
});
});
}
}
Now from cellForRowAtIndexPath: you just need to call downloadImageFromURL: function of YourCell and pass the imageUrl to it and its the cell responsibility to download and show the image.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier= #"YourCell";
YourCell *cell = (YourCell *)[self.activitiesTableView_ dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"YourCell" owner:self options:nil] objectAtIndex:0];
}
// Set your UILabels as before.....
NSString *imagePath=[[self.inboxmessagesarray objectAtIndex:indexPath.row] objectForKey:#"offerPhoto"];
[cell downloadImageFromURL:[NSURL URLWithString:imagePath]];
return cell;
}
Let me know if you have any questions.
UIImageView *img1 = (UIImageView *)[cell viewWithTag:104];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
img1.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:img]]];
});
});
Send async requests for images. Doing this would not block your UI until the image gets loaded.
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
I have a test for whether a cell was clicked by the user. If it was clicked, the image changes. I want that image to remain checked, even if the user clicks it again or the app reloads.
It's really close to working. Right now, the image changes from the grey version to the green version when the cell was selected. The problem is the grey image shows back up when the user clicks the cell again. What do I need to do to fix this?
//begin checking for selected row and add checkmark
- (NSString *)getKeyForIndex:(int)index
{
return [NSString stringWithFormat:#"KEY%d",index];
}
- (BOOL) getCheckedForIndex:(int)index
{
if([[[NSUserDefaults standardUserDefaults] valueForKey:[self getKeyForIndex:index]] boolValue]==YES)
{
return YES;
}
else
{
return NO;
}
}
- (void) checkedCellAtIndex:(int)index
{
BOOL boolChecked = [self getCheckedForIndex:index];
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:!boolChecked] forKey:[self getKeyForIndex:index]];
[[NSUserDefaults standardUserDefaults] synchronize];
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableList count];
}
// Customize the content and the look of table view cells.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UIImage *greyck =[UIImage imageNamed:#"greycheck-sd.png"];
UIImage *greenck =[UIImage imageNamed:#"greencheck-sd.png"];
//step 1 check to see if we can reuse a cell that has just rolled off the screen
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath: indexPath];
//step 2: if there are no cells to be reused, create a new cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
//step 3: set the text in the cell using items from the array
cell.textLabel.text = [tableList objectAtIndex:indexPath.row];
//set custom font
cell.textLabel.font = [UIFont fontWithName:#"Chalkboard SE" size:18.0f];
//check for previously viewed then set the image
if([self getCheckedForIndex:indexPath.row]==YES)
{
//sets green checkmark after user clicks
cell.imageView.image = greenck;
}
else
{
cell.imageView.image = greyck;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIImage *greyck =[UIImage imageNamed:#"greycheck-sd.png"];
UIImage *greenck =[UIImage imageNamed:#"greencheck-sd.png"];
NSString *str= [tableList objectAtIndex:indexPath.row];
if ([str isEqual:#"introduction"])
{
NSBundle *bundle = [NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:#"Step1-Intro" ofType:#"mp4"];
NSURL *movieURL = [NSURL fileURLWithPath:moviePath];
MPMoviePlayerController *theMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.scalingMode = MPMovieScalingModeAspectFill;
[theMovie play];
MPMoviePlayerViewController *moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];
[self presentMoviePlayerViewControllerAnimated:moviePlayer];
}
else if ([str isEqual:#"skating"])
{
NSBundle *bundle = [NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:#"Step2-Skating" ofType:#"mp4"];
NSURL *movieURL = [NSURL fileURLWithPath:moviePath];
MPMoviePlayerController *theMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.scalingMode = MPMovieScalingModeAspectFill;
[theMovie play];
MPMoviePlayerViewController *moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];
[self presentMoviePlayerViewControllerAnimated:moviePlayer];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
//Use checkedCellAtIndex for check or uncheck cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self checkedCellAtIndex:indexPath.row];
if([self getCheckedForIndex:indexPath.row]==YES)
{
cell.imageView.image = greenck;
}
else
{
cell.imageView.image = greyck;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You do set the displayed image to green at 2 places with
if([self getCheckedForIndex:indexPath.row]==YES)
{
cell.imageView.image = greenck;
}
But getCheckedForIndex: returns YES
if([[[NSUserDefaults standardUserDefaults] valueForKey:[self getKeyForIndex:index]] boolValue]==YES)
So far, so good. But it seems to me that you never update your user defaults. If so, you always would return the same value, and nothing will change.
I want to connect an my app to the database and display it in a Label.
I could connect my app to the database and display it in the UITableView.
This is what I have so far:
Viewontroller.h
#import <UIKit/UIKit.h>
#interface CartHistoryViewController : UITableViewController
{
NSMutableArray *arrayDataFromServer;
}
#end
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/CartGet.php? choice=history"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
strURL = #"http://localhost:8888/CartGet.php?choice=historydate";
NSArray *arrayImagesPaths = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
// store the result in arrayDataFromServer
arrayDataFromServer = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
NSEnumerator *enumForPahts = [arrayImagesPaths objectEnumerator];
id objName, objPath;
while ( objName = [enumForNames nextObject]) {
objPath = [enumForPahts nextObject];
[arrayDataFromServer addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", objPath, #"path", nil]];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [[arrayDataFromServer objectAtIndex:indexPath.row] objectForKey:#"name"];
[cell.textLabel setFont:[UIFont systemFontOfSize:20]];
cell.detailTextLabel.text = [[arrayDataFromServer objectAtIndex:indexPath.row] objectForKey:#"path"];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#",[[arrayDataFromServer objectAtIndex:indexPath.row] objectForKey:#"path"]]];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:data];
cell.imageView.image = img;
return cell;
}
I want to be able to display it in a Label and in an ImageView instead of a cell. Please help.
Go to your Interface Builder choose your table view and make it Grouped TableView
add below code before your - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [arrayDataFromServer count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 0;
}
// set header height of gropued tableview
-(CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section
{
return 120;//change this value if it is too big
}
//set header section labels
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
NSString * subject=[[arrayDataFromServer objectAtIndex:section] objectForKey:#"name"];//this line may give you error because of section easy to correct
UILabel *subjectLabel = [[UILabel alloc] initWithFrame:CGRectMake(45, 30, 100, 100)];
subjectLabel.textColor = [UIColor colorWithRed:0/256.0 green:84/256.0 blue:129/256.0 alpha:1.0];
subjectLabel.font = [UIFont fontWithName:#"Arial" size:25];
subjectLabel.text = subject;
subjectLabel.backgroundColor = [UIColor clearColor];
[subjectLabel sizeToFit];
// if you want to add image view create an imageview programatically here
// NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#",[[arrayDataFromServer objectAtIndex:section] objectForKey:#"path"]]];
//NSData *data = [NSData dataWithContentsOfURL:url];
//UIImage *img = [UIImage imageWithData:data];
// UIImageView *brickAnim = [[UIImageView alloc] initWithImage:img];
// Create header view and add label as a subview choose coordinates wisely
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 120, 100, G00)];
[view addSubview:subjectLabel];
//[view addSubview:brickAnim];
return view;
}