aLFaRSi
aLFaRSi

Reputation: 559

Showing/Hiding button in custom cell on demand not working

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

Answers (1)

tgyhlsb
tgyhlsb

Reputation: 1915

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

Upvotes: 1

Related Questions