2

I have a UITableViewCell and I have a UIButton in it. Each time I press the button, there is a network call and it updates a label (increments or decrements the count), something similar to the Facebook 'like' concept.

The problem is when the user repeatedly presses the UIButton, the values keep incrementing or decrementing. I tried toggling the userInteraction and also setting the setEnabled state. Still doesnt work.

I then tried using blocks as this link suggested. Still not working. I'm pretty new to blocks. Is there something I'm doing wrong here?

This is the implementation without blocks:

    - (void) giveKarmaCheck:(BOOL)complete // network delegate after the update
    {
        NSLog(@"Completed!");
        _karmaBeingGiven = NO;
        NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] initWithDictionary:[[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section]];
        int qKarma = [[tempDict objectForKey:@"qkarma"] integerValue];
        NSString *karmaCountString;
        QXTHomeCell *questionCell = (QXTHomeCell*)[self.questionsTable cellForRowAtIndexPath:_indexPath];
        if (_karmaGiven)
        {
            [tempDict setValue:[NSNumber numberWithInt:1] forKey:@"qkarmaStatus"];
            qKarma++;
            [questionCell.karmaLogo setImage:[UIImage imageNamed:@"logo-black"]];
            questionCell.karmaCount = [NSNumber numberWithInt:questionCell.karmaCount.integerValue + 1];

            // Question Owner Karma
            NSMutableString *karmaLabelText = [[NSMutableString alloc] initWithString:@"Karma\n"];
            karmaCountString = [NSString stringWithFormat:@"%d", [[[[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section] objectForKey:@"qownerkarma"]integerValue]+1];

            [karmaLabelText appendString:karmaCountString];
            questionCell.karmaLabel.text = karmaLabelText;
        }
        else
        {
            [tempDict setValue:[NSNumber numberWithInt:0] forKey:@"qkarmaStatus"];
            qKarma--;
            [questionCell.karmaLogo setImage:[UIImage imageNamed:@"logo-grey"]];
            questionCell.karmaCount = [NSNumber numberWithInt:questionCell.karmaCount.integerValue - 1];

            // Question Owner Karma
            NSMutableString *karmaLabelText = [[NSMutableString alloc] initWithString:@"Karma\n"];
            karmaCountString = [NSString stringWithFormat:@"%d", [[[[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section] objectForKey:@"qownerkarma"]integerValue]-1];

            [karmaLabelText appendString:karmaCountString];
            questionCell.karmaLabel.text = karmaLabelText;
        }
        NSLog(@"Count *** %@", karmaCountString);

        NSMutableArray *tempAnswerArray = [[NSMutableArray alloc] initWithArray:[_questions objectForKey:@"questions"]];
        NSMutableDictionary *tempAnswerDict = [[NSMutableDictionary alloc] initWithDictionary:[tempAnswerArray objectAtIndex:_indexPath.section]];

        [tempAnswerDict setValue:karmaCountString forKey:@"qownerkarma"];
        [tempAnswerArray replaceObjectAtIndex:_indexPath.section withObject:tempAnswerDict];
    //    NSLog(@"Array %@", tempAnswerDict);
        [_questions setObject:tempAnswerArray forKey:@"questions"];

        NSLog(@"Total %@ Count %d", [[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section], [[[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section] count]);



        [tempDict setValue:[NSNumber numberWithInt:qKarma] forKey:@"qkarma"];
        [[_questions mutableArrayValueForKey:@"questions"] replaceObjectAtIndex:_indexPath.section withObject:tempDict];

        NSMutableString *withoutCount = [[NSMutableString alloc] initWithString:[QXTUtility removeLastWord:questionCell.karmaButton.titleLabel.text]];
        [withoutCount appendString:[NSString stringWithFormat:@" %d", questionCell.karmaCount.integerValue]];
        [questionCell.karmaButton setTitle:[QXTUtility stripDoubleSpaceFrom:withoutCount] forState:UIControlStateNormal];

        [questionCell.karmaButton setUserInteractionEnabled:YES];

    }

Did the same thing with the block implementation:

- (void) giveKarmaCheck:(BOOL)complete
{
    QXTHomeCell *questionCell = (QXTHomeCell*)[self.questionsTable cellForRowAtIndexPath:_indexPath];
    [questionCell.karmaButton setEnabled:NO];

    __block NSMutableString *karmaLabelText, *withoutCount;

    dispatch_async(dispatch_get_global_queue(0,0), ^{
        NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] initWithDictionary:[[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section]];
        int qKarma = [[tempDict objectForKey:@"qkarma"] integerValue];
        NSString *karmaCountString;
        if (_karmaGiven)
        {
            [tempDict setValue:[NSNumber numberWithInt:1] forKey:@"qkarmaStatus"];
            qKarma++;

            // Question Owner Karma
            karmaLabelText = [[NSMutableString alloc] initWithString:@"Karma\n"];
            karmaCountString = [NSString stringWithFormat:@"%d", [[[[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section] objectForKey:@"qownerkarma"]integerValue]+1];

            [karmaLabelText appendString:karmaCountString];

        }
        else
        {
            [tempDict setValue:[NSNumber numberWithInt:0] forKey:@"qkarmaStatus"];
            qKarma--;

            // Question Owner Karma
            NSMutableString *karmaLabelText = [[NSMutableString alloc] initWithString:@"Karma\n"];
            karmaCountString = [NSString stringWithFormat:@"%d", [[[[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section] objectForKey:@"qownerkarma"]integerValue]-1];

            [karmaLabelText appendString:karmaCountString];
        }

        NSMutableArray *tempAnswerArray = [[NSMutableArray alloc] initWithArray:[_questions objectForKey:@"questions"]];
        NSMutableDictionary *tempAnswerDict = [[NSMutableDictionary alloc] initWithDictionary:[tempAnswerArray objectAtIndex:_indexPath.section]];

        [tempAnswerDict setValue:karmaCountString forKey:@"qownerkarma"];
        [tempAnswerArray replaceObjectAtIndex:_indexPath.section withObject:tempAnswerDict];
        //    NSLog(@"Array %@", tempAnswerDict);
        [_questions setObject:tempAnswerArray forKey:@"questions"];

        NSLog(@"Total %@ Count %d", [[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section], [[[_questions objectForKey:@"questions"] objectAtIndex:_indexPath.section] count]);



        [tempDict setValue:[NSNumber numberWithInt:qKarma] forKey:@"qkarma"];
        [[_questions mutableArrayValueForKey:@"questions"] replaceObjectAtIndex:_indexPath.section withObject:tempDict];

        withoutCount = [[NSMutableString alloc] initWithString:[QXTUtility removeLastWord:questionCell.karmaButton.titleLabel.text]];
        [withoutCount appendString:[NSString stringWithFormat:@" %d", questionCell.karmaCount.integerValue]];

        dispatch_async(dispatch_get_main_queue(), ^{
            [questionCell.karmaButton setEnabled:YES];
            if (_karmaGiven)
            {
                [questionCell.karmaLogo setImage:[UIImage imageNamed:@"logo-black"]];
                questionCell.karmaCount = [NSNumber numberWithInt:questionCell.karmaCount.integerValue + 1];
                questionCell.karmaLabel.text = karmaLabelText;
            }
            else
            {
                [questionCell.karmaLogo setImage:[UIImage imageNamed:@"logo-grey"]];
                questionCell.karmaCount = [NSNumber numberWithInt:questionCell.karmaCount.integerValue - 1];

                questionCell.karmaLabel.text = karmaLabelText;
            }
            [questionCell.karmaButton setTitle:[QXTUtility stripDoubleSpaceFrom:withoutCount] forState:UIControlStateNormal];
        });


    });

    NSLog(@"Completed!");

}
Community
  • 1
  • 1
Anil
  • 2,430
  • 3
  • 37
  • 55
  • 1
    Hold on, so you are stating that multiple button presses cause multiple actions. That is the definition of how a button should work. Are you asking for a way to disable the UIButton? you can use setEnabled to NO for that. The question is a little unclear. – Bergasms Sep 17 '13 at 07:16
  • Try by disabling the self.view and check. And make sure you update UI on main thread. – Prasad_R Sep 17 '13 at 07:20
  • @Bergasms I tried setEnabled to NO but that doesnt help. There are points where the 'enabled' state of the UIButton changes to YES for a fraction of a second or so. As the user is constantly tapping the UI, it causes the increment/decrement – Anil Sep 17 '13 at 07:45
  • @Prasad_R Disabling self.view will cause my UI to freeze. The user should be able to tap on the cell during this time too. – Anil Sep 17 '13 at 07:46
  • The code you have posted is explicitly enabling the button `[questionCell.karmaButton setEnabled:YES];` in your main_queue block. – Michael Kernahan Sep 17 '13 at 13:20
  • I would disable the button immediately upon pressing it, and have it enabled on the delegate callback. – diatrevolo Sep 17 '13 at 15:57
  • @MichaelKernahan should I be doing it differently? – Anil Sep 18 '13 at 03:59
  • @diatrevolo that's what I'm doing. But it doesnt seem to fix the problem. Coz for each press there is a network call going and also the local data is changed to make the UI better. So the setEnabled = YES of the first click might be toggled say when the 4th press is made. Making the increment happen again. – Anil Sep 18 '13 at 04:01
  • @Anil Maybe I don't understand your use case, but you are always enabling the karma button when your blocks complete. – Michael Kernahan Sep 18 '13 at 12:49
  • @MichaelKernahan I have a feeling you do. And theoretically what you're asking me to do should solve the problem. But it isn't. – Anil Sep 18 '13 at 13:43
  • @Anil - Why not have two buttons? One is always hidden and vice versa. When the user touches the button, swap. – Michael Kernahan Sep 18 '13 at 16:08
  • @MichaelKernahan that is an interesting solution. But is it supposed to be that hard? Dont you think its a weird work around? Shouldn't it be possible with a single button? – Anil Sep 18 '13 at 19:22
  • 1
    Wouldn't it be much easier? You would separate your concerns (up/down karma), and you could easily have different images/text for the two different functions. – Michael Kernahan Sep 19 '13 at 01:55

1 Answers1

0

The reason why disabling the button doesn't work is because it's a call to a UIKit object, which should be performed on the main thread. Basically, you don't know what thread the network delegate method is being called from (it's probably the background). Within the delegate method anything that has to do with UI should be sent to the main queue. In the method:

- (void) giveKarmaCheck:(BOOL)complete;

Wrap the UI calls in

dispatch_async(dispatch_get_main_queue(), ^{
    // Do UI stuff on this thread
});

Note the main queue and global queue are not the same.

Community
  • 1
  • 1
JuJoDi
  • 14,627
  • 23
  • 80
  • 126