Reputation: 559
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 ?
Upvotes: 0
Views: 771
Reputation: 1915
I see different problems here.
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.
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];
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;
}
Upvotes: 1