1

I am developing an app in which I have picked 10 images from iOS gallery and then generate QRCode of all the images and then save everything in document directory using background thread but the problem is when I change the tab bar means to say after processing start when I move to some another tab bar view then background thread stop and I only get the 3 or 4 stored images. I have used different different background function to achive this like I have used NSOperationQueue also I made separate class then tried to save but do not succeeded. Code I have used:

 - (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info
    {
       NSLog(@"%@",info);
        [self dismissViewControllerAnimated:YES completion:nil];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

         [self saveallD:info];

            dispatch_async(dispatch_get_main_queue(), ^{

            });
        });
    }

    -(void)saveallD:(NSArray*)info
    {
        // int i=0;
        for (NSDictionary *dict in info)
        {
            if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypePhoto)
            {
                // i++;

                if ([dict objectForKey:UIImagePickerControllerOriginalImage])
                {
                    UIImage* chosenImage=[dict objectForKey:UIImagePickerControllerOriginalImage];

                    NSData *imageData = UIImagePNGRepresentation(chosenImage);

                    CGFloat scale= (100*1024)/(CGFloat)[imageData length]; // For 100KB.

                    UIImage *small_image=[UIImage imageWithCGImage:chosenImage.CGImage scale:scale orientation:chosenImage.imageOrientation];

                    NSData *imagefinaldata = UIImageJPEGRepresentation(small_image, scale*1.00);

                    //UIImage *imgCompressed = [self compressImage:chosenImage];

                    //NSData *imagefinaldata = UIImagePNGRepresentation(imgCompressed);

                    BOOL qrcodedetected = NO;

                    [[NSUserDefaults standardUserDefaults] setObject:imagefinaldata forKey:@"imagesaved"];

                    // QRCode detector
                    NSDictionary *detectorOptions = @{ CIDetectorAccuracy : CIDetectorAccuracyHigh };
                    CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:detectorOptions];
                    NSArray *features = [faceDetector featuresInImage:chosenImage.CIImage];
                    CIQRCodeFeature *faceFeature;
                    for(faceFeature in features)
                    {
                        qrcodedetected = YES;
                        self.decodedstr = [NSString stringWithFormat:@"%@",faceFeature.messageString];
                        break;
                    }

                    if (!qrcodedetected)
                    {

                        int timestamp = [[NSDate date] timeIntervalSince1970];

                        NSString*selectedFolder=[[NSUserDefaults standardUserDefaults] valueForKey:@"SelectedFolder"];

                        if ([selectedFolder isEqualToString:@""] || [selectedFolder isKindOfClass:[NSNull class]] || selectedFolder.length==0 )
                        {
                            selectedFolder=@"Default";
                        }

                        //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 2), ^{
                            // time-consuming task

                        NSLog(@"basepath..%@",[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]);

                        NSString *stringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",selectedFolder]];

                        //NSString *QRstringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:@"QRimages"];


                        if ([[NSFileManager defaultManager] fileExistsAtPath:stringPath])
                        {
                            // [imagefinaldata writeToFile:savedImagePath atomically:NO];
                            //                     stringPath = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d",timestamp]];

                            NSString *stringPath2 = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d",timestamp]];
                            NSString *savedImagePath = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.png",timestamp]];

                            [self writeImageToFile:stringPath2 :savedImagePath :imagefinaldata];

                            NSString *savedAudioPath = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.m4a",timestamp]];

                            //NSData*recordedAudioData=[NSData dataWithContentsOfURL:_recorder.url];

                            if ([autoRecordingCheck isEqualToString:@"ON"])
                            {
                            [self writeAudioToFile:stringPath2 :savedAudioPath];
                            }


                        }


                        else
                        {
                            [[NSFileManager defaultManager]createDirectoryAtPath:stringPath withIntermediateDirectories:NO attributes:nil error:nil];

                            NSString *stringPath2 = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d",timestamp]];
                            NSString *savedImagePath = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.png",timestamp]];

                            [self writeImageToFile:stringPath2 :savedImagePath :imagefinaldata];

                            NSString *savedAudioPath = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.m4a",timestamp]];

                            //NSData*recordedAudioData=[NSData dataWithContentsOfURL:_recorder.url];

                            if ([autoRecordingCheck isEqualToString:@"ON"])
                            {
                            [self writeAudioToFile:stringPath2 :savedAudioPath];
                            }
                            //  [imagefinaldata writeToFile:savedImagePath atomically:NO];

                        }



                        NSString *savedImagePath = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.png",timestamp]];

                        CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
                        [filter setDefaults];

                        NSData *data = [savedImagePath dataUsingEncoding:NSUTF8StringEncoding];
                        [filter setValue:data forKey:@"inputMessage"];

                        CIImage *outputImage = [filter outputImage];

                        CIContext *context = [CIContext contextWithOptions:nil];
                        CGImageRef cgImage = [context createCGImage:outputImage
                                                           fromRect:[outputImage extent]];

                        UIImage *image = [UIImage imageWithCGImage:cgImage
                                                             scale:1.0
                                                       orientation:UIImageOrientationUp];

                        // Resize without interpolating
                        UIImage *resized = [self resizeImage:image
                                                 withQuality:kCGInterpolationNone
                                                        rate:5.0];

                        NSData* QRdata = UIImagePNGRepresentation(resized);

                        NSString *stringPath2 = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d",timestamp]];
                        NSString *savedImagePath2 = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"QR%d.png",timestamp]];

                        [self writeQRToFile:stringPath2 :savedImagePath2 :QRdata];

                        // [self performSegueWithIdentifier:@"addfilters" sender:nil];

    //                        dispatch_async(dispatch_get_main_queue(), ^{
    //                            [SVProgressHUD dismiss];
    //                        });
    //                        
    //                    });
                    }

                    else
                    {
                        [self galleryalert];
                    }

                }
            }
            else
            {
                NSLog(@"UIImagePickerControllerReferenceURL = %@", dict);
            }
        }

