AVAudioPlayer EXC_BAD_ACCESS - avaudioplayer

I am trying to pause the AVAudioPlayer if it is currently playing. When I debug my code and check AVAudioPlayer, I see it is allocated. When I try to access a method/property on it (i.e. myAudioPlayer isPlaying), I get an EXC_BAD_ACCESS error. This happens if the AVAudioPlayer does not have a sound loaded. Is there a way I can do a check to see if it has loaded a sound? I tried accessing myAudioPlayer.data, but I still get the same error.

For me it was because I wasn't calling the one of the designated initialisers. I was instantiating it with AVAudioPlayer() instead of the designated initialisers which are public init(contentsOfURL url: NSURL) throws and public init(data: NSData) throws

As of iOS 13, make sure you are removing the initialization on AVAudioPlayer before asigning it with AVAudioPlayer(contentsOf: URL(...))
i.e. change
var audioPlayer = AudioPlayer() to var audioPlayer: AVAudioPlayer!

I guess you have to use prepareToPlay method to find whether it has loaded or not.

First you have to add AVFoundation Framework.Then,import AVFounadtion framework in .h file.
.h:
AVAudioPlayer *audioPlayer;
.m:
NSURL *url1 = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/audio1.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url1 error:&error];
//audioPlayer.numberOfLoops = 0;
[audioPlayer play];
Try this code it may help you..

Related

Unrecognized selector occurring after Lightweight Core Data migration

