Release AVAudioPlayer in iOS4/iOS5 giving EXC_BAD_ACCESS error - ios

EDIT: Updated my device (and deployment target) from iOS 4.3.5 to iOS 5.1.1 and still has the same issue
Having a problem releasing a class member AVAudioPlayer to play another sound after playing a sound.
This only seems to be a problem on one of my devices, a 3rd generation iPod Touch running iOS 4.3.5/5.1.1.
My 4th and 5th generation devices running iOS 6 run just fine.
[audio release];
audio = nil;
#try
{
audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
if ((audio != nil) && (!error))
{
audio.delegate = (id)self;
audio.volume = gVolume/10;
[audio play];
}
else
{
[audio release];
audio = nil;
}
}
#catch (NSException *exception)
{
[audio release];
audio = nil;
}
First time through it plays just fine, but when this code executes a second time to play another sound, it gives an EXC_BAD_ACCESS error, which does not happen on my 4th/5th generation devices.
I purposely delay the release until I need to play another sound in order to give the play time to perform.
Tried working with AVAudioPlayerDelegate but that didn't solve the problem, nor does calling:
[audio prepareToPlay];
I do initialize audio to nil in viewDidLoad, and clean up in viewDidUnload and dealloc.
Was having a lot of memory leak issues but this version of the code seemed to have solved that.

Thanks to the comment above, and the failure of all my other ideas, I went ahead and took advantage of ARC.
I didn't want to refactor my entire project to start using ARC, so I rewrote a new class to handle all of my audio needs and set some compiler flags (-fobjc-arc) to enable ARC just for that file.
Not exactly sure what I was doing wrong before, but the system seems to be much better at managing memory than I am, and I'm happy to let it solve all my problems.
EDIT 2:
Apparently Apple did finally fix their memory leak so I went back to my ARC solution which works fine for both iOS 5 and iOS 6.
EDIT:
I may have been a little premature.
While implementing ARC for this was helpful in general, this specific problem goes deeper.
Apparently, there is a leak in Core Foundation for iOS 6.
Leak from NSURL and AVAudioPlayer using ARC
Memory Leak - NSString & NSURL
Using ARC, it works fine on my Gen 3 iOS 5 device, but leaks significantly for Gen 4/5 iOS 6.
Without ARC, Gen 4/5 iOS 6 works fine, but Gen 3 iOS 5 crashes.
I ended up making two versions of my new class, one using ARC and one not, and checking the system version at runtime [[UIDevice currentDevice] systemVersion] to determine which version to use.
It may be a little clumsy, but does allow me to support the Gen 3 devices. If Apple ever fixes their problem I can return to a single version at that time.

Related

Why does not executing the following code cause it to crash?

