Runtime error when using MPMediaPickerController in iOS Simulator - ios

The following happens when I try to run an app using the MPMediaPickerController on the iOS Simulator.
2012-05-28 22:26:42.416 My App[48426:11f03] Could not load source: 3
2012-05-28 22:26:42.418 My App[48426:11f03] *** Assertion failure in -[MPMediaPickerController loadView], /SourceCache/MediaPlayer_Sim/MobileMusicPlayer-1391.72/SDK/MPMediaPickerController.m:86
2012-05-28 22:26:42.419 My App[48426:11f03] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unable to load iPodUI.framework'
Is this some problem in my App/Xcode/iOS Simulator, or does the iOS Simulator simply not support the MPMediaPickerController? If not, any alternatives, besides running it on a physical device?

MPMediaPickerController does not work in the Simulator. Apple notes this in the "iPod Library Access Programming Guide" under "Hello Music Player". The note says:
Note: To follow these steps you’ll need a provisioned device because
the Simulator has no access to a device’s iPod library.
To prevent the assertion you can always check if you can access the do this in your code (code bellow uses ARC and iOS SDK 5.0).
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
[picker setDelegate:self];
[picker setAllowsPickingMultipleItems:YES];
[picker setPrompt:NSLocalizedString(#"Add songs to play","Prompt in media item picker")];
#try {
[picker loadView]; // Will throw an exception in iOS simulator
[self presentViewController:picker animated:YES completion:nil];
}
#catch (NSException *exception) {
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Oops!",#"Error title")
message:NSLocalizedString(#"The music library is not available.",#"Error message when MPMediaPickerController fails to load")
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
}

Also (if using storyboard) you can try it:
- (IBAction)showPicker:(id)sender
{
#if TARGET_IPHONE_SIMULATOR
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"playerTest"
message:#"Media picker didn't work in simulator, please run this app on device"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
#else
[self performSegueWithIdentifier:#"ShowPickerViewSegue" sender:self];
#endif
}

MPMediaPickerController now works in the iOS Simulator without any additional code changes (at least as of iOS 8, possibly earlier). Here is a project that can demonstrate it: GVMusicPlayerController.
You will have to prepare the music library in the Simulator by copying the necessary files from an actual device, most importantly the MediaLibrary.sqlitedb database files. If you want to play the files and view artwork, you'll also have to copy the iTunes_Control/Music, Purchases and Artwork folders (found in /var/mobile/Media/). See this question for further details: Can i access iPod Library on simulator?.

Related

After iOS 8, can I continue to use UIActionSheet and UIAlertView?

I have apps which use UIActionSheet and UIAlertView.
In iOS8, Apple's documentation and some websites say that they are deprecated in iOS8.
UIActionSheet documentation
Important: UIActionSheet is deprecated in iOS 8. (Note that
UIActionSheetDelegate is also deprecated.) To create and manage action
sheets in iOS 8 and later, instead use UIAlertController with a
preferredStyle of UIAlertControllerStyleActionSheet.
But in Xcode 6 with deployment target 8.0 does not generate warning for the use of UIActionSheet and UIAlertView.
Normally Xcode generates warning for deprecated API.
Why doesn't Xcode generate warnings for UIActionSheet and UIAlertView?
Does this mean Apple does not actually deprecate those classes?
It is very dangerous if they actually deprecated them and Xcode does not generate warnings.
In another apple's documentation "What's New in iOS 8.0" says:
The new UIAlertController class replaces the UIActionSheet and UIAlertViewclasses as the preferred way to display alerts in your app.
https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS8.html
And UIActionSheet and UIAlertView is not listed on Deprecated APIs section of the documentation of the above URL.
So, this documentation means UIAlertController is preferable but UIActionSheet and UIAlertView are also still available in iOS 8.
Should I replace UIActionSheet and UIAlertView in my apps with new UIAlertController class?
Or can I continue to use UIActionSheet and UIAlertView?
It's always best to not use depreciated code, it all adds up for well written code.
So yeah, use UIAlertController.
Yes you should. Preferable leads to deprecated which leads to being cut off suddenly.
Yes, you should replace your code.
When I tried to use in my code some of the functions and delegate methods for both of the Classes UIActionSheet and UIAlertView were not working.
I was getting issues and weird results each time.
Therefore, you should not use deprecated APIs.
I am sure about this, I think if the app is uploaded to App Store with deprecated APIs then that App can be rejected.
It takes a while to figure out the new method, so you might find this code useful. I’m supporting older versions of iOS so I use a conditional to decide which to use. This code runs in my app delegate. If you are running it in a view controller, replace
[self.window.rootViewController presentViewController:alert animated:true completion:nil];
with
[self presentViewController:alert animated:YES completion:nil];
The #define is in my .pch but I put it here since it is what I use in the conditional.
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
- (void)applicationWillEnterForeground:(UIApplication *)application {
if (self.window.rootViewController) {
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
[self displayUIAlertController];
} else {
[self displayUIAlertView];
}
}
}
- (void)displayUIAlertController {
NSString *alertMessage = [NSString stringWithFormat:#"Do you want to resume playing %# or start a new session?", GAME_NAME_TITLE];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"Welcome Back"
message:alertMessage
preferredStyle:UIAlertControllerStyleAlert];
// You can add as many actions as you want
UIAlertAction *startNewSession = [UIAlertAction actionWithTitle:#"Start New Session"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self startNewSession];
}];
UIAlertAction *doNothingAction = [UIAlertAction actionWithTitle:#"Resume"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
// Do nothing
}];
// Add actions to the controller so they will appear
[alert addAction:doNothingAction];
[alert addAction:startNewSession];
// Finally present the action
[self.window.rootViewController presentViewController:alert animated:true completion:nil];
}
- (void)displayUIAlertView {
NSString *messageWithTitle = [NSString stringWithFormat:#"Do you want to resume playing %# or start a new session?", GAME_NAME_TITLE];
self.alertView = [[UIAlertView alloc] initWithTitle:#"Welcome Back"
message:messageWithTitle
delegate:self
cancelButtonTitle:#"Resume"
otherButtonTitles: #"Start New Session",nil];
[self.alertView show];
}
#pragma mark - Alert on restart
// buttonIndex 0 is cancel and the game continues
// buttonIndex 1 is Start New Session and the old results are saved and new session started
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
[self startNewSession];
}
}
Deprecated code typically means that the prior versions are not supported from the version marked and in the future. If you were building a legacy app (or an app that will be supporting prior versions) one should use the UIActionSheet and UIAlertView, however if you are updating code for iOS8+ you should use UIAlertController. The nice thing is that the code you wrote previously will not be affected so users can use a legacy version of the app without problem.
You should be able to continue using UIAlertView and UIActionSheet in iOS8 since they were deprecated in iOS8 and not in iOS7. That said, I've run into similar problems => UIAlertView automatic newline gone in iOS8?. So it appears that we may need to move to UIAlertController faster than we anticipated.