If anybody have any type of solution then please let me know. It would be appreciated. Thanks in advance!

Vishal
  • 8,246
  • 6
  • 37
  • 52

1 Answers1

0

Here is the code I was talking about. Make changes as per your need.

BackgroundOperation.h

@protocol BackgroundOperationDelegate <NSObject>

-(void)operationCompleted;
-(void)operationInterrupted;


@end


@interface BackgroundOperation : NSObject


@property (nonatomic, weak) id<BackgroundOperationDelegate> delegate;

+(BackgroundOperation*)sharedInstance;

-(void)saveallD:(NSArray*)info;

@end

BackgroundOperation.m

#import "BackgroundOperation.h"

@implementation BackgroundOperation

static BackgroundOperation *_sharedInstance = nil;

+(BackgroundOperation*)sharedInstance{

    if(_sharedInstance == nil){
        _sharedInstance = [[BackgroundOperation alloc] init];
    }
    return _sharedInstance;
}


- (id)init {

    if(self = [super init]) {

    }

    return self;
}



-(void)saveallD:(NSArray*)infoArray
{

     int i=0;
    NSArray *info = [NSArray arrayWithArray:infoArray];
    for (NSDictionary *dict in info)
    {
        if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypePhoto)
        {
             i++;

            if ([dict objectForKey:UIImagePickerControllerOriginalImage])
            {
                UIImage* chosenImage=[dict objectForKey:UIImagePickerControllerOriginalImage];

                NSData *imageData = UIImagePNGRepresentation(chosenImage);

                CGFloat scale= (100*1024)/(CGFloat)[imageData length]; // For 100KB.

                UIImage *small_image=[UIImage imageWithCGImage:chosenImage.CGImage scale:scale orientation:chosenImage.imageOrientation];

                NSData *imagefinaldata = UIImageJPEGRepresentation(small_image, scale*1.00);

                //UIImage *imgCompressed = [self compressImage:chosenImage];

                //NSData *imagefinaldata = UIImagePNGRepresentation(imgCompressed);

                BOOL qrcodedetected = NO;

                [[NSUserDefaults standardUserDefaults] setObject:imagefinaldata forKey:@"imagesaved"];

                // QRCode detector
                NSDictionary *detectorOptions = @{ CIDetectorAccuracy : CIDetectorAccuracyHigh };
                CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:detectorOptions];
                NSArray *features = [faceDetector featuresInImage:chosenImage.CIImage];
                CIQRCodeFeature *faceFeature;
                for(faceFeature in features)
                {
                    qrcodedetected = YES;
                    self.decodedstr = [NSString stringWithFormat:@"%@",faceFeature.messageString];
                    break;
                }

                if (!qrcodedetected)
                {

                    int timestamp = [[NSDate date] timeIntervalSince1970];

                    NSString*selectedFolder=[[NSUserDefaults standardUserDefaults] valueForKey:@"SelectedFolder"];

                    if ([selectedFolder isEqualToString:@""] || [selectedFolder isKindOfClass:[NSNull class]] || selectedFolder.length==0 )
                    {
                        selectedFolder=@"Default";
                    }

                    //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 2), ^{
                    // time-consuming task

                    NSLog(@"basepath..%@",[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]);

                    NSString *stringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",selectedFolder]];

                    //NSString *QRstringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:@"QRimages"];


                    if ([[NSFileManager defaultManager] fileExistsAtPath:stringPath])
                    {
                        // [imagefinaldata writeToFile:savedImagePath atomically:NO];
                        //                     stringPath = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d",timestamp]];

                        NSString *stringPath2 = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d",timestamp]];
                        NSString *savedImagePath = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.png",timestamp]];

                        [self writeImageToFile:stringPath2 :savedImagePath :imagefinaldata];

                        NSString *savedAudioPath = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.m4a",timestamp]];

                        //NSData*recordedAudioData=[NSData dataWithContentsOfURL:_recorder.url];

                        if ([autoRecordingCheck isEqualToString:@"ON"])
                        {
                            [self writeAudioToFile:stringPath2 :savedAudioPath];
                        }


                    }


                    else
                    {
                        [[NSFileManager defaultManager]createDirectoryAtPath:stringPath withIntermediateDirectories:NO attributes:nil error:nil];

                        NSString *stringPath2 = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d",timestamp]];
                        NSString *savedImagePath = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.png",timestamp]];

                        [self writeImageToFile:stringPath2 :savedImagePath :imagefinaldata];

                        NSString *savedAudioPath = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.m4a",timestamp]];

                        //NSData*recordedAudioData=[NSData dataWithContentsOfURL:_recorder.url];

                        if ([autoRecordingCheck isEqualToString:@"ON"])
                        {
                            [self writeAudioToFile:stringPath2 :savedAudioPath];
                        }
                        //  [imagefinaldata writeToFile:savedImagePath atomically:NO];

                    }



                    NSString *savedImagePath = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.png",timestamp]];

                    CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
                    [filter setDefaults];

                    NSData *data = [savedImagePath dataUsingEncoding:NSUTF8StringEncoding];
                    [filter setValue:data forKey:@"inputMessage"];

                    CIImage *outputImage = [filter outputImage];

                    CIContext *context = [CIContext contextWithOptions:nil];
                    CGImageRef cgImage = [context createCGImage:outputImage
                                                       fromRect:[outputImage extent]];

                    UIImage *image = [UIImage imageWithCGImage:cgImage
                                                         scale:1.0
                                                   orientation:UIImageOrientationUp];

                    // Resize without interpolating
                    UIImage *resized = [self resizeImage:image
                                             withQuality:kCGInterpolationNone
                                                    rate:5.0];

                    NSData* QRdata = UIImagePNGRepresentation(resized);

                    NSString *stringPath2 = [stringPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%d",timestamp]];
                    NSString *savedImagePath2 = [stringPath2 stringByAppendingPathComponent:[NSString stringWithFormat:@"QR%d.png",timestamp]];

                    [self writeQRToFile:stringPath2 :savedImagePath2 :QRdata];

                    // [self performSegueWithIdentifier:@"addfilters" sender:nil];

                    //                        dispatch_async(dispatch_get_main_queue(), ^{
                    //                            [SVProgressHUD dismiss];
                    //                        });
                    //                        
                    //                    });
                }

                else
                {
                    [self galleryalert];
                }

            }
        }
        else
        {
            NSLog(@"UIImagePickerControllerReferenceURL = %@", dict);

        }

    }
    if(i+1==info.count)
    {
        [self.delegate operationCompleted];
    }
    else
    {
        [self.delegate operationInterrupted];
    }
}

@end

You can make call like below in your viewcontroller

- (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info
 {
    NSLog(@"%@",info);
    [self dismissViewControllerAnimated:YES completion:nil];

    [[BackgroundOperation sharedInstance] setDelegate:self];
    [[BackgroundOperation sharedInstance] saveallD:info];



 }

Make sure you override BackgroundOperationDelegate methods in your view controller to get callbacks once that task is completed

Sanniv
  • 1,892
  • 1
  • 17
  • 21
  • I have tried with your suggestion but it still save 4 or 5 images out of 10. Thanks for your effort. – Vishal Aug 22 '17 at 04:44
  • then its not the problem of changing tab bar (i.e. process interruption) otherwise the problem would have gone by this solution. This must be the problem with image data which is failing somewhere after 4-5 images. try not to save image data into NSUserDefaults.. – Sanniv Aug 24 '17 at 11:43