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