2

I am developing an app where i handle NSTimer using NSInvocation as the code below. I am getting Sigbart error with the following code *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSInvocation invocationWithMethodSignature:]: method signature argument cannot be nil' *** First throw call stack

I am trying to identify this crash but couldn't get it. Could someone help me solving this?

Code:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveImageToPhotoAlbum) name:kImageCapturedSuccessfully object:nil];

    NSInvocation *myInvocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(capturePicture:)]];
    [myInvocation setSelector:@selector(capturePicture:)];
    [myInvocation setTarget:self];
    [myInvocation retainArguments];

    [NSTimer scheduledTimerWithTimeInterval:5.0 invocation:myInvocation repeats:NO];




   -(void) capturePicture :(id) sender
{
    NSLog(@"capTureAutoPicture:Scanning image at interval");

    // Get all cameras in the application and find the frontal camera.
    AVCaptureDevice *backCamera;
    NSArray *allCameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

    // Find the back camera.
    for ( int i = 0; i < allCameras.count; i++ ) {
        AVCaptureDevice *camera = [allCameras objectAtIndex:i];

        if ( camera.position == AVCaptureDevicePositionBack ) {
            backCamera = camera;
        }
    }

    // If we did not find the camera then do not take picture.
    if ( backCamera != nil ) {
        // Start the process of getting a picture.
        AVCaptureSession *session = [[AVCaptureSession alloc] init];

        // Setup instance of input with back camera and add to session.
        NSError *error;
        AVCaptureDeviceInput *input =
        [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error];

        if ( !error && [session canAddInput:input] ) {
            // Add frontal camera to this session.
            [session addInput:input];

            // We need to capture still image.
            AVCaptureStillImageOutput *output = [[AVCaptureStillImageOutput alloc] init];

            // Captured image. settings.
            [output setOutputSettings:
             [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey,nil]];

            if ( [session canAddOutput:output] ) 
            {

                [session addOutput:output];

                AVCaptureConnection *videoConnection = nil;
                for (AVCaptureConnection *connection in output.connections) {
                    for (AVCaptureInputPort *port in [connection inputPorts]) {
                        if ( [[port mediaType] isEqual:AVMediaTypeVideo] ) 
                        {
                            videoConnection = connection;
                            break;
                        }
                    }
                    if (videoConnection) 
                    { 
                        break; 
                    }
                }

                // Finally take the picture
                if ( videoConnection ) 
                {
                    [session startRunning];

                    [output captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) 
                     {
                         if (imageDataSampleBuffer != NULL) 
                         {
                             NSData *imageData = [AVCaptureStillImageOutput 
                                                  jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
                             UIImage *photo = [[UIImage alloc] initWithData:imageData];

                             //UIImageWriteToSavedPhotosAlbum(photo, nil, nil, nil);
                             [photo release];

                             [[NSNotificationCenter defaultCenter] postNotificationName:kImageCapturedSuccessfully object:nil];

                             [session stopRunning];

                         }

                     }];

                }
            }
            [output release];
        }
    }
}
- (void)saveImageToPhotoAlbum
{
    UIImageWriteToSavedPhotosAlbum([self stillImage], self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

    [self dismissModalViewControllerAnimated:YES];
}

Updated Code:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveImageToPhotoAlbum) name:kImageCapturedSuccessfully object:nil];

    /*NSInvocation *myInvocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(capTureAutoPicture)]];
    [myInvocation setSelector:@selector(capTureAutoPicture)];
    [myInvocation setTarget:self];
    [NSTimer scheduledTimerWithTimeInterval:5.0 invocation:myInvocation repeats:NO];*/

    [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(capTureAutoPicture:) userInfo:nil repeats:NO];
Getsy
  • 4,887
  • 16
  • 78
  • 139
  • Can you post code for `[self methodSignatureForSelector:@selector(capturePicture:)]`? It appears that that method is not returning what you think it is. – MishieMoo Jan 15 '13 at 19:30
  • I updated my code, i'm not using NSInvocation now in scheduledTimerWithTimeInterval, but the same crash is happening due to this line [[NSNotificationCenter defaultCenter] postNotificationName:kImageCapturedSuccessfully object:nil]; .. Any helps? – Getsy Jan 16 '13 at 05:11

2 Answers2

2

The exception thrown is pretty clear the argument cannot be nil.

The following is a working example of an NSInvocation :

NSMethodSignature *methodSignature = [[_filter class] instanceMethodSignatureForSelector:@selector()];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setTarget:_filter];
[invocation setSelector:selector];
[invocation setArgument:&value atIndex:2];
[invocation invoke];

I would also suggest you to have a look at answer to this question that explain really well how NSInvocation works

Community
  • 1
  • 1
oiledCode
  • 8,589
  • 6
  • 43
  • 59
  • I tried removing the entire NSInvocation code for scheduledTimerWithTimeInterval usage and used the scheduledTimerWithTimeInterval normally as earlier without NSInvocation, but still the same crash is coming, i don't understand why. Also i found, if i comment [[NSNotificationCenter defaultCenter] postNotificationName:kImageCapturedSuccessfully object:nil]; in block code, there is no crash but it used to move back to previous screen. – Getsy Jan 16 '13 at 04:56
  • I updated my code, i'm not using NSInvocation now in scheduledTimerWithTimeInterval, but the same crash is happening due to this line [[NSNotificationCenter defaultCenter] postNotificationName:kImageCapturedSuccessfully object:nil]; .. Any helps? – Getsy Jan 16 '13 at 05:11
0

I fixed it. Problem was, i didn't added "didFinishSavingWithError" but calling it. After adding this definition, it worked.

Getsy
  • 4,887
  • 16
  • 78
  • 139