0

I have on my application a list of pictures in a table. I have a function on Parse to modify a picture.

So in a for loop i take pictures one by one by one and upload it (save on parse) and next i call the parse function to modify the file.

And on the device screen i want to write the progress like "3 of 14 pictures modified" or with a progressbar.

The problem is when in my loop i call Parse methods like [imageToSave save]; i can't modify elements on the viewcontroller.

It mean methods like this doesn't work :

iLabelText = [NSString stringWithFormat:@"%d", i+1];
totalScanText = [NSString stringWithFormat:@"%d", (int)[arrayOfPicture count]];
[_iLabel setText:iLabelText];
[_totalScanLabel setText:totalScanText];

I know it's possible to use saveInBackgroundWithBlock and get the percent of actual upload but how can i know when the upload is complete and then start the next upload ?

Actually I have a code without saveInBackgroundWithBlock and it work but i can't modify elements of UI. When i try with saveInBackgroundWithBlock all the pictures are uploaded in the same time.

I am not on to make things in a right way, how you would make ?

I can post the code later if you need. edit : here is my code : (i have deleted useless lines) : I call save and modify function with thread, it was for test it work witout thread. I think i have the same problem of this post : Change UILabel in loop but I can not seem to correct the problem :/

-(void)majLabel {
[_iLabel setText:iLabelText];
[_totalScanLabel setText:totalScanText];
NSLog(@"UPDATE LABEL");
}

- (IBAction)startButton:(id)sender {
    //AJOUTER TEST CONNEXION

    NSMutableArray *listOfPicture = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"listOfPicture"]];

    theCurrentUser = [PFUser currentUser];

    scanDone = 0;

    //for each scan
    for (int i=0; i < [listOfPicture count]; i++) {

        //update total progress
        float totalProgressValue = (i*100)/([listOfPicture count]-1);
        _totalProgress.progress = totalProgressValue/100;

        //uptade label total progress

        iLabelText = [NSString stringWithFormat:@"%d", i+1];
        totalScanText = [NSString stringWithFormat:@"%d", (int)[listOfPicture count]];
        [_iLabel setText:iLabelText];
        [_totalScanLabel setText:totalScanText];
        [self majLabel];

        UIImage *imageTomodify = listOfPicture[i];
        _currentImage.image = imageTomodify;


        //Need before STEP 1
        NSData *imageData = UIImageJPEGRepresentation(imageTomodify);

        //filename is date
        NSString * timeStampValue = [NSString stringWithFormat:@"%ld", (long)[[NSDate date] timeIntervalSince1970]];
        NSString * fileName = [NSString stringWithFormat:@"%@.jpg",timeStampValue];
        PFFile *imageFile = [PFFile fileWithName:fileName data:imageData];


        NSLog(@"(img%d) STEP 1 OK (make image)", i);

        //STEP 2
        NSThread* myThread = [[NSThread alloc] initWithTarget:self
                                                     selector:@selector(saveImage:)
                                                       object:imageFile];
        fileSaveDone = NO;
        [myThread start];
        while (fileSaveDone == NO) {
            //wait
        }
        NSLog(@"(img%d) STEP 2 OK (upload image), modify...", i);
        //STEP 3
        NSThread* myThread2 = [[NSThread alloc] initWithTarget:self
                                                      selector:@selector(modifyImage:)
                                                        object:imageFile];
        modifyDone = NO;
        [myThread2 start];

        while (modifyDone == NO) {
            //wait
        }
        _lastImage.image = imageTomodify;
        NSLog(@"(img%d) Comparaison img terminé", i);

    }
}

- (BOOL)saveImage:(PFFile *)imageToSave{
    NSLog(@"Thread save image started");
    [imageToSave save];

    fileSaveDone = YES;
    return YES;
}

- (void)modifyImage:(PFFile*)imageFile{
    NSLog(@"Thread modify image started");
    [self modify:[PFUser currentUser] image:imageFile block:^(PFObject *result, NSError *error) {
        if (self)
        {
            scanDone++;
            NSLog(@"PARSE result %@",result);
            NSLog(@"PARSE error %@",error);
            [_iLabel setText:@"CF"];

        }
    }];
}

//modify FUNCTION
- (void)modify:(PFUser *)user image:(PFFile *)image block:(PFIdResultBlock)block
{
    [PFCloud callFunction:@"modify" withParameters:@{@"user": PARSE_POINTER_USER(user), @"image_src": image}];
    modifyDone = YES;
}

Sorry if i'm not clear i'm not english.

Thank you

EDIT2 : I have try replace

[self majLabel];

by

[self performSelectorOnMainThread:@selector(majLabel) withObject:nil waitUntilDone:NO];

but the method "majLabel" is called once the for loop is finished... And it does exactly the same with :

        dispatch_async(dispatch_get_main_queue(), ^{
            [self majLabel];
        });

:'(

Console log for 2 pictures:

2014-09-30 10:48:20.784 MyApp[12934:2669263] Scan i=0 sur 1
2014-09-30 10:48:20.802 MyApp[12934:2669263] id : 20140927140500, status : 0
2014-09-30 10:48:21.078 MyApp[12934:2669263] Image size 500.000000x375.000000
2014-09-30 10:48:21.174 MyApp[12934:2669263] (img0) STEP 1 OK (création image)
2014-09-30 10:48:21.174 MyApp[12934:2669443] Thread save image started
2014-09-30 10:48:27.082 MyApp[12934:2669263] (img0) STEP 2 OK (upload image), modify en cour...
2014-09-30 10:48:27.082 MyApp[12934:2669489] Thread modify image started
2014-09-30 10:48:39.481 MyApp[12934:2669263] (img0) Comparaison img terminé
2014-09-30 10:48:39.481 MyApp[12934:2669263] Scan i=1 sur 1
2014-09-30 10:48:39.500 MyApp[12934:2669263] id : 20140930103437, status : 0
2014-09-30 10:48:39.769 MyApp[12934:2669263] Image size 500.000000x375.000000
2014-09-30 10:48:39.795 MyApp[12934:2669263] (img1) STEP 1 OK (création image)
2014-09-30 10:48:39.796 MyApp[12934:2669554] Thread save image started
2014-09-30 10:48:45.505 MyApp[12934:2669263] (img1) STEP 2 OK (upload image), modify en cour...
2014-09-30 10:48:45.505 MyApp[12934:2669592] Thread modify image started
2014-09-30 10:48:45.643 MyApp[12934:2669263] (img1) Comparaison img terminé
2014-09-30 10:48:45.737 MyApp[12934:2669263] UPDATE LABEL
2014-09-30 10:48:45.738 MyApp[12934:2669263] UPDATE LABEL
Community
  • 1
  • 1
Romain
  • 1
  • 2
  • 1
    You can change UI elements only in the main thread. So when you need to "update" it, do it in the main thread. – Larme Sep 27 '14 at 14:53
  • how i can do ? i have try this http://stackoverflow.com/a/5042521/4086180 but it don't work, or I make a mistake – Romain Sep 29 '14 at 13:58
  • http://stackoverflow.com/questions/5606145/objective-c-calling-a-method-on-the-main-thread ? – Larme Sep 29 '14 at 14:03
  • Thank you Larme but it don't work with my code i have updated my post – Romain Sep 30 '14 at 08:25

1 Answers1

0

The solution was just to execute all my "startButton" function in a thread and update UI in another.

- (IBAction)startButton:(id)sender {
    NSThread* threadSync = [[NSThread alloc] initWithTarget:self
                                                 selector:@selector(theSync)
                                                   object:nil];
    [threadSync start];
}

- (void)theSync{
    //...
}
Romain
  • 1
  • 2