UIAlertView breaks AVPlayer's audio process - ios

I have a basic iOS app that uses an AVPlayer to play local files with an MTAudioProcessingTap attached. I added a UIAlertView pop-up with a text field to allow custom URLs to be added to the app's playlist, but when the alert is shown using [alert show], the audio system fails. If I show the alert before any track has been played, start playing a track, and then show the alert again it works fine — almost as if there's some CPU-spike penalty for the first show (though I can't see anything on instruments).
Alert:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Play Remote Track"
message:#"Enter the address."
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Play", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
Errors:
Log message: <ClientProcessingTapManager> AudioQueueProcessingTapGetSourceAudio posting message to kill mediaserverd (36078)
MTAudioProcessingTapGetSourceAudio() returns status code 268451843 then on the next packet 268435459.
Update: The issue only happens while debugging, so it turns out it's not a showstopper. I'd still be interested in getting to the bottom of it, though.

Try this:
#import <dispatch/dispatch.h>
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Play Remote Track"
message:#"Enter the address."
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Play", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
});
If it doesn't help, then try to look on MTAudioProcessingTap Audio Processor Sample Code. I have tried to put your AlertView call to different places while video was showing, and everything was ok - no bugs. It was iPad Simulator v. 6.1.

Just to put this one to bed, I eventually concluded that it was a performance issue. In all other circumstances I've come across, AudioQueueProcessingTapGetSourceAudio posting message to kill mediaserverd (36078) seems to be called when you're doing "too much" work inside the MTAudioProcessingTap process loop. I think showing the UIAlertView in my case was pushing the device over the edge.
As for what constitutes "too much" work, I have no idea, and there's no mention in any of the documentation in the header file for MTAudioProcessingTap. On several devices I tested my app on, I could increase the work done in the audio loop until overall CPU was at about 20%, then the kill message appeared and the tap stopped calling its processing callback. It must either be an artificially imposed limit, or for some reason my process loop couldn't fulfil its real time guarantee regardless of the amount of CPU used.

Related

Xcode Webview Internet Connection alert

so i have finished making my application and i am wondering is it mandatory to add code that checks if the user has a valid connection to the internet or not? one of the reasons I'm asking this is because in my previous app i used this piece of code below.
- (void) webView:(UIWebView*) webview didFailLoadWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Important" message:#"Sorry,
it seems you are not currently connected to a network, please try again later." delegate:self
cancelButtonTitle:#"I understand" otherButtonTitles: nil];
[alert show];
}
I used this i believe with Xcode 4 and iOS 6 i believe has something changed in the Xcode 5.1.1 and iOS 7, or am i doing something wrong. Sorry to sound stupid but its really bugging me.
Thank you
It is not needed, and is not specified anywhere in Apple's terms and conditions. However, it is kind of a standard procedure to warn your user if he encounters some kind of problem. I would strongly suggest that you implement these delegate methods.

