NSInvocationOperation with bad access crash - objective-c

I got a big problem with NSInvocationOperation. When I run on my iPod 4, firmware 5.0.1, it's OK. But on my iPhone 4, iOS 4.1, it crashed. This is my code:
CustomAnnotation *annotation = [[[ModelManager defaultModelManager] getAnnotationDictionaryInMemory] objectForKey:joltId];
if (annotation == nil)
annotation = [[[ModelManager defaultModelManager] getAnnotationDictionaryInMemory] annotationWithInstagramId:eID];
if (annotation == nil)
continue;
//THIS ONE CRASH ON IPHONE 4 OS 4.1
NSDictionary *param = [[NSDictionary alloc] initWithObjectsAndKeys: #"aKey", #"aValue", nil];
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:annotation selector:#selector(updateAnnotation:) object:param];
[_queue addOperation:op];
[op autorelease];
updateAnnotation function was defined in CustomAnnotation class:
- (void)updateAnnotation:(id)sender {
//NSLog(#"UPDATE ANNOTATION ID: %#", self.annoID);
NSDictionary *senderDic = (NSDictionary *)sender;
UzooltAppDelegate* appDelegate = (UzooltAppDelegate*) [UIApplication sharedApplication].delegate;
if ([senderDic objectForKey:#"nb_rejolt"] != nil) {
NSInteger new_nb_rejolts = [[senderDic objectForKey:#"nb_rejolt"] intValue];
//if (new_nb_rejolts != rejolts) {
//NSLog(#"update nb rejolts: %d", new_nb_rejolts);
if (self.rejolts != new_nb_rejolts) {
self.rejolts = new_nb_rejolts;
//if (self.isGrouped)
// [self.masterAnnotation.annotationView performSelectorOnMainThread:#selector(updateAnnotationViewWithRejolts:) withObject:[NSString stringWithFormat:#"%d", rejolts] waitUntilDone:NO];
//else
if ([senderDic objectForKey:#"rejolt_fbid"] != nil) {
NSString *fbRejoltsString = [senderDic objectForKey:#"rejolt_fbid"];
self.fbRejolts = [[fbRejoltsString componentsSeparatedByString:#","] mutableCopy];
[self.fbRejolts removeLastObject];
[self updateNumberOfRejoltsFromFBFrds];
}
[self.annotationView performSelectorOnMainThread:#selector(updateAnnotationViewWithRejolts:) withObject:[NSString stringWithFormat:#"%d", rejolts] waitUntilDone:NO];
}
if (self.isGrouped) {
if (self.masterAnnotation.isShowingRadius == NO && appDelegate.uMainViewController.isInGroup == NO && ( new_nb_rejolts > self.masterAnnotation.rejolts || (new_nb_rejolts == self.masterAnnotation.rejolts && self.getAge < self.masterAnnotation.getAge))) {
[self.masterAnnotation removeFromGroupedAnnotations:self];
self.annotationView.hidden = NO;
[self.annotationView performSelectorOnMainThread:#selector(showWithAlpha:) withObject:[NSNumber numberWithFloat:annotationAlpha] waitUntilDone:NO];
[[NSNotificationCenter defaultCenter] postNotificationName:#"need_group_annotations" object:nil];
}
}
//}
}
if ([senderDic objectForKey:#"lifetime"] != nil) {
float new_lifetime = [[senderDic objectForKey:#"lifetime"] floatValue]*3600;
//NSLog(#"new lifetime: %.f", new_lifetime);
if (new_lifetime != lifetime) {
//NSLog(#"update lifetime");
self.lifetime = new_lifetime;
}
}
[self updateViewAlpha];
if ([senderDic objectForKey:#"radius"] != nil) {
float new_radius = [[senderDic objectForKey:#"radius"] floatValue];
if (new_radius != radius) {
//NSLog(#"update lifetime");
self.radius = new_radius;
}
}
/*
if ([appDelegate.uMainViewController isMaximumZoomIn])
[[self annotationView] performSelectorOnMainThread:#selector(setGroupNumberIndicatorVisible:) withObject:[NSNumber numberWithBool:YES] waitUntilDone:NO];
else
[[self annotationView] performSelectorOnMainThread:#selector(setGroupNumberIndicatorVisible:) withObject:[NSNumber numberWithBool:NO] waitUntilDone:NO];
*/
if (isSelected == YES && isShowingRadius == NO ) {
//NSLog(#"update details");
[self performSelectorOnMainThread:#selector(updateDetailsView) withObject:nil waitUntilDone:NO];
UzooltAppDelegate* appDelegate = (UzooltAppDelegate*) [UIApplication sharedApplication].delegate;
if (isGrouped == YES && appDelegate.uMainViewController.isInGroup) {
NSLog(#"grouped jolt rejolted");
[self performSelectorOnMainThread:#selector(updateInGroupAnnotationView) withObject:nil waitUntilDone:NO];
}
}
}
I don't know where it wrong? Please help me. Thanks all !!!

Try running with NSZombies enabled. It should at least give you a hint as to what object you are trying to access after it has been deallocated.
NSZombies enabled, debug information

Related

Record video via AVFoundation in iOS

I try to create an application that records video and takes images at receiving a message via sockets.
What I do not arrive to do is video recording using AVFoundation.
is that because of the fact that I use a single session ?
Here is my code :
#import "ViewController.h"
#import "Parser.h"
#import "DeviceConfig.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// z-index
_vImage.layer.zPosition = 1;
_toggle.layer.zPosition = 1;
recording = NO;
[self initNetworkCommunication];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) initNetworkCommunication {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"192.168.0.103", 8080, &readStream, &writeStream);
input = (__bridge NSInputStream*) readStream;
output = (__bridge NSOutputStream*) writeStream;
[input setDelegate: self];
[output setDelegate: self];
[input scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[output scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[input open];
[output open];
}
- (void) sendMessage : (NSString*) message {
NSString *response = [NSString stringWithFormat:#"iam:%#", message];
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[output write:[data bytes] maxLength:[data length]];
}
- (void) stream : (NSStream*) theStream handleEvent:(NSStreamEvent) streamEvent {
switch(streamEvent) {
case NSStreamEventOpenCompleted:
[self openCamera];
break;
case NSStreamEventHasBytesAvailable:
NSLog(#"kayn");
if(theStream == input) {
uint8_t buffer[1024];
int length;
while([input hasBytesAvailable]) {
length = [input read:buffer maxLength:sizeof(buffer)];
if(length > 0) {
NSString* outputString = [[NSString alloc] initWithBytes:buffer length:length encoding:NSASCIIStringEncoding];
// To split different messages sended in buffer via Socket (in one message)
NSArray *options = [[outputString substringToIndex:[outputString length] - 1] componentsSeparatedByString:#":"];
NSLog(#"%#", options);
if(outputString != nil) {
if([options[1] isEqualToString:#"TAKE_PIC"]) {
[self takePic];
}else if([options[1] isEqualToString:#"PARAMS"]) {
Parser* parser = [[Parser alloc] initWithXMLData: options[2]];
[self changeCameraConfig:[parser getCameraOptions]];
}else if([options[1] isEqualToString:#"REC_VIDEO"]) {
[self recordVideo];
}else{
[self showMessage:#"Unknow order, please contact the administrator."];
}
}
}
}
}
break;
default:
NSLog(#"Unknown event");
}
}
- (void) showMessage : (NSString*) msg {
UIAlertView *helloWorldAlert = [[UIAlertView alloc]
initWithTitle:#"My First App" message:msg delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// Display the Hello World Message
[helloWorldAlert show];
}
- (void) openCamera {
session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetHigh;
AVCaptureVideoPreviewLayer* previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
previewLayer.frame = self.liveCameraView.bounds;
[self.liveCameraView.layer addSublayer:previewLayer];
device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
[session addInput:deviceInput];
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[_stillImageOutput setOutputSettings:outputSettings];
_videoOutput = [[AVCaptureMovieFileOutput alloc] init];
[session addOutput:_videoOutput];
[session addOutput:_stillImageOutput];
[session startRunning];
}
-(void) changeCameraConfig:(NSMutableDictionary *)config {
[device lockForConfiguration:nil];
DeviceConfig* conf;
for(id key in config) {
conf = [config objectForKey:key];
//[self showMessage:#"ok"];
// Config Torch
if([key isEqualToString:#"torch"]) {
if([[conf curValue] isEqualToString: #"on"]) {
[device setTorchMode:AVCaptureTorchModeOn];
}else{
[device setTorchMode:AVCaptureTorchModeOff];
}
}
// Config Focus
if([key isEqualToString:#"focus_mode"]) {
if([[conf curValue] isEqualToString: #"auto"]) {
[device setFocusMode: AVCaptureFocusModeAutoFocus];
}else if([[conf curValue] isEqualToString: #"continous_auto"]) {
[device setFocusMode: AVCaptureFocusModeContinuousAutoFocus];
}else{
[device setFocusMode: AVCaptureFocusModeLocked];
}
}
// Config Flash
if([key isEqualToString:#"flash"]) {
if([[conf curValue] isEqualToString: #"on"]) {
[device setFlashMode: AVCaptureFlashModeOn];
}else{
[device setFlashMode:AVCaptureFlashModeOff];
}
}
// Config Exposure
if([key isEqualToString:#"white_balance"]) {
if([[conf curValue] isEqualToString: #"auto"]) {
[device setExposureMode: AVCaptureExposureModeAutoExpose];
}else if([[conf curValue] isEqualToString: #"continous_auto"]) {
[device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
}else if([[conf curValue] isEqualToString: #"custom"]) {
[device setExposureMode:AVCaptureExposureModeCustom];
}else{
[device setExposureMode:AVCaptureExposureModeLocked];
}
}
// Config White balance
if([key isEqualToString:#"exposure_mode"]) {
if([[conf curValue] isEqualToString: #"auto"]) {
[device setExposureMode: AVCaptureExposureModeAutoExpose];
}else if([[conf curValue] isEqualToString: #"continous_auto"]) {
[device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
}else if([[conf curValue] isEqualToString: #"custom"]) {
[device setExposureMode:AVCaptureExposureModeCustom];
}else{
[device setExposureMode:AVCaptureExposureModeLocked];
}
}
}
[device unlockForConfiguration];
}
-(void) takePic {
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in _stillImageOutput.connections) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
videoConnection = connection;
break;
}
}
if (videoConnection) { break; }
}
NSLog(#"about to request a capture from: %#", _stillImageOutput);
[_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
{
CFDictionaryRef exifAttachments = CMGetAttachment( imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
if (exifAttachments)
{
// Do something with the attachments.
NSLog(#"attachements: %#", exifAttachments);
}
else
NSLog(#"no attachments");
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
UIImage *image = [[UIImage alloc] initWithData:imageData];
self.vImage.image = image;
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}];
}
- (AVCaptureDevice *) CameraWithPosition:(AVCaptureDevicePosition) Position
{
NSArray *Devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *Device in Devices)
{
if ([Device position] == Position)
{
return Device;
}
}
return nil;
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
- (IBAction)toggleCam:(id)sender {
AVCaptureDeviceInput* newDeviceInput;
NSError* error;
AVCaptureDevicePosition position = [[deviceInput device] position];
if(position == AVCaptureDevicePositionBack) {
newDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self CameraWithPosition:AVCaptureDevicePositionBack] error:&error];
}else{
newDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self CameraWithPosition:AVCaptureDevicePositionFront] error:&error];
}
if(error != nil) {
[session beginConfiguration]; //We can now change the inputs and output configuration. Use commitConfiguration to end
[session removeInput:deviceInput];
if ([session canAddInput:newDeviceInput])
{
[session addInput:newDeviceInput];
deviceInput = newDeviceInput;
}
else
{
[session addInput:deviceInput];
}
//Set the connection properties again
//[self CameraSetOutputProperties];
[session commitConfiguration];
}
}
-(void) recordVideo {
[self showMessage:#"recording .."];
// If we are not recording
if(!recording) {
recording = YES;
NSString* path = [[NSString alloc] initWithFormat:#"%#%#", NSTemporaryDirectory(), #"output_video.wav"];
NSURL* url = [[NSURL alloc] initFileURLWithPath:path];
NSFileManager* fileManager = [NSFileManager defaultManager];
if([fileManager fileExistsAtPath:path]) {
NSError* errorMsg;
if ([fileManager removeItemAtPath:path error:&errorMsg] == NO)
{
//Error - handle if requried
}
}
[_videoOutput startRecordingToOutputFileURL:url recordingDelegate:self];
}else{
recording = NO;
[_videoOutput stopRecording];
}
}
-(void) captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error {
BOOL recordedSuccessfully = YES;
if ([error code] != noErr) {
// A problem occurred: Find out if the recording was successful.
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value) {
recordedSuccessfully = [value boolValue];
}
}
if(recordedSuccessfully) {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if([ALAssetsLibrary authorizationStatus]) {
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputFileURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:outputFileURL
completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
}
}];
}
}else{
[self showMessage:#"Error"];
}
}
}
#end

Coding Multiple Leaderboards

I am making a game in which the player can achieve a positive high score or a negative low score depending on the choices they make. The high score has been working fine, but I'm having trouble with the low score.
-(void)authenticateLocalPlayer{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil) {
[self presentViewController:viewController animated:YES completion:nil];
}
else{
if ([GKLocalPlayer localPlayer].authenticated) {
_gameCenterEnabled = YES;
// Get the default leaderboard identifier.
[[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier, NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
else{
_leaderboardIdentifier = leaderboardIdentifier;
}
}];
}
else{
_gameCenterEnabled = NO;
}
}
};
}
-(void)reportScore{
GKScore *highscore = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
highscore.value = HighScoreNumber;
[GKScore reportScores:#[highscore] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
}];
-(void)showLeaderboardAndAchievements:(BOOL)shouldShowLeaderboard{
GKGameCenterViewController *gcViewController = [[GKGameCenterViewController alloc] init];
gcViewController.gameCenterDelegate = self;
if (shouldShowLeaderboard) {
gcViewController.viewState = GKGameCenterViewControllerStateLeaderboards;
gcViewController.leaderboardIdentifier = _leaderboardIdentifier;
}
else{
gcViewController.viewState = GKGameCenterViewControllerStateAchievements;
}
[self presentViewController:gcViewController animated:YES completion:nil];
}
You'll notice leaderboardidentifier, it is useful for reporting scores to the default leaderboard, but when I try to get it to work for two different ones, the code shuts down.
I've tried adding this to "Report Score":
GKScore *lowscore = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
lowscore.value = LowScoreNumber;
[GKScore reportScores:#[lowscore] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
}
}];
}
Then, I change the leaderboard identifiers to match itunesconnect, but I'm not sure how I need to change authenticateLocalPlayer and shouldShowLeaderboardandAchievements.
I have some experience with game center. I have two games on the App Store that have multiple leaderboards (Squared!! and Primes!).
Instead of having one method for each leaderboard I made one method for submitting scores. Here is that method:
-(void) submitScore:(int64_t)score Leaderboard: (NSString*)leaderboard
{
//1: Check if Game Center
// features are enabled
if (!_gameCenterFeaturesEnabled) {
return;
}
//2: Create a GKScore object
GKScore* gkScore =
[[GKScore alloc]
initWithLeaderboardIdentifier:leaderboard];
//3: Set the score value
gkScore.value = score;
//4: Send the score to Game Center
[gkScore reportScoreWithCompletionHandler:
^(NSError* error) {
[self setLastError:error];
BOOL success = (error == nil);
if ([_delegate
respondsToSelector:
#selector(onScoresSubmitted:)]) {
[_delegate onScoresSubmitted:success];
}
}];
}
When you want to submit your high scores all you have to do is add something like:
[[GCHelper sharedGameKitHelper] submitScore:myLowScore Leaderboard:TELS];
[[GCHelper sharedGameKitHelper] submitScore:myHighScore Leaderboard:TEHS];
GCHelper is the class that contains my submitScore:Leaderboard: method.
To view your leaderboards or achievements within your app try this:
- (void) presentLeaderboards {
GKGameCenterViewController* gameCenterController = [[GKGameCenterViewController alloc] init];
gameCenterController.viewState = GKGameCenterViewControllerStateLeaderboards;
gameCenterController.gameCenterDelegate = self;
[self presentViewController:gameCenterController animated:YES completion:nil];
}
- (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController*) gameCenterViewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void) presentAchievements {
GKGameCenterViewController* gameCenterController = [[GKGameCenterViewController alloc] init];
gameCenterController.viewState = GKGameCenterViewControllerStateAchievements;
gameCenterController.gameCenterDelegate = self;
I hope this answers your question!

Error:--FigCreateCGImageFromJPEG returned -12910. 49152 bytes

I am getting above error when I run program in device and it crashes,while it works fine in simulator,I am loading images using asset library and displaying in scroll view.
Here is my code::
-
(void)usingAssets{
x=0;
y=0;
w=320;
h=460;
void (^assetEnumerator)( ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) {
if(result != NULL) {
[app hideLoading];
[assets addObject:result];
NSLog(#"assets count: %i", assets.count);
NSString *assetType = [result valueForProperty:ALAssetPropertyType];
if ([assetType isEqualToString:ALAssetTypePhoto]) {
NSLog(#"Photo Asset");
[self success];
}
}
else {
[app hideLoading];
NSLog(#"AssetEnum: result nil or end of list");
}
};
void (^assetGroupEnumerator)( ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) {
if(group != nil) {
[group enumerateAssetsUsingBlock:assetEnumerator];
}
else {
NSLog(#"GroupEnum: group nil or end of list..");
}
[assets retain];
};
ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
usingBlock:assetGroupEnumerator
failureBlock: ^(NSError *error) {
NSLog(#"Failure: %#", error.description);
}];
// [library release];
isVisited=YES;
}
-(void)success{
dispatch_async(dispatch_get_main_queue(), ^(void){
for(int i=0;i<[assets count];i++){
asset = [assets objectAtIndex:i];
UIImage *images = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage] scale:1.0 orientation:[[asset valueForProperty:#"ALAssetPropertyOrientation"] intValue]];
imageview =[[UIImageView alloc]init];
imageview.frame=CGRectMake(x, y, w, h);
[imageview setImage:images];
[scrollview addSubview:imageview];
x = x + w ;
}
});
}
#pragma mark:----scroll view methods
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGPoint scrollOffset=scrollView.contentOffset;
///at any time, it will have only 3 pages loaded- previous, current and next
if(pageno < ((int)scrollOffset.x/320))
{
//unload
if(pageno>1)[self unloadPreviousPage:pageno-2];
//load the next page
[self loadScrollViewWithPage:((int)scrollOffset.x/320)+1];
}
else if(pageno > ((int)scrollOffset.x/320))
{
//unload
if(pageno<(kNumberOfPages-2))[self unloadPreviousPage:pageno+2];
//load back the previous page
[self loadScrollViewWithPage:((int)scrollOffset.x/320)-1];
}
pageno=scrollOffset.x/320;
}
-(void)unloadPreviousPage:(int)index
{
for(int i=index*4;i<(index+1)*4;i++)
{
[[scrollview viewWithTag:i+1] removeFromSuperview];
}
}
- (void)loadScrollViewWithPage:(int)page {
if (page < 0)
return;
if (page >= kNumberOfPages)
return;
pageno=page;
pgControl.currentPage=pageno-1;
if(isVisited==NO){
[NSThread detachNewThreadSelector:#selector(usingAssets) toTarget:self withObject:nil];
assets = [[NSMutableArray alloc] init];
for (ALAsset* a in assets){
NSLog(#"Item in asset");
}
}
}
Please correct me where I am going wrong.Also I wants to load images using lazy loading as first it iterates over all images and then display in scroll view so it takes more time when there are large number of images.
Also if there is any other link then please post it.
Thanks for your response in advance.

Can't play system sounds after capturing audio / video

I'm recoding audio/video using AVfoudnation. and I need to play a sounds, using system sounds, before I start capturing video/audio. This is working correctly the first time, but when I try to do it the second time, the system audi doesn't play. My guess is that something in the AVfoundation is not been released correctly.
In my application deletage, I have this code in the applicationDidFinishLaunching method:
VKRSAppSoundPlayer *aPlayer = [[VKRSAppSoundPlayer alloc] init];
[aPlayer addSoundWithFilename:#"sound1" andExtension:#"caf"];
self.appSoundPlayer = aPlayer;
[aPlayer release];
and also this method
- (void)playSound:(NSString *)sound
{
[appSoundPlayer playSound:sound];
}
As you can see I'm using VKRSAppSoundPlayer, which works great!
In a view, I have this code:
- (void) startSession
{
self.session = [[AVCaptureSession alloc] init];
[session beginConfiguration];
if([session canSetSessionPreset:AVCaptureSessionPreset640x480])
session.sessionPreset = AVCaptureSessionPresetMedium;
[session commitConfiguration];
CALayer *viewLayer = [videoPreviewView layer];
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.frame = viewLayer.bounds;
[viewLayer addSublayer:captureVideoPreviewLayer];
self.videoInput = [AVCaptureDeviceInput deviceInputWithDevice:[self frontFacingCameraIfAvailable] error:nil];
self.audioInput = [AVCaptureDeviceInput deviceInputWithDevice:[self audioDevice] error:nil];
if(videoInput){
self.videoOutput = [[AVCaptureMovieFileOutput alloc] init];
[session addOutput:videoOutput];
//[videoOutput release];
if([session canAddInput:videoInput]){
//[session beginConfiguration];
[session addInput:videoInput];
}
//[videoInput release];
[session removeInput:[self audioInput]];
if([session canAddInput:audioInput]){
[session addInput:audioInput];
}
//[audioInput release];
if([session canAddInput:audioInput])
[session addInput:audioInput];
NSLog(#"startRunning!");
[session startRunning];
[self startRecording];
if(![self recordsVideo])
[self showAlertWithTitle:#"Video Recording Unavailable" msg:#"This device can't record video."];
}
}
- (void) stopSession
{
[session stopRunning];
[session release];
}
- (AVCaptureDevice *)frontFacingCameraIfAvailable
{
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *captureDevice = nil;
Boolean cameraFound = false;
for (AVCaptureDevice *device in videoDevices)
{
NSLog(#"1 frontFacingCameraIfAvailable %d", device.position);
if (device.position == AVCaptureDevicePositionBack){
NSLog(#"1 frontFacingCameraIfAvailable FOUND");
captureDevice = device;
cameraFound = true;
break;
}
}
if(cameraFound == false){
for (AVCaptureDevice *device in videoDevices)
{
NSLog(#"2 frontFacingCameraIfAvailable %d", device.position);
if (device.position == AVCaptureDevicePositionFront){
NSLog(#"2 frontFacingCameraIfAvailable FOUND");
captureDevice = device;
break;
}
}
}
return captureDevice;
}
- (AVCaptureDevice *) audioDevice
{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
if ([devices count] > 0) {
return [devices objectAtIndex:0];
}
return nil;
}
- (void) startRecording
{
#if _Multitasking_
if ([[UIDevice currentDevice] isMultitaskingSupported]) {
[self setBackgroundRecordingID:[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{}]];
}
#endif
[videoOutput startRecordingToOutputFileURL:[self generatenewVideoPath]
recordingDelegate:self];
}
- (void) stopRecording
{
[videoOutput stopRecording];
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections error:(NSError *)error
{
NSFileManager *man = [[NSFileManager alloc] init];
NSDictionary *attrs = [man attributesOfItemAtPath: [outputFileURL path] error: NULL];
NSString *fileSize = [NSString stringWithFormat:#"%llu", [attrs fileSize]];
// close this screen
[self exitScreen];
}
-(BOOL)recordsVideo
{
AVCaptureConnection *videoConnection = [AVCamUtilities connectionWithMediaType:AVMediaTypeVideo
fromConnections:[videoOutput connections]];
return [videoConnection isActive];
}
-(BOOL)recordsAudio
{
AVCaptureConnection *audioConnection = [AVCamUtilities connectionWithMediaType:AVMediaTypeAudio
fromConnections:[videoOutput connections]];
return [audioConnection isActive];
}
If I do [videoInput release]; and [audioInput release]; I got a bad access error. that's why they are commented out. This may be part of the issue.
If I try to play the system sound n times, it work, but if I go first to the recording script, it wont work after that.
Any ideas?
The proper way to release AVCaptureSession is the following:
- (void) destroySession {
// Notify the view that the session will end
if ([delegate respondsToSelector:#selector(captureManagerSessionWillEnd:)]) {
[delegate captureManagerSessionWillEnd:self];
}
// remove the device inputs
[session removeInput:[self videoInput]];
[session removeInput:[self audioInput]];
// release
[session release];
// remove AVCamRecorder
[recorder release];
// Notify the view that the session has ended
if ([delegate respondsToSelector:#selector(captureManagerSessionEnded:)]) {
[delegate captureManagerSessionEnded:self];
}
}
If you're having some sort of release problems (bad access), I can recommend taking your code out of your current "messy" project to some other new project and debug the problem over there.
When I had similar problem, I just did that. I shared it on Github, you might find this project useful: AVCam-CameraReleaseTest

Delegates in Objective-C

I am trying to explore some codes in Objective-C. I came across an open source program - batch renamer. I was looking at its code and adding my own implementation. There is one thing in this code that I could not understand - I was hoping someone would be able to help me out.
The problem is that there is a renamer delegate "- (void)renamed" and I have no idea how it is called. So, I was wondering how does the program know when to call/use this delegate.
The code is as follows:
#import "ControllerMain.h"
static NSString *addFilesIdentifier = #"addFiles_item";
static NSString *removeFilesIdentifier = #"removeFiles_item";
static NSString *cleanAllIdentifier = #"cleanAll_item";
static NSString *updateUrl = #"http://www.hardboiled.it/software/update.xml";
#implementation ControllerMain
- (id)init
{
self = [super init];
//init some object
tableSource = [[NSMutableArray alloc] init];
updater = [[STUpdateChecker alloc] init];
renamer = [[STRenamer alloc] init];
//set some variables
withExt = NO;//for include the extension in the renaming, default NO
renamed = NO;//is YES after renaming preview
insoverappPosition = 0;
//set the notification for NSControlTextDidChangeNotification
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(textDidEndEditing:) name:#"NSControlTextDidChangeNotification" object:nil];
return self;
}
-(void)awakeFromNib
{
//set the delegates
[tabella setDelegate:self];
[tableSource setDelegate:self];
[renamer setDelegate:self];
[updater setDelegate:self];
//check if the software is updated
[updater checkUpdateWithUrl:[NSURL URLWithString:updateUrl]];
//drag' drop - set the dragged types
[tabella registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
//toolbar configuration
toolbar = [[NSToolbar alloc] initWithIdentifier:#"toolbar"];
[toolbar setDelegate:self];
//mainWindows properties
[mainWindow center];
[mainWindow setTitle:#"macXrenamer"];
[mainWindow setToolbar:toolbar];
//set the extension checkbox
[extSwitch setState:0];
//Set the custom cell imageAndTextCell
ImageAndTextCell *imageAndTextCell = nil;
NSTableColumn *tableColumn = nil;
tableColumn = [tabella tableColumnWithIdentifier:#"original_name"];
imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease];
[imageAndTextCell setEditable: NO];
[tableColumn setDataCell:imageAndTextCell];
//
//initialize the window for empty table
[self tableSourceIsEmpty];
//release the toolbar
[toolbar release];
}
- (void)dealloc
{
//release all
[tabella unregisterDraggedTypes];
[tableSource release];
[renamer release];
[super dealloc];
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
//close the application
return YES;
}
/* ################### tableSource delegates #################################*/
- (void)tableSourceIsEmpty
{
if (KDEBUG)
NSLog(#"tablesource is empty");
[upper_lower setEnabled:NO];
[from setEditable:NO];
[to setEditable:NO];
[insertText setEditable:NO];
[insertAtPosition setEditable:NO];
[insertAtPosition setIntValue:0];
[renameButton setEnabled:NO];
[annullButton setEnabled:NO];
[searchField setEditable:NO];
[replaceField setEditable:NO];
}
- (void)tableSourceIsNotEmpty
{
if (KDEBUG)
NSLog(#"tablesource is not empty");
[upper_lower setEnabled:YES];
[from setEditable:YES];
[to setEditable:YES];
[insertText setEditable:YES];
[insertAtPosition setEditable:YES];
[searchField setEditable:YES];
[replaceField setEditable:YES];
}
-(void)tableSourceDidChange
{
NSString *countString = [NSString stringWithFormat:#"%d files",[tableSource count]];
[number_of_files setStringValue:countString];
}
/*####################end tableSource delegates###############################*/
/*######################renamer delegates#####################################*/
- (void)renamed
{
NSLog(#"renaming preview ok");
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
[insertAtPosition setTextColor:[NSColor blackColor]];
}else if([tabViewId isEqual:#"remove"])
{
[from setTextColor:[NSColor blackColor]];
[to setTextColor:[NSColor blackColor]];
}
renamed = YES;
[renameButton setEnabled:YES];
[annullButton setEnabled:YES];
}
- (void)notRenamed
{
renamed = NO;
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
[insertAtPosition setTextColor:[NSColor redColor]];
}else if([tabViewId isEqual:#"remove"])
{
[from setTextColor:[NSColor redColor]];
[to setTextColor:[NSColor redColor]];
}
NSLog(#"exception in preview delegate");
[renameButton setEnabled:NO];
}
/* ###################end renamer delegates ##################################*/
//make the file extension editable
-(IBAction)makeExtEditable:(id)sender
{
if (KDEBUG)
NSLog(#"makeExtEditable action");
if ([sender state] == 0) {
withExt = NO;
}else if ([sender state] == 1) {
withExt = YES;
}
}
//add files to the table
-(IBAction)addFiles:(id)sender
{
//start the progression bar
[progBar startAnimation:self];
int result;
NSOpenPanel *oPanel = [NSOpenPanel openPanel];
[oPanel setCanChooseFiles:YES];
[oPanel setAllowsMultipleSelection:YES];
[oPanel setResolvesAliases:NO];
result = [oPanel runModalForTypes:nil];
if (result == NSOKButton) {
NSArray *filesToOpen = [oPanel filenames];
[tableSource add:filesToOpen];
[tabella reloadData];
}
//stop the progression bar
[progBar stopAnimation:self];
}
//remove files from the table
-(IBAction)removeFiles:(id)sender
{
if(KDEBUG)
NSLog(#"remove the selected file from the table");
[progBar startAnimation:self];
NSIndexSet *selected = [tabella selectedRowIndexes];
[tableSource removeAtIndexes:selected];
[tabella reloadData];
[progBar stopAnimation:self];
}
//remove all files from the table
-(IBAction)clearTable:(id)sender
{
if(KDEBUG)
NSLog(#"clear all table");
[progBar startAnimation:self];
[tableSource cleanAll];
[tabella reloadData];
[progBar stopAnimation:self];
}
//annull
-(IBAction)annulRenaming:(id)sender
{
[tableSource annull];
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
[insertAtPosition setTextColor:[NSColor blackColor]];
}else if([tabViewId isEqual:#"remove"])
{
[from setTextColor:[NSColor blackColor]];
[to setTextColor:[NSColor blackColor]];
}
renamed = NO;
[renameButton setEnabled:NO];
[tabella reloadData];
}
/*###########################log section######################################*/
-(IBAction)showLogWindows:(id)sender{
if ([logWindow isVisible]) {
[logWindow setIsVisible:FALSE];
}else {
[logWindow setIsVisible:TRUE];
}
}
-(void)addToLog:(NSString *)text
{
NSString *textLog = [text stringByAppendingString:#"\n\r"];
NSRange endRange;
endRange.location = [[logField textStorage] length];
endRange.length = 0;
[logField replaceCharactersInRange:endRange withString:textLog];
endRange.length = [textLog length];
[logField scrollRangeToVisible:endRange];
}
/*#######################end log section######################################*/
/*######################editing actions#######################################*/
-(IBAction)finalRenaming:(id)sender
{
if(KDEBUG)
NSLog(#"renaming button pressed");
//start the progression bar
[progBar startAnimation:self];
//count of the files really renamed
int countRenamed = 0;
//count of the renaming error
int errRenamed = 0;
//the result of rename()
int renameResult;
//the enumerator and the obj
NSEnumerator *en = [tableSource objectEnumerator];
id row;
if(renamed)
{
while(row = [en nextObject])
{
renameResult = rename([[row objectAtIndex:0] fileSystemRepresentation], [[row objectAtIndex:1] fileSystemRepresentation]);
if(renameResult == 0){
NSString *textLog = [NSString stringWithFormat:#"%# renamed with\n %#", [row objectAtIndex:0],[row objectAtIndex:1]];
NSLog(textLog);
[self addToLog:textLog];
countRenamed++;
}else {
NSString *textLog =[NSString stringWithFormat: #"Error in file renaming %#", [row objectAtIndex:0]];
NSLog(textLog);
[self addToLog:textLog];
errRenamed++;
}
}
if(errRenamed >0){
//open the panel alert
int result;
result = NSRunAlertPanel(#"Renaming error. Please check the log", #"Error!", #"Ok", NULL, NULL);
}
//print the result of renaming
[notiField setStringValue:[NSString stringWithFormat:#"renamed %d/%d files, %d errors", countRenamed,[tableSource count],errRenamed]];
//
[tableSource reinitialize];
[tabella reloadData];
[renameButton setEnabled:NO];
[annullButton setEnabled:NO];
[progBar stopAnimation:self];
}
}
- (void)textDidEndEditing:(NSNotification *)aNotification
{
[progBar startAnimation:self];
NSTabViewItem *tabItem;
tabItem = [tabView selectedTabViewItem];
id tabViewId = [tabItem identifier];
if ([tabViewId isEqual:#"insert"]) {
if(KDEBUG)
NSLog(#"insert selected");
if(insoverappPosition == 1)
{
if(KDEBUG)
NSLog(#"overwrite selected");
tableSource = [renamer overwriteChar:tableSource insertText:[insertText stringValue] position:[insertAtPosition intValue] withExt:withExt];
}else if(insoverappPosition == 0){
if(KDEBUG)
NSLog(#"insert selected");
tableSource = [renamer insertChar:tableSource insertText:[insertText stringValue] position:[insertAtPosition intValue] withExt:withExt];
}else if(insoverappPosition == 2){
if(KDEBUG)
NSLog(#"append selected");
tableSource = [renamer appendChar:tableSource appendText:[insertText stringValue] withExt:withExt];
}
}else if ([tabViewId isEqual:#"remove"]) {
if(KDEBUG)
NSLog(#"remove selected");
tableSource = [renamer removeChar:tableSource from:[from intValue] to:[to intValue] withExt:withExt];
}else if([tabViewId isEqual:#"search"]){
if(KDEBUG)
NSLog(#"search selected");
tableSource = [renamer searchAndReplace:tableSource string:[searchField stringValue] withString:[replaceField stringValue] withExt:withExt];
}
[progBar stopAnimation:self];
}
-(IBAction)upLowerCellClicked:(id)sender
{
NSCell* cell;
cell = [upper_lower selectedCell];
int tag = [cell tag];
if (tag == 0) {
if(KDEBUG)
NSLog(#"lowercase selected");
tableSource = [renamer makeLowerCase:tableSource withExt:withExt];
[renameButton setEnabled:YES];
[annullButton setEnabled:YES];
[tabella reloadData];
}
else if(tag == 1){
if(KDEBUG)
NSLog(#"uppercase selected");
tableSource = [renamer makeUpperCase:tableSource withExt:withExt];
[renameButton setEnabled:YES];
[annullButton setEnabled:YES];
[tabella reloadData];
}
}
-(IBAction)insertOverwriteClicked:(id)sender
{
if(KDEBUG)
NSLog(#"insertOverwriteClicked");
NSCell* cell;
cell = [insert_overwrite selectedCell];
int tag = [cell tag];
if(tag == 0)
{
if(KDEBUG)
NSLog(#"insert");
[insertAtPosition setEnabled:YES];
insoverappPosition = 0;
}else if(tag==1){
if(KDEBUG)
NSLog(#"overwrite");
[insertAtPosition setEnabled:YES];
insoverappPosition = 1;
}else if (tag==2) {
if(KDEBUG)
NSLog(#"append");
[insertAtPosition setEnabled:NO];
insoverappPosition = 2;
}
}
/*################end editing actions#########################################*/
-(void)newUpdateIsOnline
{
NSLog(#"newUpdateIsOnline");
BOOL retval;
retval = (NSAlertDefaultReturn == NSRunAlertPanel(#"Update Available", #"Update now or later", #"Update", #"Cancel", nil, nil));
if(retval){
if(KDEBUG)
NSLog(#"update now");
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:#"http://www.hardboiled.it/software/rinominatore-upgrade.zip"]];
//to edit
//[[NSNotificationCenter defaultCenter] postNotificationName:#"openSheetNotification" object:self userInfo:nil];
}else {
if(KDEBUG)
NSLog(#"cancel the update");
}
//release the updater. now is useless
[updater release];
}
/*################nstableview delegates#######################################*/
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
return [tableSource count];
}
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
if ([[aTableColumn identifier] isEqualToString: #"original_name"]) {
id obj = [tableSource objectAtRow:rowIndex atIndex:0] ;
return [obj lastPathComponent];
//return theIcon;
}else if([[aTableColumn identifier] isEqualToString: #"new_name"]){
id obj = [tableSource objectAtRow:rowIndex atIndex:1] ;
return [obj lastPathComponent];
}
return nil;
}
- (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
{
if(cell_with_icon)
{
if ( [[aTableColumn identifier] isEqualToString:#"original_name"] ){
[((ImageAndTextCell*) cell) setImage:[tableSource objectAtRow:rowIndex atIndex:2]];
}
}
}
/* ###############end nstableview delegates #################################*/
/*############### nstoolbar delegates #######################################*/
- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
{
return [NSArray arrayWithObjects:addFilesIdentifier,
removeFilesIdentifier,cleanAllIdentifier,
NSToolbarFlexibleSpaceItemIdentifier,
NSToolbarSpaceItemIdentifier,
NSToolbarSeparatorItemIdentifier, nil];;
}
- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar
{
return [NSArray arrayWithObjects:addFilesIdentifier,
removeFilesIdentifier,NSToolbarFlexibleSpaceItemIdentifier,cleanAllIdentifier, nil];
}
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
NSToolbarItem *toolbarItem = nil;
if ([itemIdentifier isEqualTo:addFilesIdentifier]) {//button addfiles
toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[toolbarItem setLabel:#"Add"];
[toolbarItem setPaletteLabel:[toolbarItem label]];
[toolbarItem setToolTip:#"Add"];
[toolbarItem setImage:[NSImage imageNamed:#"add.icns"]];
[toolbarItem setTarget:self];
[toolbarItem setAction:#selector(addFiles:)];
}else if ([itemIdentifier isEqualTo:removeFilesIdentifier]) {//button remove files
toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[toolbarItem setLabel:#"Remove"];
[toolbarItem setPaletteLabel:[toolbarItem label]];
[toolbarItem setToolTip:#"Remove"];
[toolbarItem setImage:[NSImage imageNamed:#"remove.icns"]];
[toolbarItem setTarget:self];
[toolbarItem setAction:#selector(removeFiles:)];
}else if ([itemIdentifier isEqualTo:cleanAllIdentifier]) {//button clean
toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
[toolbarItem setLabel:#"Clean All"];
[toolbarItem setPaletteLabel:[toolbarItem label]];
[toolbarItem setToolTip:#"Clean the table"];
[toolbarItem setImage:[NSImage imageNamed:#"cleanAll.icns"]];
[toolbarItem setTarget:self];
[toolbarItem setAction:#selector(clearTable:)];
}
return [toolbarItem autorelease];
}
/*###############end nstoolbar delegates #####################################*/
/*################drag'n drop delegates #####################################*/
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard {
// Drag and drop support
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
[pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:self];
[pboard setData:data forType:NSFilenamesPboardType];
return YES;
}
- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op
{
// Add code here to validate the drop
if (KDEBUG)
NSLog(#"validate Drop");
return NSDragOperationEvery;
}
- (BOOL)tableView:(NSTableView*)tv acceptDrop:(id )info row:(int)row dropOperation:(NSTableViewDropOperation)op
{
if (KDEBUG)
NSLog(#"acceptDrop");
NSPasteboard *pboard = [info draggingPasteboard];
if ( [[pboard types] containsObject:NSFilenamesPboardType] ) {
NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
[tableSource add:files];
}
[tabella reloadData];
return YES;
}
/*################end drag'n drop delegates ##################################*/
#end
The delegate is the object, not the method. The ControllerMain object is set as some other object's delegate. When that other object sees the condition that tells it renaming has occurred (whatever that means), it executes something along the lines of [[self delegate] renamed], which calls the ControllerMain method.