Orientation issue in Landscape mode while opening camera in iOS 7 in iPhone

I am having an app which is only in Landscape Mode. In my app I am opening the Camera from one of my views. It is working well for my iPad but on iPhone it crashes. It is working well in iOS 6 but the app crashes for iOS 7 and only for iPhone.
Below is my code.
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
ipc=[[UIImagePickerController alloc] init ];
ipc.delegate=self;
ipc.sourceType=UIImagePickerControllerSourceTypeCamera;
[self presentViewController:ipc animated:YES completion:nil];
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Desc" message:#"Camera capture is not supported in this device" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
How to solve this issue?
It crashes when I select to capture from camera. It doesn't crash from the above code but after that it crashes with below error.
I am getting this error:
Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'Supported orientations has no common orientation with the application, and shouldAutorotate is returning YES
And my app crashes.
My orientation code on this view.
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight ;
}
I am also getting same problem previously. I followed the steps. Please try this and let me know if your facing same problem.
check mark
Step 1:
check in appdelegate.m
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskAll;
}
step 2: In your view controller
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
if (interfaceOrientation==UIInterfaceOrientationLandscapeLeft || interfaceOrientation==UIInterfaceOrientationLandscapeRight)
return YES;
return NO;
}
Step 3: your view controller
-(IBAction)TakePhoto:(id)sender{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
UIImagePickerController* imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.allowsEditing = YES;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:(NSString *) kUTTypeImage, nil];
[self.view.window.rootViewController presentViewController:imagePicker animated:YES completion:nil];//add to view as per requirement
}
else
{
UIAlertView *noCam = [[UIAlertView alloc] initWithTitle:#"Notification" message:#"There is No Camera Fecility" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[noCam show];
}
}
Does the crash occur on launching the UIImagePickerController or after taking an image with the camera? I tried out your code on an iPod running iOS7 and it works fine. The issue could be somewhere else. I've seen crashes happening with the UIImagePickerController due to memory usage so that could be something for you to check. Also while we're at it, presentModalViewController:animated: is deprecated since iOS6.0. You need to use presentViewController:animated:completion: instead. Also seeing the release statement for your UIAlertView, it looks like you're not using ARC so memory usage is definitely something I would look into. Hope this helps.EDIT: From the UIImagePickerController documentationImportant: The UIImagePickerController class supports portrait mode only. This class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified, with one exception. You can assign a custom view to the cameraOverlayView property and use that view to present additional information or manage the interactions between the camera interface and your code.
Try this code, it works on my old app.
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
May be you want to check this: GameCenter authentication in landscape-only app throws UIApplicationInvalidInterfaceOrientation
I found my solution from the link iOS7 iPad Landscape only app, using UIImagePickerController.
It worked for me like a charm.
Hope it help someone else also.
Thanks for your help people.
I had inherited the UIImagePickerController, and override the tow methods to supported landscape (or you can make a category):
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotate
{
return YES;
}
And add the Portrait (bottom home button), Landscape (left home button), Landscape (right home button) in Supported interface orientations(iPad).
Here, must add the Portrait (bottom home button) value, because the UIImagePickerController just supports portrait mode only, so we need to add the portrait mode, otherwise it will raise an exception.