I have an app that uses Admob. But since I am supporting versions of iOS 5 and above, I make sure that I don't call Admob code in versions below iOS 6 by doing the following:
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_5_1) {
int j = 2;
j++; //This is just some code so I can use breakpoints for testing.
NSLog(#"Google Mobile Ads SDK version: %#", [GADRequest sdkVersion]); //Commenting out the line prevents the crash
}
I am testing on iOS 5.1.1. Now if I comment out the NSLog, line, the app works without problem. But if I uncomment it the app crashes almost immediately within the main method:
int retVal = UIApplicationMain(argc, argv, nil, #"AppController");
I guess its not crashing when it is commented out because the compiler "optimises out" the code since its not used. But then what is the correct way to make sure the code isn't used, and the app doesn't crash ?
EDIT: I edited the code, the if block is not optimised out:
int j = 2;
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_5_1) {
j++; //This is just some code so I can use breakpoints for testing.
NSLog(#"Google Mobile Ads SDK version: %#", [GADRequest sdkVersion]); //Commenting out the line prevents the crash
}else{
j--;
}
NSLog(#"%d",j);
The output is "1", so the code in the else block executes. So even thought the function call [GADRequest sdkVersion] is not made, why does it crash ? Again, if I comment out the function call the app does not crash.
One possibility that is consistent with what you're describing is that linking to AdMob causes the crash. Sending a message to the GADRequest class in your code causes it to link to the GADRequest class, whereas if you didn't, it wouldn't link to it.
Why does linking to AdMob cause the crash? Most likely it's because AdMob links to several system frameworks, some of which may not exist on iOS 5 (e.g. AdSupport framework), so when it tries to dynamically link to them on app startup, the dynamic linker crashes.
I'm not sure what you can do. Maybe you can try explicitly linking to the system frameworks that AdMob use as "optional" in Xcode? (I haven't tested it.)
Otherwise, you could downgrade to a version of AdMob that supports iOS 5 (according to the release notes, any version before 7 should do).
I dont know why it crashes - but don't support iOS 5. It is pointless. The iOS market split is something like 20% iOS7, 80% iOS8. You cannot buy iOS5 phones, and you cannot install or, or even release apps for it.

XCode setting to see code which won't work on previous OS versions

I've written an app specifically for iOS7, and am now attempting to make it work for iOS6.
I'd really like a setting to enable warnings which highlight lines of code which won't work on iOS6. i.e. any calls to code which ONLY work on iOS7.
That way I can immediately identify any lines of code which I need to attend to before catching them during debugging.
Does this even exist?
There is two option to deal with this.
Use MJGAvailability, a drop in header file and it will make warnings if a selector is "too new".
Buy Delpoymate, it can scan your Xcode project and show you any incompatible calls.
If you use an older Xcode next to the newest, than use this snippet:
if ([self respondsToSelector:#selector(newSelector)]){
#if __IPHONE_7_0
[self newSelector];
#endif
} else {
[self oldSelector];
}
There is no way of getting a warning to appear and even if there was how would the IDE now that you would have done something to handle it like the below
if([myObject respondsToSelect:#selector(myiOS7SelectorOnly)]) {
[myObject myiOS7SelectorOnly];
}
It works the other way if you where developing an app for iOS7 and you used a deprecated method that iOS7 API doesn't use any more it would give you a warning but not the other way you will have to wait for it to turn around and crash and throw an unrecognised selector exception.
At some point I had 2 Xcode installed - Xcode 4 and Xcode 5. Xcode 4 did not have API for ios7 and it was showing all incompatibilities.
But I don't know where can you find XCode4 now and will it still show errors in ios7 code or not?
At least you can try this way.

iOS 7 UIWebView not rendering

I'm porting my app to iOS 7 and I have a problem with UIWebView in iOS 7.
I load local html string in it with this code:
NSURL *baseURL = [NSURL fileURLWithPath: DOCUMENTS_DIRECTORY];
[self.descWebView loadHTMLString:html baseURL:baseURL];
It works perfectly on iOS 6 and prior but on iOS 7 it doesn't rendering and the UIWebView is still white. And this message appears in console:
void SendDelegateMessage(NSInvocation *): delegate
(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)
failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
Thanks for your replies.
As mentioned by #zaplitny, I had to update Crittercism to the latest version (4.1.0) for this problem to go away.
There was a problem with older version of the Crittercism library which caused this. As others have alluded to in comments, this bug was fixed in the 4.3.1 version of the Crittercism SDK.
https://app.crittercism.com/downloads/release_notes/ios/4.3.1 :
fix: Workaround for apps experiencing UIWebViews failing to load data
on first launch when running on iOS 7. This only occurs in apps that
subclass UIWebView, and Crittercism has filed a bug report with Apple.
Note - Be aware that while your application may not directly subclass
UIWebView, this is done in many common 3rd party libraries such as the
Google AdMob and Millenial Media SDKs.
For those of us who updated Crittercism to the version 4.1.2 hoping that it would solve the issue but it didn't. I can offer quite an ugly but simple solution: create and initialize UIWebView before calling [Crittercism enableWithAppID:#"***...***"];
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
...
UIWebView* fakeWebView = [[[UIWebView alloc] initWithFrame:CGRectMake(-1, -1, 1, 1)] autorelease];
[fakeWebView loadHTMLString:#"<!DOCTYPE HTML><html><body>I need Crittercism</body></html>" baseURL:nil];
[mainViewController.view addSubview:fakeWebView];
[Crittercism enableWithAppID:#"***...***"];
...
}
This trick allowed me not only to get rid of a described problem, but also slightly speed up the first initialization of a real UIWebView.
I had this error appearing trying to display admob ads, when ever crittercism was enabled I would get that error in the logs, incidentally the ads were not displaying either.
To fix it, I disabled crittercism instrumentation, this might not be an option for everyone.
[Crittercism enableWithAppID:#"your_app_id" andDelegate:nil andURLFilters:nil disableInstrumentation:YES];
If not simply creating a webview (You don't need to add it as a subview) as suggested by others seems to work for me as well.
[[UIWebView alloc] initWithFrame:CGRectMake(-1, -1, 1, 1)]
[Crittercism enableWithAppID:#"your_app_id"];
Try product --> clean. It can't hurt. When you run an app it will only replace/compile the files that changed. Some times the xCode bugs up and doesn't compile a changed file. Product clean deletes old versions of the compiled code so next time you build it will have been all from the last compile. Again you have nothing to lose by doing it.
I am seeing the same problem you are. I have tried:
moving the load request from the viewDidLoad to the viewWillAppear and viewDidAppear, this did not help anything
tried reloading the webview after the load request was made. still nothing
tried changing the URL creation from URLWithString to fileURLWithPath and still nothing
What is even more strange is that none of the delegate methods fire when the page doesnt load. it is almost as if the web view doesnt even attempt to load the page. Yet, like you said, if you close the app from the multitask view and reopen it, everything works fine.
were you able to figure out a way around this or found a solution?
I had similar issues with my PhoneGap application on IOS7, i had to Redraw the UI of the page on "viewDidAppear" or "Pageshow" using the below code and this worked for me.
$(".cls_div_page_content").redraw();
jQuery.fn.redraw = function() {
return this.hide(0, function(){$(this).show()});
};
many times this error can come in case u are using something that is not available in that particular iOS version..
for example
NSString *test=#"test this";
[test containsString:#"test"];
use of containsString in iOS 7.1 will give you the same following error, but it will work fine in iOS 8.0,
void SendDelegateMessage(NSInvocation *): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:)
failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
I ran into this issue too. It seems the problem is caused when certain 3rd party libraries are linked, but I am not even sure exactly which one was responsible in my case. I didn't have Crittercism in my app.
What fixed it for me was the suggestion I found here on Apple's Dev Forum to instantiate a UIWebView early.
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// In a severe case of WTF: some 3rd party libs (exact culprit unknown) can cause webviews to stop
// showing anything on iOS 7, and instead have console warnings every 10 seconds that look like:
// void SendDelegateMessage(NSInvocation *): delegate (webView:decidePolicyForNavigationAction:request:frame:decisionListener:) failed to return after waiting 10 seconds. main run loop mode: kCFRunLoopDefaultMode
// Just instantiating an UIWebView before any of the 3rd party libs kick in is enough to fix it.
// Don't know why, but it works.
if (SYSTEM_VERSION_LESS_THAN(#"8.0")) {
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
webView.delegate = nil; // Do something with webView to silence warning
}
return YES;
}
For those who are using Parse SDK with the 1.6.x version under iOS7/iOS8 and subclass UIWebView, same problem will appear if you are using PFInstallation saveInBackground method.
Solution is to delay call saveInBackground, e.g.:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3.f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[currentInstallation saveInBackground];
});

Tesseract crash

I am using tesseract on my iOS device and it was working properly until recently it started to crash on me. I have been testing with the same image over and over again and prior to now I had it working about 75 times consecutively. The only thing I can think of is that I deleted the app from my iOS device and then ran it again through Xcode.
I am far from an expert on tesseract and I could really use some advice on what to do next, it would truly be a disappointment for all the hours I put in to go to waste because I cannot read the image anymore. Thank you
This is the crash error it appears to happen when the tesseract file in this method
- (BOOL)recognize {
int returnCode = _tesseract->Recognize(NULL); // here is where the arrow points on the crash
return (returnCode == 0) ? YES : NO;
}
This is the snapshot of the crash

AVAssetWriter finishWriting fails on iOS 6 Simulator

It seems that finishWriting is broken on iOS 6 simulator - it hangs forever. It's now deprecated and replaced by the new finishWritingWithCompletionHandler: - which also never calls the handler.
On real devices running iOS 6, this works just fine as it always did. Also in previous iOS simulators it works just fine. Seems like a bug in iOS 6 simulator.
Anyone else experiencing this or can prove me wrong?
I had this issue as well, then realized that I wasn't calling endSessionAtSourceTime: after starting one. This resolved my issue.
Ok found a work around on Simulator.
Looks like stop deadlocks the video processing thread so a workaround is to call stop in the main thread instead:
// in iOS6 Simulator this blocks the video processing thread call back in UI thread.
// BOOL stop = [assetWriter finishWriting];
[self performSelectorOnMainThread:#selector(stopInOtherThread) withObject:nil];
-(void)stopInOtherThread{
//Stop doesn't block in MainThread
BOOL stop = [assetWriter finishWriting];
NSLog(#" assetWriter finishWriting :%d",stop);
}
This workaround doesn't seem to work for finishWritingWithCompletionHandler
I'll try and see if I can raise a bug on Apple.

Resources