I know this subject has been discussed several times, but I cannot figure out what is causing this error message. I've been stuck here for a couple weeks now and its driving me crazy. The first part of the method sets up a match for 2-4 players. Once a match is found, it tries to add 3 and 4 players within a certain limit. Right now, the limit is just set to 3 seconds, but I envision it being much larger once it is ready for release.
I know this is a memory error somewhere in the matchmakerViewController code. When I comment out the code changing the scene, I still get the error. Can you show me what I've done wrong and how to fix it?
-(void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)match
{
NSLog(#"IN matchmakerViewController!");
NSLog(#"Found a match!");
//startDate = [[NSDate date] retain];
//NSArray * playerIds1 = match.playerIDs;
//[marray_players addObject:playerIds1];
// Setup match
TXGameCenterManager *gameCenterManager = [TXGameCenterManager sharedTXGameCenterManager];
gameCenterManager.multiplayerMatch = match;
// The delegate of the match is HelloWorldLayer
gameCenterManager.multiplayerMatch.delegate = self;
AppDelegate * delegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
[delegate.viewController dismissModalViewControllerAnimated:NO];
GKMatchRequest * matchRequest = [[[GKMatchRequest alloc] init] autorelease];
NSLog(#"playerIDs count is %d",[match.playerIDs count] );
if( match.expectedPlayerCount==0 )
{
// Launching the game without waiting for connection change messages
NSLog(#"Begin game without waiting for match connection change messages");
// Determine the host, local or remote
NSArray * playerIds = match.playerIDs;
NSLog(#"Number of players: %d", [playerIds count]);
NSLog(#"ID of player: %#", [playerIds lastObject]);
NSLog(#"I got the player ids");
[GKPlayer loadPlayersForIdentifiers:playerIds withCompletionHandler:^(NSArray *players, NSError * error)
{
NSLog(#"Player 1 %#", [[players objectAtIndex:0] alias] );
// NSLog(#"Player 2 %#", [[players objectAtIndex:1] alias] );
if( !error)
{
NSLog(#"Local player: %#", [[GKLocalPlayer localPlayer] alias]);
NSLog(#"Remote player: %#", [[players lastObject] alias]);
NSLog(#"Remote player: %#", [[players lastObject] alias]);
//NSArray *nsarray_player2 = [marray_players objectAtIndex:1];
// remote1name= [[nsarray_player1 lastObject] alias];
int_totalremoteplayers=[match.playerIDs count];
boo_playersfound=true;
localName = [[GKLocalPlayer localPlayer] alias];
remoteName = [[players objectAtIndex:0] alias];
NSLog(#"Player 1 %#", [[players objectAtIndex:0] alias] );
// NSLog(#"Player 2 %#", [[players objectAtIndex:1] alias] );
//remote1name= [[nsarray_player1 lastObject] alias];
if ([match.playerIDs count]==1)
{
NSLog(#"IN [match.playerIDs count]==1");
remoteplayer1name= [[players objectAtIndex:0] alias];
[playernames addObject:remoteplayer1name];
[playernames addObject:localName];
NSArray *sortedArray;
sortedArray = [playernames sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)];
NSLog(#"Host: %#", [sortedArray objectAtIndex:0]);
NSLog(#"Player1: %#", [sortedArray objectAtIndex:1]);
hostName=[sortedArray objectAtIndex:0];
remoteplayer1name=[sortedArray objectAtIndex:1];
if ([hostName isEqualToString:localName])
{
[[TXGameCenterManager sharedTXGameCenterManager] setHost:YES];
}
}
if ([match.playerIDs count]==2)
{
NSLog(#"IN [match.playerIDs count]==2");
NSLog(#" [match.playerIDs count]==2 Player 1 %#", [[players objectAtIndex:0] alias] );
NSLog(#"[match.playerIDs count]==2 Player 2 %#", [[players objectAtIndex:1] alias] );
NSLog(#"[match.playerIDs count]==2 localName %#", localName );
remoteplayer1name= [[players objectAtIndex:0] alias];
remoteplayer2name= [[players objectAtIndex:1] alias];
[playernames addObject:remoteplayer1name];
[playernames addObject:remoteplayer2name];
[playernames addObject:localName];
NSLog(#"Players in playernames %d", [playernames count]);
NSArray *sortedArray;
sortedArray = [playernames sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)];
NSLog(#"Host: %#", [sortedArray objectAtIndex:0]);
NSLog(#"Player1: %#", [sortedArray objectAtIndex:1]);
NSLog(#"Player2: %#", [sortedArray objectAtIndex:2]);
hostName=[sortedArray objectAtIndex:0];
remoteplayer1name=[sortedArray objectAtIndex:1];
remoteplayer2name=[sortedArray objectAtIndex:2];
if ([hostName isEqualToString:localName])
{
[[TXGameCenterManager sharedTXGameCenterManager] setHost:YES];
}
NSLog(#"match.expectedPlayerCount = %d",match.expectedPlayerCount);
}
else if ([match.playerIDs count]==3)
{
remoteplayer1name= [[players objectAtIndex:0] alias];
remoteplayer2name= [[players objectAtIndex:1] alias];
remoteplayer3name= [[players objectAtIndex:2] alias];
[playernames addObject:remoteplayer1name];
[playernames addObject:remoteplayer2name];
[playernames addObject:remoteplayer3name];
[playernames addObject:localName];
NSArray *sortedArray;
sortedArray = [playernames sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)];
NSLog(#"Host: %#", [sortedArray objectAtIndex:0]);
NSLog(#"Player 1: %#", [sortedArray objectAtIndex:1]);
NSLog(#"Player 2: %#", [sortedArray objectAtIndex:2]);
NSLog(#"Player 3: %#", [sortedArray objectAtIndex:3]);
hostName=[sortedArray objectAtIndex:0];
remoteplayer1name=[sortedArray objectAtIndex:1];
remoteplayer2name=[sortedArray objectAtIndex:2];
remoteplayer3name=[sortedArray objectAtIndex:3];
if ([hostName isEqualToString:localName])
{
[[TXGameCenterManager sharedTXGameCenterManager] setHost:YES];
}
}
NSLog(#"Player names");
// TODO: Set the correct player names in the globals
player1 = localName;
player2 = [[NSUserDefaults standardUserDefaults] objectForKey:#"player2name"];
player3 = [[NSUserDefaults standardUserDefaults] objectForKey:#"player3name"];
player4 = [[NSUserDefaults standardUserDefaults] objectForKey:#"player4name"];
NSLog(#"Launch the game");
// Launch the game
int_team2tally=0;
NSLog(#"boo_startgame");
boo_startgame=true;
NSLog(#"go to the required scene");
//go to the required scene
}
else
{
NSLog(#"Error");
}
NSLog(#"StartMultiplayerGameTablehost");
//gameCenterManager.matchController.matchmakerDelegate = nil;
[self performSelector:#selector(StartMultiplayerGameTablehost) withObject:nil afterDelay:1.];
}
];
NSLog(#"No Error");
}
// Believe the error is somewhere in the following code.
if (boo_gamestarted!=true)
{
if (match.expectedPlayerCount==0)
{
//if([localName isEqualToString:hostName])
// {
boo_startgame=true;
if ([match.playerIDs count]==1)
{
matchRequest.minPlayers = 3;
matchRequest.maxPlayers = 4;
matchRequest.playersToInvite = nil;
[[GKMatchmaker sharedMatchmaker] addPlayersToMatch:match matchRequest:matchRequest completionHandler:^(NSError *error)
{
if (error)
{
NSLog(#"An error occurred during adding a player to match: %#", [error localizedDescription]);}
else if (match != nil)
{NSLog(#"A player has been added to the match");}
}];
}
else if ([match.playerIDs count]==2)
{
matchRequest.minPlayers = 4;
matchRequest.maxPlayers = 4;
matchRequest.playersToInvite = nil;
[[GKMatchmaker sharedMatchmaker] addPlayersToMatch:match matchRequest:matchRequest completionHandler:^(NSError *error)
{
if (error)
{
NSLog(#"An error occurred during adding a player to match: %#", [error localizedDescription]);}
else if (match != nil)
{NSLog(#"A player has been added to the match");}
}];
}
if ([match.playerIDs count]==3)
{
NSLog(#"Starting Game-589");
// [CCTimer timerWithTarget:self selector:#selector(StartMultiplayerGameTablehost) interval:10];
//[self performSelector:#selector(StartMultiplayerGameTablehost) withObject:nil afterDelay: 1.];
} // end if (match.expectedPlayerCount==0)
else if (boo_gamestarted==false)
{
NSLog(#"player count = %d",[match.playerIDs count]);
NSLog(#"Starting Game-597");
// [self performSelector:#selector(StartMultiplayerGameTablehost) withObject:nil afterDelay:1.];
}
//[CCTimer timerWithTarget:self selector:#selector(StartMultiplayerGameTablehost) interval:10];
// [self performSelector:#selector(StartMultiplayerGameTablehost) withObject:nil afterDelay:3.];
// }
//
else
{
boo_startgame=true;
matchRequest.minPlayers = 3;
matchRequest.maxPlayers = 4;
matchRequest.playersToInvite = nil;
[[GKMatchmaker sharedMatchmaker] addPlayersToMatch:match matchRequest:matchRequest completionHandler:^(NSError *error)
{
if (error)
{
NSLog(#"An error occurrred during adding a player to match: %#", [error localizedDescription]);}
else if (match != nil)
{NSLog(#"A player has been added to the match");}
}];
[self performSelector:#selector(StartMultiplayerGameTablehost) withObject:nil afterDelay:3.];
}
}
}
}
-(void)StartMultiplayerGameTablehost
{
boo_gamestarted=true;
[[CCDirector sharedDirector] replaceScene:[HelloWorldLayer node]];
}
-(void)dealloc
{
[super dealloc];
}
The end result is a message that looks like:
#0 0x32499468 in ___forwarding___ ()
#1 0x323f0f68 in __forwarding_prep_0___ ()
#2 0x31ffac5e in _Block_object_assign ()
#3 0x39614614 in __copy_helper_block_333 ()
#4 0x31ffa928 in _Block_copy_internal ()
#5 0x34a86694 in _dispatch_Block_copy ()
#6 0x34a8894e in dispatch_group_async$VARIANT$up ()
#7 0x39613c4e in -[GKConnectionInternal connectParticipantsWithConnectionData:withSessionInfo:] ()
#8 0x32c5e21c in -[GKMatch connectToPeersWithDictionaries:version:sessionToken:cdxTicket:] ()
#9 0x32c694b2 in __block_global_17 ()
#10 0x34a8711e in _dispatch_call_block_and_release ()
#11 0x34a864b6 in _dispatch_client_callout ()
#12 0x34a87dca in _dispatch_main_queue_callback_4CF$VARIANT$up ()
#13 0x3246af3a in __CFRunLoopRun ()
#14 0x323ddebc in CFRunLoopRunSpecific ()
#15 0x323ddd48 in CFRunLoopRunInMode ()
#16 0x3a1db2ea in GSEventRunModal ()
#17 0x39c992f8 in UIApplicationMain ()
#18 0x0009f370 in main ()
None of these are from my now code.
The answer ended up being that I needed to release
matchRequest.minPlayers = 3;
matchRequest.maxPlayers = 4;
Before re-defining their values.
Related
I have been following the How To Synchronize Core Data with a Web Service – Part 1 from RayWenderlinch.com I am trying to customize it to my application and have an issue with the actual downloading of the data from Parse using AFNetworking
The application should connect to parse, see the two classes "Club" and "IronSet" check and see if there are and new records (or on initial run, grab everything) and download only the newly added stuff.
Then it will save those records to core data, then delete the files from the Cache/JSONRecords/Club(or IronSet). It seems I am never actually grabbing the data from Parse, although it is connecting successfully, and does not throw an error until it goes to delete the the files from the Cache.
I am getting the "All operations completed" indicating the SyncEngine should be complete with the download in the downloadDataForRegisteredObjects
Error
2013-08-26 19:39:03.981 WGT Golf Calculator[3287:c07] All operations completed
2013-08-26 19:39:03.991 WGT Golf Calculator[3287:c07] Unable to delete JSON records at Club -- file://localhost/Users/**/Library/Application%20Support/iPhone%20Simulator/6.1/Applications/4B72F57E-264D-44F7-981D-3D921B0CC2A4/Library/Caches/JSONRecords/, reason Error Domain=NSCocoaErrorDomain Code=4 "The operation couldn’t be completed. (Cocoa error 4.)" UserInfo=0x75610f0 {NSUnderlyingError=0x75615e0 "The operation couldn’t be completed. No such file or directory", NSFilePath=/Users/**/Library/Application Support/iPhone Simulator/6.1/Applications/4B72F57E-264D-44F7-981D-3D921B0CC2A4/Library/Caches/JSONRecords/Club, NSUserStringVariant=(
Remove
)}
MLVAppDelegate.m
#import "MLVAppDelegate.h"
#import "MLVSyncEngine.h"
#import "Club.h"
#import "IronSet.h"
#implementation MLVAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[MLVSyncEngine sharedEngine] registerNSManagedObjectClassToSync:[Club class]];
[[MLVSyncEngine sharedEngine] registerNSManagedObjectClassToSync:[IronSet class]];
return YES;
}
MLVAFParseAPIClient.h
#import "AFHTTPClient.h"
#interface MLVAFParseAPIClient : AFHTTPClient
+ (MLVAFParseAPIClient *)sharedClient;
- (NSMutableURLRequest *)GETRequestForClass:(NSMutableString *)className parameters:(NSDictionary *)parameters;
- (NSMutableURLRequest *)GETRequestForAllRecordsOfClass:(NSString *)className updatedAfterDate:(NSDate *)updatedDate;
#end
MLVAFParseAPIClient.m
#import "MLVAFParseAPIClient.h"
#import "AFJSONRequestOperation.h"
static NSString * const kSDFParseAPIBaseURLString = #"https://api.parse.com/1/";
static NSString * const kSDFParseAPIApplicationId = #"APP ID REMOVED";
static NSString * const kSDFParseAPIKey = #"API KEY REMOVED";
#implementation MLVAFParseAPIClient
+ (MLVAFParseAPIClient *)sharedClient
{
static MLVAFParseAPIClient *sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{sharedClient = [[MLVAFParseAPIClient alloc] initWithBaseURL:[NSURL URLWithString:kSDFParseAPIBaseURLString]];
});
return sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (self) {
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
[self setParameterEncoding:AFJSONParameterEncoding];
[self setDefaultHeader:#"X-Parse-Application-Id" value:kSDFParseAPIApplicationId];
[self setDefaultHeader:#"X-Parse-REST-API-Key" value:kSDFParseAPIKey];
}
return self;
}
- (NSMutableURLRequest *)GETRequestForClass:(NSMutableString *)className parameters:(NSDictionary *)parameters
{
NSMutableURLRequest *request = nil;
request = [self requestWithMethod:#"GET" path:[NSString stringWithFormat:#"classes/%#", className] parameters:parameters ];
return request;
}
- (NSMutableURLRequest *)GETRequestForAllRecordsOfClass:(NSString *)className updatedAfterDate:(NSDate *)updatedDate
{
NSMutableURLRequest *request = nil;
NSDictionary *parameters = nil;
if (updatedDate) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss.'999Z'"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
NSString *jsonString = [NSString stringWithFormat:#"{\"updatedAt\":{\"$gte\":{\"__type\":\"Date\",\"iso\":\"%#\"}}}", [dateFormatter stringFromDate:updatedDate]];
parameters = [NSDictionary dictionaryWithObject:jsonString forKey:#"where"];
}
request = [self GETRequestForClass:className parameters:parameters];
return request;
}
#end
MLVCoreDataController.m
#import "MLVCoreDataController.h"
#interface MLVCoreDataController ()
#property (strong, nonatomic) NSManagedObjectContext *masterManagedObjectContext;
#property (strong, nonatomic) NSManagedObjectContext *backgroundManagedObjectContext;
#property (strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#end
#implementation MLVCoreDataController
#synthesize masterManagedObjectContext = _masterManagedObjectContext;
#synthesize backgroundManagedObjectContext = _backgroundManagedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
+ (id)sharedInstance {
static dispatch_once_t once;
static MLVCoreDataController *sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
#pragma mark - Core Data stack
// Used to propegate saves to the persistent store (disk) without blocking the UI
- (NSManagedObjectContext *)masterManagedObjectContext {
if (_masterManagedObjectContext != nil) {
return _masterManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_masterManagedObjectContext performBlockAndWait:^{
[_masterManagedObjectContext setPersistentStoreCoordinator:coordinator];
}];
}
return _masterManagedObjectContext;
}
// Return the NSManagedObjectContext to be used in the background during sync
- (NSManagedObjectContext *)backgroundManagedObjectContext {
if (_backgroundManagedObjectContext != nil) {
return _backgroundManagedObjectContext;
}
NSManagedObjectContext *masterContext = [self masterManagedObjectContext];
if (masterContext != nil) {
_backgroundManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_backgroundManagedObjectContext performBlockAndWait:^{
[_backgroundManagedObjectContext setParentContext:masterContext];
}];
}
return _backgroundManagedObjectContext;
}
// Return the NSManagedObjectContext to be used in the background during sync
- (NSManagedObjectContext *)newManagedObjectContext {
NSManagedObjectContext *newContext = nil;
NSManagedObjectContext *masterContext = [self masterManagedObjectContext];
if (masterContext != nil) {
newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[newContext performBlockAndWait:^{
[newContext setParentContext:masterContext];
}];
}
return newContext;
}
- (void)saveMasterContext {
[self.masterManagedObjectContext performBlockAndWait:^{
NSError *error = nil;
BOOL saved = [self.masterManagedObjectContext save:&error];
if (!saved) {
// do some real error handling
NSLog(#"Could not save master context due to %#", error);
}
}];
}
- (void)saveBackgroundContext {
[self.backgroundManagedObjectContext performBlockAndWait:^{
NSError *error = nil;
BOOL saved = [self.backgroundManagedObjectContext save:&error];
if (!saved) {
// do some real error handling
NSLog(#"Could not save background context due to %#", error);
}
}];
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"WGTCalculator" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"WGTCalcul.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
#end
MLVSyncEngine.h
#import <Foundation/Foundation.h>
typedef enum {
MLVObjectSynced = 0,
MLVObjectCreated,
MLVObjectDeleted,
} MLVObjectSyncStatus;
#interface MLVSyncEngine : NSObject
#property (atomic, readonly) BOOL syncInProgress;
+ (MLVSyncEngine *)sharedEngine;
- (void)registerNSManagedObjectClassToSync:(Class)aClass;
- (void)startSync;
#end
MLVSyncEngine.m
#import "MLVSyncEngine.h"
#import "MLVCoreDataController.h"
#import "MLVAFParseAPIClient.h"
#import "AFHTTPRequestOperation.h"
#import "AFJSONRequestOperation.h"
NSString * const kMLVSyncEngineInitialCompleteKey = #"MLVSyncEngineInitialSyncCompleted";
NSString * const kMLVSyncEngineSyncCompletedNotificationName = #"MLVSyncEngineSyncCompleted";
#interface MLVSyncEngine ()
#property (nonatomic, strong) NSMutableArray *registeredClassesToSync;
#property (nonatomic, strong) NSDateFormatter *dateFormatter;
#end
#implementation MLVSyncEngine
#synthesize registeredClassesToSync = _registeredClassesToSync;
#synthesize syncInProgress = _syncInProgress;
#synthesize dateFormatter = _dateFormatter;
+ (MLVSyncEngine *)sharedEngine
{
static MLVSyncEngine *sharedEngine = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedEngine = [[MLVSyncEngine alloc] init];
});
return sharedEngine;
}
- (void)registerNSManagedObjectClassToSync:(Class)aClass
{
if (!self.registeredClassesToSync) {
self.registeredClassesToSync = [NSMutableArray array];
}
if ([aClass isSubclassOfClass:[NSManagedObject class]]) {
if (![self.registeredClassesToSync containsObject:NSStringFromClass(aClass)]) {
[self.registeredClassesToSync addObject:NSStringFromClass(aClass)];
} else {
NSLog(#"Unable to register %# as it is already registered", NSStringFromClass(aClass));
}
} else {
NSLog(#"Unable to reguster %# as it is not a subclass of NSManagedObject", NSStringFromClass(aClass));
}
}
- (BOOL)initialSyncComplete{
return [[[NSUserDefaults standardUserDefaults] valueForKey:kMLVSyncEngineInitialCompleteKey] boolValue];
}
- (void)setInitialSyncCompleted{
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:kMLVSyncEngineInitialCompleteKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)executeSyncCompletedOperations {
dispatch_async(dispatch_get_main_queue(), ^{
[self setInitialSyncCompleted];
NSError *error = nil;
[[MLVCoreDataController sharedInstance] saveBackgroundContext];
if (error) {
NSLog(#"Error saving background context after creating objects on server: %#", error);
}
[[MLVCoreDataController sharedInstance] saveMasterContext];
[[NSNotificationCenter defaultCenter]
postNotificationName:kMLVSyncEngineSyncCompletedNotificationName
object:nil];
[self willChangeValueForKey:#"syncInProgress"];
_syncInProgress = NO;
[self didChangeValueForKey:#"syncInProgress"];
});
}
- (void)startSync
{
if (!self.syncInProgress) {
[self willChangeValueForKey:#"syncInProgress"];
_syncInProgress = YES;
[self didChangeValueForKey:#"syncInProgress"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{[self downloadDataForRegisteredObjects:YES];
});
}
}
- (NSDate *)mostRecentUpdatedAtDateForEntityWithName:(NSString *)entityName {
__block NSDate *date = nil;
//
// Create a new fetch request for the specified entity
//
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
//
// Set the sort descriptors on the request to sort by updatedAt in descending order
//
[request setSortDescriptors:[NSArray arrayWithObject:
[NSSortDescriptor sortDescriptorWithKey:#"updatedAt" ascending:NO]]];
//
// You are only interested in 1 result so limit the request to 1
//
[request setFetchLimit:1];
[[[MLVCoreDataController sharedInstance] backgroundManagedObjectContext] performBlockAndWait:^{
NSError *error = nil;
NSArray *results = [[[MLVCoreDataController sharedInstance] backgroundManagedObjectContext] executeFetchRequest:request error:&error];
if ([results lastObject]) {
//
// Set date to the fetched result
//
date = [[results lastObject] valueForKey:#"updatedAt"];
}
}];
return date;
}
- (void)newManagedObjectWithClassName:(NSString *)className forRecord:(NSDictionary *)record {
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:className inManagedObjectContext:[[MLVCoreDataController sharedInstance] backgroundManagedObjectContext]];
[record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[self setValue:obj forKey:key forManagedObject:newManagedObject];
}];
[record setValue:[NSNumber numberWithInt:MLVObjectSynced] forKey:#"syncStatus"];
}
- (void)updateManagedObject:(NSManagedObject *)managedObject withRecord:(NSDictionary *)record {
[record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[self setValue:obj forKey:key forManagedObject:managedObject];
}];
}
- (void)setValue:(id)value forKey:(NSString *)key forManagedObject:(NSManagedObject *)managedObject {
if ([key isEqualToString:#"createdAt"] || [key isEqualToString:#"updatedAt"]) {
NSDate *date = [self dateUsingStringFromAPI:value];
[managedObject setValue:date forKey:key];
} else if ([value isKindOfClass:[NSDictionary class]]) {
if ([value objectForKey:#"__type"]) {
NSString *dataType = [value objectForKey:#"__type"];
if ([dataType isEqualToString:#"Date"]) {
NSString *dateString = [value objectForKey:#"iso"];
NSDate *date = [self dateUsingStringFromAPI:dateString];
[managedObject setValue:date forKey:key];
} else if ([dataType isEqualToString:#"File"]) {
NSString *urlString = [value objectForKey:#"url"];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *dataResponse = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
[managedObject setValue:dataResponse forKey:key];
} else {
NSLog(#"Unknown Data Type Received");
[managedObject setValue:nil forKey:key];
}
}
} else {
[managedObject setValue:value forKey:key];
}
}
- (NSArray *)managedObjectsForClass:(NSString *)className withSyncStatus:(MLVObjectSyncStatus)syncStatus {
__block NSArray *results = nil;
NSManagedObjectContext *managedObjectContext = [[MLVCoreDataController sharedInstance] backgroundManagedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:className];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"syncStatus = %d", syncStatus];
[fetchRequest setPredicate:predicate];
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
}];
return results;
}
- (NSArray *)managedObjectsForClass:(NSString *)className sortedByKey:(NSString *)key usingArrayOfIds:(NSArray *)idArray inArrayOfIds:(BOOL)inIds {
__block NSArray *results = nil;
NSManagedObjectContext *managedObjectContext = [[MLVCoreDataController sharedInstance] backgroundManagedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:className];
NSPredicate *predicate;
if (inIds) {
predicate = [NSPredicate predicateWithFormat:#"objectId IN %#", idArray];
} else {
predicate = [NSPredicate predicateWithFormat:#"NOT (objectId IN %#)", idArray];
}
[fetchRequest setPredicate:predicate];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:
[NSSortDescriptor sortDescriptorWithKey:#"objectId" ascending:YES]]];
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
}];
return results;
}
- (void)downloadDataForRegisteredObjects:(BOOL)useUpdatedAtDate {
NSMutableArray *operations = [NSMutableArray array];
for (NSString *className in self.registeredClassesToSync) {
NSDate *mostRecentUpdatedDate = nil;
if (useUpdatedAtDate) {
mostRecentUpdatedDate = [self mostRecentUpdatedAtDateForEntityWithName:className];
}
NSMutableURLRequest *request = [[MLVAFParseAPIClient sharedClient]
GETRequestForAllRecordsOfClass:className
updatedAfterDate:mostRecentUpdatedDate];
AFHTTPRequestOperation *operation = [[MLVAFParseAPIClient sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject isKindOfClass:[NSDictionary class]]) {
[self writeJSONResponse:responseObject toDiskForClassWithName:className];
NSLog(#"Response for %#: %#", className, responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Request for class %# failed with error: %#", className, error);
}];
[operations addObject:operation];
}
[[MLVAFParseAPIClient sharedClient] enqueueBatchOfHTTPRequestOperations:operations progressBlock:^(NSUInteger numberOfCompletedOperations, NSUInteger totalNumberOfOperations) {
} completionBlock:^(NSArray *operations) {
NSLog(#"All operations completed");
[self processJSONDataRecordsIntoCoreData];
}];
}
- (void)processJSONDataRecordsIntoCoreData {
NSManagedObjectContext *managedObjectContext = [[MLVCoreDataController sharedInstance] backgroundManagedObjectContext];
//
// Iterate over all registered classes to sync
//
for (NSString *className in self.registeredClassesToSync) {
if (![self initialSyncComplete]) {
NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className];
NSArray *records = [JSONDictionary objectForKey:#"results"];
for (NSDictionary *record in records) {
[self newManagedObjectWithClassName:className forRecord:record];
}
} else {
NSArray *downloadedRecords = [self JSONDataRecordsForClass:className sortedByKey:#"objectId"];
if ([downloadedRecords lastObject]) {
NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:#"objectId" usingArrayOfIds:[downloadedRecords valueForKey:#"objectId"] inArrayOfIds:YES];
int currentIndex = 0;
for (NSDictionary *record in downloadedRecords) {
NSManagedObject *storedManagedObject = nil;
if ([storedRecords count] > currentIndex) {
storedManagedObject = [storedRecords objectAtIndex:currentIndex];
}
if ([[storedManagedObject valueForKey:#"objectId"] isEqualToString:[record valueForKey:#"objectId"]]) {
[self updateManagedObject:[storedRecords objectAtIndex:currentIndex] withRecord:record];
} else {
[self newManagedObjectWithClassName:className forRecord:record];
}
currentIndex++;
}
}
}
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
if (![managedObjectContext save:&error]) {
NSLog(#"Unable to save context for class %#", className);
}
}];
[self deleteJSONDataRecordsForClassWithName:className];
[self executeSyncCompletedOperations];
}
}
- (void)initializeDateFormatter {
if (!self.dateFormatter) {
self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss'Z'"];
[self.dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"GMT"]];
}
}
- (NSDate *)dateUsingStringFromAPI:(NSString *)dateString {
[self initializeDateFormatter];
dateString = [dateString substringWithRange:NSMakeRange(0, [dateString length]-5)];
return [self.dateFormatter dateFromString:dateString];
}
- (NSString *)dateStringForAPIUsingDate:(NSDate *)date {
[self initializeDateFormatter];
NSString *dateString = [self.dateFormatter stringFromDate:date];
dateString = [dateString substringWithRange:NSMakeRange(0, [dateString length]-1)];
dateString = [dateString stringByAppendingFormat:#".000Z"];
return dateString;
}
#pragma mark - File Management
- (NSURL *)applicationCacheDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSURL *)JSONDataRecordsDirectory{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *url = [NSURL URLWithString:#"JSONRecords/" relativeToURL:[self applicationCacheDirectory]];
NSError *error = nil;
if (![fileManager fileExistsAtPath:[url path]]) {
[fileManager createDirectoryAtPath:[url path] withIntermediateDirectories:YES attributes:nil error:&error];
}
return url;
}
-(void)writeJSONResponse:(id)response toDiskForClassWithName:(NSString *)className{
NSURL *fileURL = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]] ;
if (![(NSDictionary *)response writeToFile:[fileURL path] atomically:YES]) {
NSLog(#"Error saving response to disk, will attempt to remove NSNull values and try again.");
//remove NSNulls and try again...
NSArray *records = [response objectForKey:#"results"];
NSMutableArray *nullFreeRecords = [NSMutableArray array];
for (NSDictionary *record in records) {
NSMutableDictionary *nullFreeRecord = [NSMutableDictionary dictionaryWithDictionary:record];
[record enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
if ([obj isKindOfClass:[NSNull class]]) {
[nullFreeRecord setValue:nil forKey:key];
}
}];
[nullFreeRecords addObject:nullFreeRecord];
}
NSDictionary *nullFreeDictionary = [NSDictionary dictionaryWithObject:nullFreeRecords forKey:#"results"];
if (![nullFreeDictionary writeToFile:[fileURL path] atomically:YES]) {
NSLog(#"Failed all attempts to save response to disk: %#", response);
}
}
}
- (void)deleteJSONDataRecordsForClassWithName:(NSString *)className {
NSURL *url = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]];
NSError *error = nil;
BOOL deleted = [[NSFileManager defaultManager] removeItemAtURL:url error:&error];
if (!deleted) {
NSLog(#"Unable to delete JSON records at %#, reason %#", url, error);
}
}
- (NSDictionary *)JSONDictionaryForClassWithName:(NSString *)className {
NSURL *fileURL = [NSURL URLWithString:className relativeToURL:[self JSONDataRecordsDirectory]];
return [NSDictionary dictionaryWithContentsOfURL:fileURL];
}
- (NSArray *)JSONDataRecordsForClass:(NSString *)className sortedByKey:(NSString *)key {
NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className];
NSArray *records = [JSONDictionary objectForKey:#"results"];
return [records sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:key ascending:YES]]];
}
#end
Honestly, if your data model is that simple, and you're deleting the local persistent store / cache on every load, you probably would be much better off not using Core Data.
Keep it simple by loading data as needed. Save a cache using NSCoding, to be loaded initially as a placeholder, while the app waits for new information to be downloaded.
So it turns out the answer was pretty straight forward, the tutorial uses an older Version of AFNetworking where AFHTTPRequestOperation can download the data but does not see it as JSON.
AFHTTPRequestOperation *operation = [[MLVAFParseAPIClient sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([responseObject isKindOfClass:[NSDictionary class]]) {
[self writeJSONResponse:responseObject toDiskForClassWithName:className];
NSLog(#"Response for %#: %#", className, responseObject);
}
}
Needed to be updated with AFJSONRequestOperation
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest: request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
{
NSDictionary * responseObject = (NSDictionary * )JSON;
if ([responseObject isKindOfClass:[NSDictionary class]]) {
NSLog(#"Response for %#: %#", className, responseObject);
[self writeJSONResponse:responseObject toDiskForClassWithName:className];
I have to implement functionality to repeatedly pause and resume video capture in a single session, but have each new segment (the captured segments after each pause) added to the same video file, with AVFoundation. Currently, every time I press "stop" then "record" again, it just saves a new video file to my iPhone's Document directory and starts capturing to a new file. I need to be able to press the "record/stop" button over, only capture video & audio when record is active... then when the "done" button is pressed, have a single AV file with all the segments together. And all this needs to happen in the same capture session / preview session.
I am not using AVAssetWriterInput.
The only way I can think of to try this is when the "done" button is pressed, taking each individual output file and combining them together into a single file.
This code is working for iOS 5 but not for iOS 6. Actually for iOS 6, the first time when I pause recording (stop recording) AVCaptureFileOutputRecordingDelegate method (captureOutput: didFinishRecordingToOutputFileAtURL: fromConnections: error:) is called but after that when I start the recording the delegate method (captureOutput: didFinishRecordingToOutputFileAtURL: fromConnections: error:) is called again but it is not called at the time of stop recording.
I need a solution for that issue. Please help me.
//View LifeCycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.finalRecordedVideoName = [self stringWithNewUUID];
arrVideoName = [[NSMutableArray alloc]initWithCapacity:0];
arrOutputUrl = [[NSMutableArray alloc] initWithCapacity:0];
CaptureSession = [[AVCaptureSession alloc] init];
captureDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
if ([captureDevices count] > 0)
{
NSError *error;
VideoInputDevice = [[AVCaptureDeviceInput alloc] initWithDevice:[self backFacingCamera] error:&error];
if (!error)
{
if ([CaptureSession canAddInput:VideoInputDevice])
[CaptureSession addInput:VideoInputDevice];
else
NSLog(#"Couldn't add video input");
}
else
{
NSLog(#"Couldn't create video input");
}
}
else
{
NSLog(#"Couldn't create video capture device");
}
//ADD VIDEO PREVIEW LAYER
NSLog(#"Adding video preview layer");
AVCaptureVideoPreviewLayer *layer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:CaptureSession];
[self setPreviewLayer:layer];
UIDeviceOrientation currentOrientation = [UIDevice currentDevice].orientation;
NSLog(#"%d",currentOrientation);
if (currentOrientation == UIDeviceOrientationPortrait)
{
PreviewLayer.orientation = AVCaptureVideoOrientationPortrait;
}
else if (currentOrientation == UIDeviceOrientationPortraitUpsideDown)
{
PreviewLayer.orientation = AVCaptureVideoOrientationPortraitUpsideDown;
}
else if (currentOrientation == UIDeviceOrientationLandscapeRight)
{
PreviewLayer.orientation = AVCaptureVideoOrientationLandscapeRight;
}
else if (currentOrientation == UIDeviceOrientationLandscapeLeft)
{
PreviewLayer.orientation = AVCaptureVideoOrientationLandscapeLeft;
}
[[self PreviewLayer] setVideoGravity:AVLayerVideoGravityResizeAspectFill];
//ADD MOVIE FILE OUTPUT
NSLog(#"Adding movie file output");
MovieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
VideoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
[VideoDataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
NSString* key = (NSString*)kCVPixelBufferBytesPerRowAlignmentKey;
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
[VideoDataOutput setVideoSettings:videoSettings];
Float64 TotalSeconds = 60; //Total seconds
int32_t preferredTimeScale = 30; //Frames per second
CMTime maxDuration = CMTimeMakeWithSeconds(TotalSeconds, preferredTimeScale);//<<SET MAX DURATION
MovieFileOutput.maxRecordedDuration = maxDuration;
MovieFileOutput.minFreeDiskSpaceLimit = 1024 * 1024; //<<SET MIN FREE SPACE IN BYTES FOR RECORDING TO CONTINUE ON A VOLUME
//SET THE CONNECTION PROPERTIES (output properties)
[self CameraSetOutputProperties]; //(We call a method as it also has to be done after changing camera)
AVCaptureConnection *videoConnection = nil;
for ( AVCaptureConnection *connection in [MovieFileOutput connections] )
{
NSLog(#"%#", connection);
for ( AVCaptureInputPort *port in [connection inputPorts] )
{
NSLog(#"%#", port);
if ( [[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;
}
}
}
if([videoConnection isVideoOrientationSupported]) // **Here it is, its always false**
{
[videoConnection setVideoOrientation:[[UIDevice currentDevice] orientation]];
} NSLog(#"Setting image quality");
[CaptureSession setSessionPreset:AVCaptureSessionPresetLow];
//----- DISPLAY THE PREVIEW LAYER -----
CGRect layerRect = CGRectMake(5, 5, 299, ([[UIScreen mainScreen] bounds].size.height == 568)?438:348);
[self.PreviewLayer setBounds:layerRect];
[self.PreviewLayer setPosition:CGPointMake(CGRectGetMidX(layerRect),CGRectGetMidY(layerRect))];
if ([CaptureSession canAddOutput:MovieFileOutput])
[CaptureSession addOutput:MovieFileOutput];
[CaptureSession addOutput:VideoDataOutput];
//We use this instead so it goes on a layer behind our UI controls (avoids us having to manually bring each control to the front):
CameraView = [[UIView alloc] init];
[videoPreviewLayer addSubview:CameraView];
[videoPreviewLayer sendSubviewToBack:CameraView];
[[CameraView layer] addSublayer:PreviewLayer];
//----- START THE CAPTURE SESSION RUNNING -----
[CaptureSession startRunning];
}
#pragma mark - IBACtion Methods
-(IBAction)btnStartAndStopPressed:(id)sender
{
UIButton *StartAndStopButton = (UIButton*)sender;
if ([StartAndStopButton isSelected] == NO)
{
[StartAndStopButton setSelected:YES];
[btnPauseAndResume setEnabled:YES];
[btnBack setEnabled:NO];
[btnSwitchCameraInput setHidden:YES];
NSDate *date = [NSDate date];
NSLog(#" date %#",date);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *recordedFileName = nil;
recordedFileName = [NSString stringWithFormat:#"output%#.mov",date];
NSString *documentsDirectory = [paths objectAtIndex:0];
self.outputPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#",recordedFileName]];
NSLog(#"%#",self.outputPath);
[arrVideoName addObject:recordedFileName];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:self.outputPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:self.outputPath])
{
NSError *error;
if ([[NSFileManager defaultManager] removeItemAtPath:self.outputPath error:&error] == NO)
{
//Error - handle if requried
}
}
//Start recording
[MovieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
recordingTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(VideoRecording) userInfo:nil repeats:YES];
}
else
{
[StartAndStopButton setSelected:NO];
[btnPauseAndResume setEnabled:NO];
[btnBack setEnabled:YES];
[btnSwitchCameraInput setHidden:NO];
NSLog(#"STOP RECORDING");
WeAreRecording = NO;
[MovieFileOutput stopRecording];
[((ActOutAppDelegate *)ActOut_AppDelegate) showLoadingViewOnView:self.view withLabel:#"Please wait...."];
if ([recordingTimer isValid])
{
[recordingTimer invalidate];
recordingTimer = nil;
recordingTime = 30;
}
stopRecording = YES;
}
}
- (IBAction)btnPauseAndResumePressed:(id)sender
{
UIButton *PauseAndResumeButton = (UIButton*)sender;
if (PauseAndResumeButton.selected == NO)
{
PauseAndResumeButton.selected = YES;
NSLog(#"recording paused");
WeAreRecording = NO;
[MovieFileOutput stopRecording];
[self pauseTimer:recordingTimer];
[btnStartAndStop setEnabled:NO];
[btnBack setEnabled:YES];
[btnSwitchCameraInput setHidden:NO];
}
else
{
PauseAndResumeButton.selected = NO;
NSLog(#"recording resumed");
[btnStartAndStop setEnabled:YES];
[btnBack setEnabled:NO];
[btnSwitchCameraInput setHidden:YES];
WeAreRecording = YES;
NSDate *date = [NSDate date];
NSLog(#" date %#",date);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *recordedFileName = nil;
recordedFileName = [NSString stringWithFormat:#"output%#.mov",date];
NSString *documentsDirectory = [paths objectAtIndex:0];
self.outputPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#",recordedFileName]];
NSLog(#"%#",self.outputPath);
[arrVideoName addObject:recordedFileName];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:self.outputPath];
if ([[NSFileManager defaultManager] fileExistsAtPath:self.outputPath])
{
NSError *error;
if ([[NSFileManager defaultManager] removeItemAtPath:self.outputPath error:&error] == NO)
{
//Error - handle if requried
}
}
[self resumeTimer:recordingTimer];
//Start recording
[MovieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
}
}
- (void) CameraSetOutputProperties
{
//SET THE CONNECTION PROPERTIES (output properties)
AVCaptureConnection *CaptureConnection = [MovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
[CaptureConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
//Set frame rate (if requried)
CMTimeShow(CaptureConnection.videoMinFrameDuration);
CMTimeShow(CaptureConnection.videoMaxFrameDuration);
if (CaptureConnection.supportsVideoMinFrameDuration)
CaptureConnection.videoMinFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);
if (CaptureConnection.supportsVideoMaxFrameDuration)
CaptureConnection.videoMaxFrameDuration = CMTimeMake(1, CAPTURE_FRAMES_PER_SECOND);
CMTimeShow(CaptureConnection.videoMinFrameDuration);
CMTimeShow(CaptureConnection.videoMaxFrameDuration);
}
- (AVCaptureDevice *) CameraWithPosition:(AVCaptureDevicePosition) Position
{
NSArray *Devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *Device in Devices)
{
if ([Device position] == Position)
{
NSLog(#"%d",Position);
return Device;
}
}
return nil;
}
#pragma mark - AVCaptureFileOutputRecordingDelegate Method
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
if(videoWriterInput.readyForMoreMediaData && WeAreRecording) [videoWriterInput appendSampleBuffer:sampleBuffer];
for(AVCaptureConnection *captureConnection in [captureOutput connections])
{
if ([captureConnection isVideoOrientationSupported])
{
AVCaptureVideoOrientation orientation = AVCaptureVideoOrientationLandscapeLeft;
[captureConnection setVideoOrientation:orientation];
}
}
UIDeviceOrientation curOr = [[UIDevice currentDevice] orientation];
CGAffineTransform t;
if (curOr == UIDeviceOrientationPortrait)
{
t = CGAffineTransformMakeRotation(-M_PI / 2);
}
else if (curOr == UIDeviceOrientationPortraitUpsideDown)
{
t = CGAffineTransformMakeRotation(M_PI / 2);
}
else if (curOr == UIDeviceOrientationLandscapeRight)
{
t = CGAffineTransformMakeRotation(M_PI);
}
else
{
t = CGAffineTransformMakeRotation(0);
}
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error
{
NSLog(#"didFinishRecordingToOutputFileAtURL - enter");
NSLog(#"output file url : %#", [outputFileURL absoluteString]);
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];
}
}
AVCaptureConnection *videoConnection=nil;
for ( AVCaptureConnection *connection in [MovieFileOutput connections] )
{
NSLog(#"%#", connection);
for ( AVCaptureInputPort *port in [connection inputPorts] )
{
NSLog(#"%#", port);
if ( [[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;
}
}
}
if([videoConnection isVideoOrientationSupported]) // **Here it is, its always false**
{
[videoConnection setVideoOrientation:[[UIDevice currentDevice] orientation]];
} NSLog(#"Setting image quality");
NSData *videoData = [NSData dataWithContentsOfURL:outputFileURL];
[videoData writeToFile:self.outputPath atomically:NO];
[arrOutputUrl addObject:outputFileURL];
if (stopRecording)
{
[self mergeMultipleVideo];
}
}
//Method to merge multiple audios
-(void)mergeMultipleVideo
{
mixComposition = [AVMutableComposition composition];
AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime nextClipStartTime = kCMTimeZero;
NSLog(#"Array of output file url : %#", arrOutputUrl);
if (arrOutputUrl.count > 0)
{
for(int i = 0 ;i < [arrOutputUrl count];i++)
{
AVURLAsset* VideoAsset = [[AVURLAsset alloc]initWithURL:[arrOutputUrl objectAtIndex:i] options:nil];
CMTimeRange timeRangeInAsset;
timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [VideoAsset duration]);
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, VideoAsset.duration) ofTrack:[[VideoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:nextClipStartTime error:nil];
nextClipStartTime = CMTimeAdd(nextClipStartTime, timeRangeInAsset.duration);
}
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *myPathDocs = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.mov",self.finalRecordedVideoName]];
NSURL *url = [NSURL fileURLWithPath:myPathDocs];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:mixComposition presetName:AVAssetExportPresetHighestQuality];
exportSession.outputURL=url;
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self exportDidFinish:exportSession path:myPathDocs];
});
}];
}
-(void)exportDidFinish:(AVAssetExportSession*)session path:(NSString*)outputVideoPath
{
NSLog(#"session.status : %d",session.status);
if (session.status == AVAssetExportSessionStatusCompleted)
{
NSURL *outputURL = session.outputURL;
NSData *videoData = [NSData dataWithContentsOfURL:outputURL];
[videoData writeToFile:outputVideoPath atomically:NO];
if ([arrVideoName count] > 0)
{
for (int i = 0; i < [arrVideoName count]; i++)
{
NSArray* documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* fullFilePath = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent: [NSString stringWithFormat:#"%#",[arrVideoName objectAtIndex:i]]];
NSLog(#"Full path of file to be deleted: %#",fullFilePath);
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
if ([fileManager fileExistsAtPath:fullFilePath])
{
[fileManager removeItemAtPath:fullFilePath error:&error];
}
}
[arrVideoName removeAllObjects];
}
if (arrOutputUrl.count > 0)
{
[arrOutputUrl removeAllObjects];
}
[((ActOutAppDelegate *)ActOut_AppDelegate) removeLoadingViewfromView:self.view];
[self.view addSubview:afterRecordingPopupView];
}
}
Look at the AVCaptureConnection's enabled property. For your output connection, set enabled to NO instead of stopping the session.
In my application i have called sharedinstance multiple time in multiple method deffinition ,
Here my code,
Method 1
-(void) showActionSheet:(id)sender forEvent:(UIEvent*)event
{
if(isQuantity==YES)
{
[[WebService sharedInstance] getQuantity:^(BOOL result)
{
if(result)
{
NSLog(#"success");
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
Quantity = [context fetchObjectsForEntityName:NSStringFromClass([GetQuantity class]) withSortColumn:nil withSortDescending:TRUE withPredicate:nil];
NSLog(#"array ->%#",Quantity);
isQuantity=NO;
}
}];
}
popoverController1 = [[TSPopoverController alloc]initWithContentViewController:tableViewController1];
popoverController1.cornerRadius = 5;
popoverController1.titleText = #"Quantity";
popoverController1.popoverBaseColor = [UIColor blackColor];
popoverController1.popoverGradient= NO;
[popoverController1 showPopoverWithTouch:event];
}
Method 2
-(void) showActionSheetw:(id)sender forEvent:(UIEvent*)events
{
if(isSize==YES)
{
[[WebService sharedInstance] getDimension:^(BOOL result)
{
if(result){
NSLog(#"success");
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
dime = [context fetchObjectsForEntityName:NSStringFromClass([Getdimension class]) withSortColumn:nil withSortDescending:FALSE withPredicate:nil];
NSLog(#"array ->%#",dime);
}
}];
}
popoverController2 = [[TSPopoverController alloc] initWithContentViewController:tableViewController2];
popoverController2.cornerRadius = 5;
popoverController2.titleText = #"Size";
popoverController2.popoverBaseColor = [UIColor blackColor];
popoverController2.popoverGradient= NO;
// popoverController.arrowPosition = TSPopoverArrowPositionHorizontal;
[popoverController2 showPopoverWithTouch:events];
}
EDIT
- (void) getDimension:(void (^)(BOOL))handler
{
JBContainedURLConnection *connection = [[JBContainedURLConnection alloc]init ];
[connection initWithGETUrl:IP methodName:GETDIMENSION param:nil andCompletionHandler:^(JBContainedURLConnection *connection, NSError *error, NSString *urlString, NSDictionary *userInfo, NSData *response)
{
if(error)
{
NSLog(#"Error: %#", error);
handler(FALSE);
}
else
{
if(response == nil)
handler(FALSE);
else
{
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
NSArray *existingResults = [context fetchObjectsForEntityName:NSStringFromClass([Getdimension class]) withSortColumn:nil withSortDescending:FALSE withPredicate:nil];
for (NSManagedObject *obj in existingResults)
[context deleteObject:obj];
[[DataAccessLayer sharedInstance] saveContext];
id responseData = [self DictionaryFromResponse:response];
if(responseData == nil)
handler(FALSE);
else
{
NSLog(#"Dimension Response: %#", [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]);
NSArray *data=[responseData objectForKey:#"GetDimensionResult"];
NSLog(#"GetDimensionResult :%#",data);
for( NSDictionary *dict in data){
Getdimension *userDetails = [Getdimension newObject];
[userDetails fillFromDictionary:dict];
}
[[DataAccessLayer sharedInstance] saveContext];
handler(TRUE);
}
} }
}];
}
- (void) getQuantity:(void (^)(BOOL))handler
{
JBContainedURLConnection *connection = [[JBContainedURLConnection alloc]init ];
[connection initWithGETUrl:IP methodName:GETQUANTITY param:nil andCompletionHandler:^(JBContainedURLConnection *connection, NSError *error, NSString *urlString, NSDictionary *userInfo, NSData *response)
{
if(error)
{
NSLog(#"Error: %#", error);
handler(FALSE);
}
else
{
if(response == nil)
handler(FALSE);
else
{
NSManagedObjectContext *context = [[DataAccessLayer sharedInstance] managedObjectContext];
NSArray *existingResults = [context fetchObjectsForEntityName:NSStringFromClass([GetQuantity class]) withSortColumn:nil withSortDescending:FALSE withPredicate:nil];
for (NSManagedObject *obj in existingResults)
[context deleteObject:obj];
[[DataAccessLayer sharedInstance] saveContext];
id responseData = [self DictionaryFromResponse:response];
if(responseData == nil)
handler(FALSE);
else
{
NSLog(#"GetQuantityResult Response: %#", [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding]);
NSArray *data=[responseData objectForKey:#"GetQuantityResult"];
// NSLog(#"GetDimensionResult :%#",data);
for( NSDictionary *dict in data){
GetQuantity *userDetails = [GetQuantity newObject];
[userDetails fillFromDictionary:dict];
}
[[DataAccessLayer sharedInstance] saveContext];
handler(TRUE);
}
} }
}];
}
Instance method
+ (id)sharedInstance
{
#synchronized(self)
{
if (manager == nil)
manager = [[self alloc] init];
}
return manager;
}
-(id)init
{
if(self = [super init])
{
}
return self;
}
-(NSString *)NSStringFromDictionaryUsingJSON:(id)dictionary
{
SBJsonWriter *writer = [[SBJsonWriter alloc]init];
return [writer stringWithObject:dictionary];
}
-(id)DictionaryFromResponse:(NSData *)response
{
NSString *responseBody = [[NSString alloc] initWithData:response encoding:NSASCIIStringEncoding];
SBJsonParser *parser = [[SBJsonParser alloc]init];
return [parser objectWithString:responseBody error:nil];
}
sharedInstance only works one time,ie,. if i call any of the method first its worked,if calls other method second time app gets crashed.Can any one please help me to sort it out
I guess sharedInstance method is messy.
It should be
+ (id)sharedInstance
{
if (manager == nil)
manager = [[self alloc] init];
return manager;
}
Enjoy Programming !
Have you declared instance of your class as static,
Declare you class object as :
static ClassName *manager;
And the allocate the same object in your sharedInstance method.
The reason may be that the memory object was released but reference is still there in the memory.So when you execute the shared instance method it found a reference to !nil object and leads your application to crash.
This is singleton class feature of iOS(objective C)
I'm trying to practice the block and GCD/NSOperation, so I wrote this project Async-objc, but when I'm trying to test it with unit test, I always encountered 'double free' error, I thought there shouldn't be such error in ARC mode.
here is the code
- (void)each:(NSArray *)items iterator:(callbackEach)iterator complete:(callbackWithError)complete {
NSBlockOperation *blockOp = [NSBlockOperation blockOperationWithBlock:^{
if (!items || items.count == 0) {
complete(nil);
return;
}
callbackWithError __block completeOnce = complete;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSLog(#"start operations %#", queue);
[queue setMaxConcurrentOperationCount:kMaxConcurrentOperationCount];
NSInteger __block count = 0;
for (id item in items) {
NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{
iterator(item, ^(NSError *error) {
if (error) {
completeOnce(error);
completeOnce = nil;
} else {
count++;
if (count >= items.count) {
completeOnce(nil);
completeOnce = nil;
}
}
});
}];
[queue addOperation:op];
}
[queue waitUntilAllOperationsAreFinished];
NSLog(#"all operations are down %#", queue);
}];
[_mainQueue addOperation:blockOp];
}
this is the test code:
- (void)testEachWithBigData {
BOOL __block completed = false;
NSMutableArray *items = [NSMutableArray arrayWithCapacity:100];
for (int i = 1; i < 10000; ++i) {
[items addObject:[NSString stringWithFormat:#"%d", i]];
}
NSMutableArray *result = [NSMutableArray arrayWithCapacity:100];
[_async each:items
iterator:^(id item, callbackWithError callback) {
//NSLog(#"======item %#", item);
NSNumber *num = [NSNumber numberWithInt:[item integerValue]];
//NSLog(#"number %#", num);
[result addObject:num];
callback(nil);
}
complete:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
STAssertNil(error, #"there should be no error");
[result sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSNumber *num1 = (NSNumber *)obj1;
NSNumber *num2 = (NSNumber *)obj2;
if ([num1 integerValue] > [num2 integerValue]) {
return NSOrderedDescending;
} else if ([num1 integerValue] < [num2 integerValue]) {
return NSOrderedAscending;
}
return NSOrderedSame;
}];
NSInteger index = 1;
for (NSNumber *num in result) {
STAssertEquals(index, [num integerValue], #"the value should be ordered");
index++;
}
completed = YES;
});
}
];
NSDate *until = [NSDate dateWithTimeIntervalSinceNow:10];
while (!completed && [until timeIntervalSinceNow] > 0) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:until];
}
}
If you couldn't reproduce the error, increase the test item count to 10000.
for (int i = 1; i < 10000; ++i) {
[items addObject:[NSString stringWithFormat:#"%d", i]];
}
and comment the NSLog()
then Command + U to run the unit test
here is the error message:
otest(11105,0xb039f000) malloc: * error for object 0xa0f8000: pointer being freed was not allocated
otest(11209,0xb0115000) malloc: * error for object 0x41dcc00: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
I cannot reproduce the 'double free' error this time
I have searched a lot trying to figure this out - the code to me seems ok but the functionality doesn't reflect this.
I have a View that is presented (its an Audio Recorder view). You can press record and it records to a file just fine (data exists in the file). I can then play the file back via the play button (the AVAudioPlayer is pointing to that file).
However when I close/dismiss that view and come back to it - the file will not play when Play is tapped even though it should be exactly the same code as the file location has not changed.
UPDATE:
Seems that [audioPlayer play] returns no. I have also looked into the data. It seems that when the view appears again and loads that data it doesnt load it correctly (NSdata in Nslog displays mainly 0's) - even though the file exists and has data in it (i can see and hear it after transferring to my mac).
This leads me to suspect that either I am loading the data wrong or avaudioplayer wont read the data for some reason...
Please take a look at the code below:
(NSString *) removeCharsFrom: (NSString *) remover {
remover = [remover stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
remover = [remover stringByReplacingOccurrencesOfString:#" " withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"/" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"\\" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#":" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#";" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"(" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#")" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"£" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"$" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"&" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"'" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"{" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"}" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"[" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"]" withString:#"_"];
remover = [remover stringByReplacingOccurrencesOfString:#"""" withString:#"_"];
return remover;
}
- (NSString *) audioPathForResource: (NSString *) audio {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *saveDirectory = [paths objectAtIndex:0];
NSString *newFolder = [saveDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"/%#/Audio",catName]];
if (![[NSFileManager defaultManager] fileExistsAtPath:newFolder]) {
[[NSFileManager defaultManager] createDirectoryAtPath:newFolder withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *saveFileName = [NSString stringWithFormat:#"%#.caf",audio];
NSString *newFilePath = [newFolder stringByAppendingPathComponent:saveFileName];
return [newFilePath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
- (IBAction)cancelTapped:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)saveTapped:(id)sender {
[self.parentViewController performSelector:#selector(changeAddAudioIcon)];
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)trashTapped:(id)sender {
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle: #"Delete"
message: #"Would you like to delete the audio file? Warning: This cannot be undone."
delegate: self
cancelButtonTitle: #"Cancel"
otherButtonTitles: #"Delete", nil];
[alert show];
[alert release];
}
- (IBAction)pauseTapped:(id)sender {
pauseBtn.enabled = NO;
playBtn.enabled = YES;
recordBtn.enabled = YES;
trashBtn.enabled = YES;
if (audioRecorder.recording)
{
[audioRecorder stop];
} else if (audioPlayer.playing) {
[audioPlayer stop];
}
}
- (IBAction)recordTapped:(id)sender {
if (!audioRecorder.recording)
{
playBtn.enabled = NO;
pauseBtn.enabled = YES;
trashBtn.enabled = NO;
[audioRecorder record];
}
}
- (IBAction)playTapped:(id)sender {
pauseBtn.enabled = YES;
recordBtn.enabled = NO;
trashBtn.enabled = YES;
NSError *error;
NSLog(#"%#",filepathstring);
NSURL *soundFileURL = [NSURL fileURLWithPath:filepathstring];
audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:soundFileURL
error:&error];
audioPlayer.delegate = self;
if (error)
NSLog(#"Error: %#",
[error localizedDescription]);
else
[audioPlayer play];
}
- (void)alertView: (UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0:
return;
break;
case 1:
{
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtPath:filepathstring error:&error];
trashBtn.enabled = NO;
}
break;
default:
break;
}
}
-(void)audioPlayerDidFinishPlaying:
(AVAudioPlayer *)player successfully:(BOOL)flag
{
recordBtn.enabled = YES;
pauseBtn.enabled = NO;
playBtn.enabled = YES;
if(player != audioPlayer) {
[player release];
}
}
-(void)audioPlayerDecodeErrorDidOccur:
(AVAudioPlayer *)player
error:(NSError *)error
{
NSLog(#"Decode Error occurred");
}
-(void)audioRecorderDidFinishRecording:
(AVAudioRecorder *)recorder
successfully:(BOOL)flag
{
NSLog(#"Recording success:%#",flag ? #"YES" : #"NO");
trashBtn.enabled = YES;
pauseBtn.enabled = NO;
playBtn.enabled = YES;
}
-(void)audioRecorderEncodeErrorDidOccur:
(AVAudioRecorder *)recorder
error:(NSError *)error
{
NSLog(#"Encode Error occurred");
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void) viewWillAppear:(BOOL)animated {
catName = [NSString stringWithFormat:#"%#",[self removeCharsFrom:catName]];
testName = [NSString stringWithFormat:#"%#",[self removeCharsFrom:testName]];
filepathstring = [[self audioPathForResource:testName] retain];
NSLog(#"At start = %#",filepathstring);
if ([[NSFileManager defaultManager] fileExistsAtPath:filepathstring]) {
playBtn.enabled = YES;
trashBtn.enabled = YES;
recordBtn.enabled = YES;
}
else
{
playBtn.enabled = NO;
trashBtn.enabled = NO;
}
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
NSURL *soundFileURL = [NSURL fileURLWithPath:filepathstring];
NSDictionary *recordSettings = [NSDictionary
dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:AVAudioQualityMin],
AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16],
AVEncoderBitRateKey,
[NSNumber numberWithInt: 2],
AVNumberOfChannelsKey,
[NSNumber numberWithFloat:44100.0],
AVSampleRateKey,
nil];
NSError *error = nil;
audioRecorder = [[AVAudioRecorder alloc]
initWithURL:soundFileURL
settings:recordSettings
error:&error];
audioRecorder.delegate = self;
if (error)
{
NSLog(#"error: %#", [error localizedDescription]);
} else {
[audioRecorder prepareToRecord];
}
}
- (void)viewDidUnload
{
[self setCancelBtn:nil];
[self setSaveBtn:nil];
[self setTimeLabel:nil];
[self setDescriptionLabel:nil];
[self setToolsBar:nil];
[self setTrashBtn:nil];
[self setPauseBtn:nil];
[self setRecordBtn:nil];
[self setPlayBtn:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return YES;
} else {
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
}
- (void)dealloc {
[cancelBtn release];
[saveBtn release];
[timeLabel release];
[descriptionLabel release];
[toolsBar release];
[trashBtn release];
[pauseBtn release];
[recordBtn release];
[playBtn release];
[audioPlayer release];
[audioRecorder release];
[super dealloc];
}
Here is the answer:
NSData *data = [NSData dataWithContentsOfMappedFile:[NSString stringWithFormat:#"%#",filepathstring]];
AVAudioPlayer *ap = [[AVAudioPlayer alloc]
initWithData:data error:&error];
Seems that it just wouldnt work with filepathstring but within an NSString it worked fine. Obvious now!