UIAlertView button not working

I want the cancel button of my UIAlertView to launch the app store so that my app can be updated. I can get the app to launch the app store, but I want it to launch only when the cancel button of my UIAlertView is pressed. The way I have it now, I'm given this error when I press the cancel button:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType alertView:clickedButtonAtIndex:]: unrecognized selector sent to instance 0x1651bd90'
Here's the code where I initialize and display the UIAlertView:
NSString* updateString = #"Please update the app! Thank you!";
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Please Update" message:updateString delegate:self cancelButtonTitle:#"Update Now" otherButtonTitles:nil];
[alert show];
Here's the function that's supposed to handle the cancel button being pressed:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"itms://itunes.com/apps/appname"]];
}
I've written in the containing object's header file that it follows the UIAlertViewDelegate protocol.
What am I doing wrong here?
You might be released the object that was calling this piece of code. If you are using ARC please make it a property.

give ios simulator permission to access photo albums [duplicate]

This question already has answers here:
iOS stopped asking user for Photo Library Permission
(6 answers)
Closed 8 years ago.
I've an iphone app where the user is able to upload photos. During test on ios simulator, everytime I click the "upload image" button, the simulator pops up an alert that says I should give the app permission to access photo albums.
The problem is that the simulator never asked me before if I want to give it access or not. And when I go to privacy settings on the simulator -> photos, I do no see the app to toggle it ON!
I tried resetting content & settings of the simulator, but that didn't solve the problem.
I'm using xCode 5.0.2
Simulator 7.0 iOS 6.1 simulator component
did you check Settings->Privacy->Photos? you should allow your app have full access here.
add following code to somewhere
UIImagePickerController* picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:Nil];
remember to add this function to handle picked image
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissViewControllerAnimated:YES completion:nil];
}
try this then to see what happened on your machine.
I found the problem
There is code
if (status != ALAuthorizationStatusAuthorized) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert" message:#"Please give the app access to photo album" delegate:nil cancelButtonTitle:#"Close" otherButtonTitles:nil, nil];
[alert show]; }
I changed:
if (status != ALAuthorizationStatusAuthorized) {
to
if (status == ALAuthorizationStatusDenied) {
Then it worked and asked me for permission, accepted it, and everything is ok now
Thanks everyone

UIDocumentInteractionController disable open in certain apps

I'm currently using a UIDocumentInteractionController for open in functionality. When it opens it shows a list of all apps on the device that can handle that file type.
Is there a way to disable my app sending a document to specific apps, even if they support that file type? For example - if I have a PDF file open in my app and iBooks is on the iPad, if I tap the iBooks icon in the UIDocumentInteractionController, I don't want it to send it to the app.
Ideally - I see this as building a blacklist (or whitelist). For example, it would be great to do this:
- (void) documentInteractionController: (UIDocumentInteractionController *) controller willBeginSendingToApplication: (NSString *) application {
// if app is blacklisted
if ([application isEqualToString:#"com.schimera.WebDAVNavigator"]) {
[self.interactionController dismissMenuAnimated:YES];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"FAIL" message:#"NO" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
return
}
}
With this however, the document is still sent to the application even if it is "black listed".
Is this approach at all possible?
Cheers!
Change the UIDocumentInteractionController's URL to an invalid value if the app is blacklisted. In the method -[UIDocumentInteractionControllerDelegate documentInteractionController: willBeginSendingToApplication:].
-(void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application
{
if([application isEqualToString:#"com.evilcorp.badapp"){
controller.URL = nil;
}
}
To offer open file in a specific app (as white list), just add (using swift 3.0):
docController.uti = #"com.yourapp.package";

Resources