I am programming to get the iPhone music library to display, the user selects a song, then this song title is reflected in a UILabel. If only it was that simple! I have tried getting the MPMediaItem into a NSString then the UILabel reflecting this, but i'm just getting (null) returned!
- (IBAction)showMediaPicker:(id)sender {
MPMediaPickerController *mediaPicker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAny];
mediaPicker.delegate = self;
//mediaPicker.allowsPickingMultipleItems = YES;
mediaPicker.prompt = #"Select Your Favourite Song!";
[self presentModalViewController:mediaPicker animated:YES];
}
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItem *) mediaItemCollection {
NSString *titleString = [mediaItemCollection valueForProperty:MPMediaItemPropertyTitle];
titleLabel.text = [NSString stringWithFormat:#"Title: %#",titleString];
[self dismissModalViewControllerAnimated: YES];
}
Thanks in advance
You're trying to grab the title for a mediaItemCollection. You need to get the individual song title like this:
MPMediaItem *selectedSong = [mediaItemCollection items] objectAtIndex:0];
NSString *titleString = [selectedSong valueForProperty:MPMediaItemPropertyTitle];
Also by the way, you have the wrong delegate setup for your MPMediaPickerControllerDelegate:
It should be:
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
-You have the MPMediaItemCollection as just an MPMediaItem
Related
I want to access music files which are available on the iPhone and get it listed (or) get the file into my iPhone application some delegats and start playing it. Is it possible to do it ? Similar to how we access images from device photo album using UIImagePickerController delegate methods.
Thank you!
You can reference MPMediaPickerController class. It functions same as UIImagePickerController class.
-(void)loadDeviceMusic{
MPMediaQuery *everything = [[MPMediaQuery alloc] init];
[everything addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithBool:NO] forProperty:MPMediaItemPropertyIsCloudItem]];
NSArray *itemsFromGenericQuery = [everything items];
for (MPMediaItem *song in itemsFromGenericQuery) {
NSURL *assetURL = [song valueForProperty:MPMediaItemPropertyAssetURL];
AVAsset *asset = [AVAsset assetWithURL:assetURL];
NSLog(#"SONGS URL=%#",assetURL);
if ([asset hasProtectedContent] == NO) {
MP3ObjectsClass *objMp3=[[MP3ObjectsClass alloc] init];
objMp3.mp3Url=[song valueForProperty:MPMediaItemPropertyAssetURL];
objMp3.mp3Duration=[song valueForProperty: MPMediaItemPropertyPlaybackDuration];
if([song valueForProperty: MPMediaItemPropertyTitle]){
objMp3.mp3Name=[song valueForProperty: MPMediaItemPropertyTitle];
}else{
objMp3.mp3Name=#"Unknown";
}
if([song valueForProperty: MPMediaItemPropertyArtist]){
objMp3.mp3ArtistName=[song valueForProperty: MPMediaItemPropertyArtist];
}else{
objMp3.mp3ArtistName=#"Unknown";
}
if([song valueForProperty: MPMediaItemPropertyAlbumTitle]){
objMp3.mp3AlbumTitle=[song valueForProperty: MPMediaItemPropertyAlbumTitle];
}else{
objMp3.mp3AlbumTitle=#"Unknown";
}
UIImage *mp3Image=[self getAlbumnArtWorkImage:assetURL];
if(mp3Image){
objMp3.mp3Image=mp3Image;
}else{
objMp3.mp3Image=[UIImage imageNamed:#"DefaultImage"];
}
[mp3Array addObject:objMp3];
}
}
}
-(UIImage *)getAlbumnArtWorkImage :(NSURL *)mp3Url{
AVAsset *asset = [AVURLAsset URLAssetWithURL:mp3Url options:nil];
UIImage *img = nil;
for (NSString *format in [asset availableMetadataFormats]) {
for (AVMetadataItem *item in [asset metadataForFormat:format]) {
if ([[item commonKey] isEqualToString:#"artwork"]) {
img = [UIImage imageWithData:[item.value copyWithZone:nil]];
}
}
}
return img;
}
*** MP3ObjectsClass is a NSObject class. Using above function you can access device music files from iPhone.
First import the AVFoundation/AVFoundation.h framework.
#import <AVFoundation/AVFoundation.h>
-(void)pickAudioFiles
{
MPMediaPickerController *soundPicker=[[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
soundPicker.delegate=self;
soundPicker.allowsPickingMultipleItems=NO;
[self presentViewController:soundPicker animated:YES completion:nil];
}
-(void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
MPMediaItem *item = [[mediaItemCollection items] objectAtIndex:0];
NSURL *url = [item valueForProperty:MPMediaItemPropertyAssetURL];
[mediaPicker dismissViewControllerAnimated:YES completion:nil];
AVPlayerItem *playerItem=[AVPlayerItem playerItemWithURL:url];
AVPlayer *player=[[AVPlayer alloc] initWithPlayerItem:playerItem];
AVPlayerLayer *playerLayer=[AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.frame=CGRectMake(0, 0, 10, 10);
[self.view.layer addSublayer:playerLayer];
}
and play with [player play];
If you want to use AVAudioPlayer then import AudioToolbox/AudioToolbox.h
Hi I'm new to iOS development. I want to pick a contact from default contacts app. For that i created an application that lets user to pick a contact from the iPhone default contacts app. For iOS 9+ version, I'm using the following snipped.
- (IBAction)btnAction:(id)sender {
CNContactPickerViewController *contactPicker = [[CNContactPickerViewController alloc] init];
contactPicker.delegate = self;
contactPicker.displayedPropertyKeys = (NSArray *)CNContactGivenNameKey;
[self presentViewController:picker animated:YES completion:nil];
}
-(void) contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact{
NSLog(#"Contact : %#",contact);
}
-(void)contactPickerDidCancel:(CNContactPickerViewController *)picker {
NSLog(#"Cancelled");
}
I also added CNContactPickerDelegate delegate in my uiviewcontroller. When i execute the above code, it opens the contacts app, But when Tap a contact the app becomes blank.
Thanks in advance and can anyone please share your knowledge to use CNContactPickerViewController in Objective-C.
The issue is caused by this code:
contactPicker.displayedPropertyKeys = (NSArray *)CNContactGivenNameKey;
The displayedPropertyKeys expects an NSArray which contains NSString values. In your code, you are trying to type cast an NSString to NSArray and set as the value of this property.
You need to change your code to:
contactPicker.displayedPropertyKeys = #[CNContactGivenNameKey];
#pragma mark - CNContactPickerViewController Delegate method implementation
(void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact
{
NSMutableArray *contactNumberArray = [[NSMutableArray alloc]init];
selectedName=[NSString stringWithFormat:#"%#",contact.givenName];
NSLog(#"%#",selectedName);
NSString *tempString = [NSString stringWithFormat:#"name : %# %# %#\n",contact.givenName, contact.familyName, contact.organizationName];
// // 1. (Phone Numbers)
tempString = [NSString stringWithFormat:#"%#phoneNumbers : ",tempString];
// NSArray*phoneNumber = contact.phoneNumbers;
for (CNLabeledValue *phoneNumber in contact.phoneNumbers)
{
CNPhoneNumber *phone = phoneNumber.value;
tempString = [NSString stringWithFormat:#"%#<%#>",tempString,phone.stringValue];
[contactNumberArray addObject:phone];
selectedPhNumber=[[NSString stringWithFormat:#"%#",phone.stringValue] stringByReplacingOccurrencesOfString:#" " withString:#""];
NSLog(#"%#",selectedPhNumber);
}
//2. (Emails)
tempString = [NSString stringWithFormat:#"%#\n Email : ",tempString];
for (CNLabeledValue *email in contact.emailAddresses)
{
selectedEmail=[NSString stringWithFormat:#"%#", email.value];
tempString = [NSString stringWithFormat:#"%#<%#>",tempString,email.value];
[contactNumberArray addObject:email];
NSLog(#"%#",selectedEmail);
}
[self sendRefferelDetailsToServer];
}
-(void)contactPicker:(CNContactPickerViewController *)picker didSelectContacts:(NSArray<CNContact *> *)contacts{
NSLog(#" %#",contacts);
CNContact *contact=[contacts objectAtIndex:0];
NSLog(#"name = %#",contact.givenName);
}
[1]: https://i.stack.imgur.com/9Sp1G.png use above code to for fetch given name from multiple selections,
comment the following line and try again.
//contactPicker.displayedPropertyKeys = (NSArray *)CNContactGivenNameKey;
In my project I'm using WSAssetPickerController.
Despite the toolbar not working (not a huge issue), everything is working fine.
I have added a share button in the view controller, but I can't seem to get the UIDocumentInteractionController to get called, I tried copying the same method I'm using for files saved in the apps folder (which works fine). But here it's not.
How the irrelevant Downloads page works:
NSString *fileName = [directoryContents objectAtIndex:indexPath.row];
NSString *path;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"Downloads"];
path = [path stringByAppendingPathComponent:fileName];
documentController = [[UIDocumentInteractionController alloc] init];
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]];
[documentController setDelegate:self];
[documentController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
How the images get loaded:
#pragma mark - Fetching Code
- (void)fetchAssets
{
// TODO: Listen to ALAssetsLibrary changes in order to update the library if it changes.
// (e.g. if user closes, opens Photos and deletes/takes a photo, we'll get out of range/other error when they come back.
// IDEA: Perhaps the best solution, since this is a modal controller, is to close the modal controller.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.assetsGroup enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if (!result || index == NSNotFound) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
self.navigationItem.title = [NSString stringWithFormat:#"%#", [self.assetsGroup valueForProperty:ALAssetsGroupPropertyName]];
});
return;
}
WSAssetWrapper *assetWrapper = [[WSAssetWrapper alloc] initWithAsset:result];
dispatch_async(dispatch_get_main_queue(), ^{
[self.fetchedAssets addObject:assetWrapper];
});
}];
});
[self.tableView performSelector:#selector(reloadData) withObject:nil afterDelay:0.5];
}
How I load and call the button:
- (void)viewDidLoad
{
self.navigationItem.title = #"Loading";
UIBarButtonItem *shareButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAction
target:self
action:#selector(shareAction:)];
self.navigationItem.rightBarButtonItem = shareButton;
self.navigationItem.rightBarButtonItem.enabled = NO;
// TableView configuration.
self.tableView.contentInset = TABLEVIEW_INSETS;
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.allowsSelection = NO;
// Fetch the assets.
[self fetchAssets];
}
Should and did select fetched assets
#pragma mark - WSAssetsTableViewCellDelegate Methods
- (BOOL)assetsTableViewCell:(WSAssetsTableViewCell *)cell shouldSelectAssetAtColumn:(NSUInteger)column
{
BOOL shouldSelectAsset = (self.assetPickerState.selectionLimit == 0 ||
(self.assetPickerState.selectedCount < self.assetPickerState.selectionLimit));
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSUInteger assetIndex = indexPath.row * self.assetsPerRow + column;
WSAssetWrapper *assetWrapper = [self.fetchedAssets objectAtIndex:assetIndex];
if ((shouldSelectAsset == NO) && (assetWrapper.isSelected == NO))
self.assetPickerState.state = WSAssetPickerStateSelectionLimitReached;
else
self.assetPickerState.state = WSAssetPickerStatePickingAssets;
return shouldSelectAsset;
}
- (void)assetsTableViewCell:(WSAssetsTableViewCell *)cell didSelectAsset:(BOOL)selected atColumn:(NSUInteger)column
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// Calculate the index of the corresponding asset.
NSUInteger assetIndex = indexPath.row * self.assetsPerRow + column;
WSAssetWrapper *assetWrapper = [self.fetchedAssets objectAtIndex:assetIndex];
assetWrapper.selected = selected;
// Update the state object's selectedAssets.
[self.assetPickerState changeSelectionState:selected forAsset:assetWrapper.asset];
// Update navigation bar with selected count and limit variables
dispatch_async(dispatch_get_main_queue(), ^{
if (self.assetPickerState.selectionLimit) {
self.navigationItem.title = [NSString stringWithFormat:#"%# (%lu/%ld)", [self.assetsGroup valueForProperty:ALAssetsGroupPropertyName], (unsigned long)self.assetPickerState.selectedCount, (long)self.assetPickerState.selectionLimit];
}
});
if (self.assetPickerState.selectedCount == 0) {
self.navigationItem.rightBarButtonItem.enabled = NO;
}
else {
self.navigationItem.rightBarButtonItem.enabled = YES;
}
}
Work needed to below with example from the download code I have used before.
-(void)shareAction:(id)sender {
//Launch UIDocumentInteractionController for selected images
documentController =[[UIDocumentInteractionController alloc]init];
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath://Code needed here??//]];
documentController.delegate=self;
[documentController presentOpenInMenuFromRect:CGRectZero inView:self.view animated:YES];
}
What would be the best practice to do this?
Thanks.
UPDATE 8/4:
-(void)shareAction:(id)sender {
//Launch UIDocumentInteractionController for selected images
if (self.assetPickerState.selectedCount >= 1) {
documentController = [[UIDocumentInteractionController alloc] init];
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:#"public.image"]];
[documentController setDelegate:self];
[documentController presentOptionsMenuFromRect:CGRectZero inView:self.view animated:YES];
}
}
Returns: Unable to get data for URL: The operation couldn’t be completed. (Cocoa error 260.)
Your interactionControllerWithURL: doesn't seem to be a problem but I have observed that -presentOpenInMenuFromRect: does not show if there are no apps that can open the file.
If your purpose is to share the file, and generally that doesn't mean open the file in the conventional sense, then instead of:
-presentOpenInMenuFromRect:inView:animated:
use
-presentOptionsMenuFromRect:inView:animated:
The former is an OpenInMenu and latter is an OptionsMenu.
For the tiny difference, check my related answer or check Apple doc directly
Example:
//this seems fine
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]];
//do this
[documentController presentOptionsMenuFromRect:CGRectZero
inView:self.view
animated:YES];
Also..., just before you present the documentInteractionController, it's good practice to specify the file's UTI so the documentInteractionController can populate itself with the appropriate options that can be performed & the list of all apps that can handle this file:
Example:
//assuming the file is a PDF
[documentController setUTI:#"com.adobe.pdf"];
//or... same thing but a more standardized way would be
[documentController setUTI:(NSString *)kUTTypePDF];
//but for this second style you'll need to add the `MobileCoreServices` framework
//to your project bundle and specify the following in your .h or .m
//#import <MobileCoreServices/MobileCoreServices.h>
Extra: Apple's Uniform Type Identifiers Reference
I am using tab bar in my iOS app. When I tap on the scan tab, i invoked the delegate method to start the camera immediately on scan tab. When I start the camera to scan the QR Code and tap on cancel button before scanning, I get the blank view. How to display the view when camera is dismissed
- (void) openCameraScanner
{
ZBarReaderViewController *reader = [[ZBarReaderViewController alloc] init];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;
reader.showsZBarControls = YES;
ZBarImageScanner *scanner = reader.scanner;
[scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 0];
[self presentViewController:reader animated:YES completion:nil];
reader.showsZBarControls = YES;
//reader.cameraOverlayView = [self commonOverlay];
}
- (void) imagePickerController: (UIImagePickerController*) reader
didFinishPickingMediaWithInfo: (NSDictionary*) info
{
// ADD: get the decode results
id<NSFastEnumeration> results =
[info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
// EXAMPLE: just grab the first barcode
break;
// EXAMPLE: do something useful with the barcode data
//resultsView.text = symbol.data;
NSString *urlString = symbol.data;
NSURL *url = [NSURL URLWithString:urlString];
NSLog(#"Query after scan = %#", [url query]);
//Extract id from URL which is there in QR Code --- start
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
for(NSString *param in [urlString componentsSeparatedByString:#"&"])
{
NSArray *elements = [param componentsSeparatedByString:#"="];
if([elements count]<2)
continue;
[dictionary setObject:[elements objectAtIndex:1] forKey:[elements objectAtIndex:0]];
NSLog(#"value is == %#", [elements objectAtIndex:1]);
//Extract id from URL which is there in QR Code --- end
if([[elements objectAtIndex:1] intValue])
{
NSUserDefaults *defaultsForAsk = [NSUserDefaults standardUserDefaults];
idToAsk = [NSString stringWithFormat:#"%d",[[elements objectAtIndex:1] intValue]];
[defaultsForAsk setObject:idToAsk forKey:#"IDTOASKVIEW"];
flagToShowView = YES;
listViewCntrl.getFlag = flagToShowView;
[self viewDidLoadForDynamicFields];
}
else if([elements objectAtIndex:1] == [NSNull null])
{
[reader dismissViewControllerAnimated:YES completion:Nil];
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Invalid QR Code scanned" message:#"Please scan Collaborator's QR Code" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[message show];
}
}
image.image =
[info objectForKey: UIImagePickerControllerOriginalImage];
// ADD: dismiss the controller (NB dismiss from the *reader*!)
//[reader dismissViewControllerAnimated:YES completion:nil];
[reader dismissViewControllerAnimated:YES completion:Nil];
}
You can re display the view using -(void)viewWillAppear:(BOOL)animated method of your ViewController class.
I try to show with QlPreviewController a pdf from internet url without download it.
This is my code:
NSURL* url2 = [NSURL URLWithString:#"http://wwww.myweb.com/files/terms_en.pdf"];
// Check if can be shown
if(![QLPreviewController canPreviewItem:url2]) {
// cant show document
NSLog(#"can't show document");
}else {
NSLog(#"can show document");
// Show the document in preview
// _previewItemURL = url;
QLPreviewController* preview = [[QLPreviewController alloc] init];
[preview setDataSource:url2];
}
But it didn't show anything. In addition I have a warning in the last sentence [preview setDataSource:url2] saying 'Sending 'NSURL *_strong' to parameter of incompatible type 'id
As per the documentation, QLPreviewController requires NSFileURL, i.e. local files. Download your web resource with other means (e.g. NSData dataWithContentsOfURL), write to disk, and then feed the local URL to it.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
QLPreviewController *previewController = [[QLPreviewController alloc] init];
[previewController setDataSource:self];
[previewController setDelegate:self];
previewController.currentPreviewItemIndex = indexPath.row;
[self presentModalViewController:previewController animated:YES];
}
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller
{
return [self.arrayForPDFList count];
}
- (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
NSString *pathForPdf =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
pathForPdf = [pathForPdf stringByAppendingFormat:#"/%#.pdf",[self.arrayForPDFList objectAtIndex:index]];
return [NSURL URLWithString:pathForPdf];
}