I'm getting an unrecognized selector on a newly added field to my Core Data (SQLite) db on iOS. I added a new model version as directed using Xcode's Editor menu, and then verified that new version is the current one. I made sure also that the .h and .m files for the modified table were updated, though I did this by hand (how to have these generated for you?). Nothing unusual though, just a String type field.
The problem seems to be that the lightweight migration never takes place by the time code is run that tries to reference the database object. Tring to access newFieldName gives:
-[MyEntity newFieldName]: unrecognized selector sent to instance 0x852b510
2014-03-27 13:26:21.734 ASSIST for iPad[41682:c07] *** Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: '-[MyEntity newFieldName]:
unrecognized selector sent to instance 0x852b510'
The line of code that generates the above error is the only line in the for loop below:
DataStoreCoreData *dStore = [[DataStoreCoreData alloc] initWithDataItemDescription:did];
for (MyEntity *myEnt in [dStore objects])
NSString *name = [myEnt newFieldName];
As mentioned, when I examine the SQLite db it has no new field in it, which makes sense given the error. So I also stepped through the execution of the code that is supposed to do the migration and it seems to work fine. Success. It looks like the following:
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"ASSIST.sqlite"]];
// handle db upgrade
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error])
NSLog(#"\r\n Fail. [error localizedDescription]: %#", [error localizedDescription]);
else
NSLog(#"\r\n Success");
This is the 6th db version upgrade. All have been lightweight migrations with no unusual problems. Should not the above code force the SQLite db to reflect the new schema? How do I get it to do so, or is there another problem here?
I finally discovered the answer. The code I provided with the question is only part of the code required to be modified when making minimal changes to the database (lightweight migration). You also need to specify the new version when you create the object model. Notice "MyNewVersion" in the code below. You are supposed to update this parameter to reflect the new version you created and then selected as the current Model Version:
NSString *path = [[NSBundle mainBundle] pathForResource:#"MyNewVersion" ofType:#"mom" inDirectory:#"ASSIST.momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];

useLayoutToLayoutNavigationTransitions in iOS7 crash

I am building an iOS7 app and I am trying to make use of the new useLayoutToLayoutNavigationTransitions effect. I have 2 UICollectionViewControllers and when I do the following I get the transition effect
SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondVC.useLayoutToLayoutNavigationTransitions = YES;
[self.navigationController pushViewController:secondVC animated:YES];
this works fine but what I want to do is make an api call and then in the completion block I want to push onto the nav stack like so
[webAPI getDetailsWithParams:params andCompletionBlock:^(id dict) {
//some work on the result
SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondVC.useLayoutToLayoutNavigationTransitions = YES;
[self.navigationController pushViewController:secondVC animated:YES];
} andErrorBlock:^(NSError *error) {
}];
but this crashes every time with the following msg
-[UICollectionView _invalidateLayoutWithContext:]: message sent to deallocated instance 0x17a26400
can anyone tell me what I am doing wrong in this case? How can I get the transition effect when pushing from completion block?
EDIT: by changing it to the following I was able to transition to the second viewcontroller.
MyLayout *layout = [[MyLayout alloc] init];
SecondViewController *expandedVC = [[SecondViewController alloc] initWithCollectionViewLayout:layout];
and I also deleted the nib file that went with the file. nib file just consisted of a collection view and it was the file owners view.
While I can now transition I still do not understand why I could not do the previous nib method with in a block. So I would be grateful if someone could shed some light on it for me.
In order to use UICollectionViewController's useLayoutToLayoutNavigationTransitions to make transitions, the layout of the SecondViewController must be known. However, if you use initWithNibName:bundle: initializer, layout is not internally prepared yet, making your desired transitions impossible. As you mentioned in your edited question, you have to use [UICollectionViewController initWithCollectionViewLayout:] to initialize your second UICollectionViewController. Since your xib file has the same name as your class name, SecondViewController.xib is going to be loaded automatically by UIViewController, superclass of UICollectionViewController.
I think you were making UIKit calls from a thread that wasn't the main thread

Why does OCMock cause nsnotificaiton center to have EXC_BAD_ACCESS when using mockObserver

I setup mock observers like this:
id quartileObserverMock = [OCMockObject observerMock];
[[NSNotificationCenter defaultCenter] addMockObserver:quartileObserverMock
name:kVPAdPlayerDidReachQuartileNotification
object:self.adPlayer];
[[quartileObserverMock expect]
notificationWithName:kVPAdPlayerDidReachQuartileNotification
object:self.adPlayer
userInfo:#{#"quartile" : #(VPAdPlayerFirstQuartile), #"trackingEvent" : VPCreativeTrackingEventFirstQuartile}];
my unit tests run; but I get spurious EXC_BAD_ACCESS errors when the notificaiton is posted.
i.e.
[[NSNotificationCenter defaultCenter]
postNotificationName:kVPAdPlayerDidReachQuartileNotification
object:self.adPlayer
userInfo:#{#"quartile" : #(quartile), #"trackingEvent" : trackingEvent}];
When I comment out the observermock code my tests run fine every single time.
When I put the code back in, I get spurious crashes on postNotiicaitonName:object:userInfo, maybe once every 2.5 times.
Anyone got any ideas?
Refer the following sample code, this might help you. It worked for me
- (void)test__postNotificationwithName__withUserInfo
{
id observerMock = [OCMockObject observerMock];
[[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:#"NewNotification" object:nil];
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:#"2",#"2", nil];
[[observerMock expect] notificationWithName:#"NewNotification" object:[OCMArg any] userInfo:userInfo];
NotificationClass *sut = [[NotificationClass alloc] init];
[sut postNotificationwithName:#"NewNotification" userInfo:userInfo];
[[NSNotificationCenter defaultCenter] removeObserver:observerMock];
[observerMock verify];
}
and my posting notification method
- (void)postNotificationwithName:(NSString *)notifName userInfo:(NSDictionary *)userInfo
{
[[NSNotificationCenter defaultCenter] postNotificationName:notifName object:self userInfo:userInfo];
}
Please note:
observerMock always raise an exception when an unexpected notification is received.
Remove the mocked observer from the NSNotificationCenter at the end of the test case.
There are a couple of reasons why this could be happening (I know, because I just solved both of them them in my own code today)
1) A mock observer from a previous test was not removed
2) An non-mock instance object from a previous test is observing for the same notification, but that object has since become obsolete. In my case, an instance object from my setUp method was listening to the notification, but when it was dealloced, it did not remove itself from the NSNotificationCenter's observers list.
In both cases the solution is to use
[[NSNotificationCenter defaultCenter] removeObserver:name:object:]
Depending on the scope: 1) in the dealloc of all classes that observe NSNotificationCenter, 2) in the tearDown method, or 3) at the end of the test case (as #PrasadDevadiga mentioned)

UINavigationController pushViewController memory management

I have a code like this:
MyViewController *myController = [[MyViewController alloc] init];
[self.myNavController pushViewController:myController animated:YES];
[myController release];
In above case, deallc of MyViewController gets called twice resulting in a crash.
If I remove the last line "[myController release];" everything is fine.
Isn't this against the memory management guidelines?
if i understand truly, you must use initWithNibName against init like below:
MyViewController *myController = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
Please try this and reply, best regards.
Are you sure that the MyViewController's dealloc method not release someObj more than once?
You can try to clear away dealloc content,then,run the app again.

video clip no longer plays (autorelease issue)

I took care of a memory leak related to the alloc object, however I think I have fouled up my code as now my video clip does not play. I believe that I have caused the device to release before the clip starts. Could someone help me to rearrange my code? I would be greatly appreciative of a few hints to get playback working again. Here is a sample of what I am working with.
#implementation ELECTRIC_GROOVEYViewController
-(IBAction)playMovie:(id)sender
{
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"1960" ofType:#"m4v"];
NSURL *fileURL = [NSURL fileURLWithPath:filepath];
MPMoviePlayerController *moviePlayerController =
[[[MPMoviePlayerController alloc] initWithContentURL:fileURL]autorelease];
[self.view addSubview:moviePlayerController.view];
moviePlayerController.fullscreen = YES;
moviePlayerController.scalingMode = MPMovieScalingModeAspectFill;
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerLoadStateDidChangeNotification
object:nil];
// no moviecontrolls
moviePlayerController.controlStyle = MPMovieControlStyleNone;
// looping forever
moviePlayerController.repeatMode= MPMovieRepeatModeOne;
[moviePlayerController play];
}
You are autoreleaseing the moviePlayerController object. It has no further retention. Hence the object must be getting deallocated. Maintain a reference to it by creating an instance variable and release it after you are done with it.

Resources