Bring up the "App Would Like to Use Your Current Location" dialogue again [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Is it possible to call alert “Allow to use current location” manually?
in my app, all of the functionality is based on the users current location. The audience is everything else than geeky.
I think about the user starts the app for the first - as a user is not really sure about what it can do, s/he might be confused about the app's "Would Like to Use Your Current Location?" If he answers with "Don't allow", he won't get any data on the screen.
Now I handle:
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
if (error.code == kCLErrorDenied) {
NSLog(#"Location manager denied access - kCLErrorDenied");
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:#"Location issue"
message:#"Your location cannot be determined."
delegate:self
cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
Okay, the app has a Reload-Button. Assuming the user taps that reload button, he will not get asked again by the system to enable location based services.
How could I force iOS to ask for current location again?
There is no way you could force this dialog to show again. iOS will ask the user again on the next start-up of the app. By start-up I do not mean entering the foreground after the app was sent to the background.
Currently, the only fast way to do this is appears to be to ask the user to restart the app and then crash (or set the UIApplicationExitsOnSuspend key and launch Safari). When the user relaunches the app, the dialog will be available.
This may or may not get your app promptly rejected when Apple reviews it.

UIAlertView shown from background thread and with no delegate creates EXC_BAD_ACCESS

Here is my code:
#ifdef DEBUG
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"JSON Parsing Error" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
#endif
This code is executed in a background thread (responsible for parsing), and the error only happens every other time. Any idea on what is the problem here?
Dont mess with the UI from the background thread. Create a method and call that method on the main thread:
[someObject performSelectorOnMainThread:#selector(showDebug:)
withObject:#"JSON Parsing Error"
waitUntilDone:YES];
You shouldn't execute UI code in separate thread.
If your application has a graphical user interface, it is recommended
that you receive user-related events and initiate interface updates
from your application’s main thread. This approach helps avoid
synchronization issues associated with handling user events and
drawing window content. Some frameworks, such as Cocoa, generally
require this behavior, but even for those that do not, keeping this
behavior on the main thread has the advantage of simplifying the logic
for managing your user interface.
Threads and Your User Interface

Close app when internet is not available

I want to close my app when an Internet connection is not available.
I check that, but how can I create an alert, and then close my app?
You shouldn't force close an app as the standard way to terminate an application is to press the home button (or use the multitasking bar)
Don’t Quit Programmatically
Never quit an iOS application programmatically because people tend to
interpret this as a crash. However, if external circumstances prevent
your application from functioning as intended, you need to tell your
users about the situation and explain what they can do about it.
Depending on how severe the application malfunction is, you have two
choices.
Display an attractive screen that describes the problem and suggests a
correction. A screen provides feedback that reassures users that
there’s nothing wrong with your application. It puts users in control,
letting them decide whether they want to take corrective action and
continue using your application or press the Home button and open a
different application
If only some of your application's features are not working, display
either a screen or an alert when people activate the feature. Display
the alert only when people try to access the feature that isn’t
functioning.
Source
Your app should never close itself. iOS does not have the concept of quitting an app. You can inform the user that there is no internet connectivity and present a waiting screen or something else that shows them that your app is useless until the internet connection is available, but your app should continue running until the OS decides to shut you down.
Instead of closing it, consider explaining the situation to the user by the means of a popup.
First of all, download Reachability from Apple.
Add the classes Reachability.h,.m,delegates to your project. Then in your .m class import Reachability
#import "Reachability.h"
And in viewWillAppear or when you should display the alert:
//Connection check
Reachability *reach = [Reachability reachabilityForInternetConnection];
NetworkStatus netStatus = [reach currentReachabilityStatus];
if (netStatus == NotReachable)
{
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"No Internet Connection" message:#"Explain the situation to the user" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alert show];
[alert release];
}
else {
//other actions.
}
As others said before me.
According to August's ans here
"On the iPhone there is no concept of quitting an app. The only action that should cause an app to quit is touching the Home button on the phone, and that's not something developers have access to.
According to Apple, your app should not terminate on its own. Since the user did not hit the Home button, any return to the Home screen gives the user the impression that your app crashed. This is confusing, non-standard behavior and should be avoided."
But if you still want to quit your app programmatically then
there are two commands to quit the app.
1.exit(0)
2.[[NSThread mainThread] exit]

SKProductsRequest - how to handle timeouts / connection errors?

Cheers,
It appears to me like SKProductsRequest does not handle timeouts or connection errors in any way. It either calls -(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response on its delegate in case of success, or it doesn't.
I'd like to present my users with some kind of activity indicator while the products are being retrieved, or maybe pop up an alert if the appstore can't be reached. Since (in case of failure) there's no feedback from the SKProductsRequest however, I wonder to which event I should tie the presentation of that feedback - other then waiting for an arbitrary amount of time.
So, the question is: Is there a known amount of time after which it is safe to assume the request has failed? Or is there any way to check upon the status of a pending request that I just failed to see?
I run this in my project for whenever an SKRequest fails (which includes SKProductRequest):
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
alert = [[UIAlertView alloc] initWithTitle:#"In-App Store unavailable" message:#"The In-App Store is currently unavailable, please try again later." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
Works a treat. Of course you can place anything inside the brackets to replace my alert, but this works well for the user.
Hope this is of use to you.
Note: This is in SKRequestDelegate not in SKProductsRequestDelegate, which is slightly confusing. The SKRequestDelegate is used for purchasing and for product requests. The delegate set using request.delegate can implement methods for both.
I don't believe you can do anything other than wait an arbitrary amount of time. In some of my apps I wait 30 seconds (while showing a modal activity view) and then bail out with a generic error alert. The problem is, in reality 30 seconds is beyond most users' attention span for such issues, but if you make it short enough to be useful (say 15 seconds), you might actually bail too early.
I don't think there is a better option ... but I'm willing to learn otherwise!

Resources