Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm facing problem with saving UITableViewCell's state and can't figure out how to solve it. Hope somebody can help me.

Explanation: There is an API on server and I get data from it and then store it inside NSMutableArray. Each object of an array contains property ready which can be 1 or 0. So I've no problems with populating UITableView with this data but not every data object is ready (i.e 0) and I need to get progress of completion at server and after that to show it in each cell is need it. I've UIProgressView in dynamic prototype of UITableViewCell and set progress after getting. There is no problem if such "not ready" object is only one. But if there are many objects I can't show progress and I don't understand why.

So here is my code.

cellForRowAtIndexPath method:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"readyCell";
AVMMovieCell  *cell = [self.readyTable dequeueReusableCellWithIdentifier:CellIdentifier];
    // Configure the cell...
if (cell == nil) {
    cell = (AVMMovieCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
AVMFilmsStore *oneItem;
oneItem = [readyArray objectAtIndex:indexPath.row];
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];

if (oneItem.ready==1){
    cell.progressLabel.hidden = YES;
    cell.progressLine.hidden = YES;

if ([selecedCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]  )
{

    if (![cell.progressLabel.text isEqualToString:@""]&& ![cell.progressLabel.text isEqualToString:@"Success"] && ![cell.progressLabel.text isEqualToString:@"Creating"]){
        cell.progressLabel.hidden = NO;
        cell.progressLine.hidden = NO;
    } else {
        cell.progressLabel.hidden = YES;
        cell.progressLine.hidden = YES;
      }
}
else{
    if(!oneItem.isProcessing && !cell.selected){
    cell.progressLabel.hidden = YES;
    cell.progressLine.hidden = YES;
    }
}
} else { //if processing
if (![processingCellsArray containsObject:[NSString stringWithFormat:@"%@",rowNsNum]]){
    [processingCellsArray addObject:[NSString stringWithFormat:@"%@",rowNsNum]];
    if (!cell.isSelected){

        [cell setSelected:YES];

    }
    cell.progressLabel.hidden = NO;
    cell.progressLine.hidden = NO;

    NSArray * arrayOfThingsIWantToPassAlong =
    [NSArray arrayWithObjects: cell, oneItem, indexPath, nil];

    if(!isMaking){
        [self performSelector:@selector(getProgress:)
                   withObject:arrayOfThingsIWantToPassAlong
                   afterDelay:0];
    } else{
    [self performSelector:@selector(getProgress:)
               withObject:arrayOfThingsIWantToPassAlong
               afterDelay:0.5];
    }

    isMaking = YES;

} else {
    if (!cell.isSelected){
        [cell setSelected:YES];
    }

    cell.progressLabel.hidden = NO;
    cell.progressLine.hidden = NO;

    NSArray * arrayOfThingsIWantToPassAlong =
    [NSArray arrayWithObjects: cell, oneItem, indexPath, nil];

    if(!isMaking){
        [self performSelector:@selector(getProgress:)
                   withObject:arrayOfThingsIWantToPassAlong
                   afterDelay:0];
    } else{
    [self performSelector:@selector(getProgress:)
               withObject:arrayOfThingsIWantToPassAlong
               afterDelay:0.3];
    }


    isMaking = YES;
    }

   }
    return cell;
 }

and getProgress method:

-(void)getProgress:(NSArray*)args{

if (progManager == nil && !progStop){
    __block AVMFilmsStore * oneItem = args[1];
    if(!oneItem.isLocal){
        __block AVMMovieCell * cell = args[0];
        __block NSIndexPath *indexPath = args[2];
        progManager = [AFHTTPRequestOperationManager manager];
        __block NSString *token = [defaults objectForKey:@"token"];
        __block NSString *header = [NSString stringWithFormat:@"Bearer %@",token];
        __block NSDictionary *params = @{@"lang": NSLocalizedString(@"lang",nil),@"project":oneItem.fileId};
        __block NSString *oneHundredPercent;
        __block NSString *progIsText;

        progManager.responseSerializer = [AFJSONResponseSerializer serializer];
        [progManager.requestSerializer setValue:header forHTTPHeaderField:@"Authorization"];
        if(cell.selected || isMaking) { //if I just check for "cell.selected" is always "NO"
            [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
            [progManager POST:@"http://example.com/api/project/get-progress" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
                if ([[responseObject objectForKey:@"result"]isEqualToString:@"success"]){
                    progCreate = [responseObject objectForKey:@"progress"];

                    oneHundredPercent = @"100";
                    if ([progCreate intValue]==[oneHundredPercent intValue]){
                        if([processingCellsArray containsObject:[NSString stringWithFormat:@"%ld",(long)indexPath.row]]){
                            [processingCellsArray removeObject:[NSString stringWithFormat:@"%ld",(long)indexPath.row]];
                            [cell setSelected:NO];

                        }
                        [readyArray removeAllObjects];
                        [defaults setObject:@"false" forKey:@"isSomethingInSort"];
                        isMaking = NO;
                        [self getReadyMovies:progIsText nameLabel:oneItem.fileName];

                    } else{
                        if([progCreate intValue]>=50){
                            if([progCreate intValue]>=60){
                                self.navigationController.navigationItem.leftBarButtonItem.enabled = YES;
                               createMainButton.enabled = YES;
                            }
                            [[NSNotificationCenter defaultCenter] postNotificationName:@"gotFiftyNote" object:@"50"];
                            [cell.progressLine setProgress:[progCreate floatValue]/100 animated:YES];
                        } else {
                            [cell.progressLine setProgress:progUploadLimit];
                        }
                        progManager = nil;
                        progManager.responseSerializer = nil;
                        progManager.requestSerializer = nil;
                        token = nil;
                        header = nil;
                        params = nil;
                        progIsText = nil;
                        oneItem = nil;
                        cell = nil;
                        indexPath = nil;
                        isMaking = YES;
                        progCreate = nil;
                        oneHundredPercent = nil;

                        [self getProgress:args];
                    }
                }
            } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
                NSLog(@"Error: %@", error.localizedDescription);
            }];

        }

    }
  }
}

Any suggestions will be helpful for me. I've a headache for two weeks with this problem.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
154 views
Welcome To Ask or Share your Answers For Others

1 Answer

I see your code but is kind of difficult to follow with those large methods. I wouldn't keep track of the processing cells in an array. Each cell has an object to represent, those object have a bool value of ready and a progress value, right?. So try something like this:

  • Make sure each of your cells have a progressView as a subview.
  • Your cell class should have a public method named styleForReady:(bool)isReady andProgress:(nsinteger)progress
  • Make the service call to see if they are done or not, for each model. Whenever that service call comes back, you just update the model objects in the array, and after they have the new progress values you do [self.tableView reloadData]. This would trigger numberOfRows (which should return arrayOfObjects.count) and cellForRowAtIndexPath:(which should dequeue the cell for that indexPath, grab the model representing that cell, something like arrayOfObjects[indexPath.row], and finally, call the cell to style itself based on that model doing [cell styleForReady:objectModel.ready andProgress:objectModel.progress])

Keep in mind that the controller should just keep track of the model objects, dequeue the cell and tell the cell to style passing the model. Don't put all the logic in the controller.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...