I am trying to get images on contacts,here i used UICollectionViewCell but in the collection view i didn't get image for the contact,i get only name and number.Here my code is
- (IBAction)ContactDisplay:(id)sender {
_addressBookController = [[ABPeoplePickerNavigationController alloc] init];
[_addressBookController setPeoplePickerDelegate:self];
[self presentViewController:_addressBookController animated:YES completion:nil];
}
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person
{
[self displayPerson:person];
}
- (void)displayPerson:(ABRecordRef)person
{
NSString* name = (__bridge_transfer NSString*)ABRecordCopyValue(person,
kABPersonFirstNameProperty);
NSLog(#"%#",name);
NSString* phone = nil;
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person,
kABPersonPhoneProperty);
if (ABMultiValueGetCount(phoneNumbers) > 0) {
phone = (__bridge_transfer NSString*)
ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
} else {
phone = #"[None]";
}
NSLog(#"%#",phone);
UIImage *img ;
if (person != nil && ABPersonHasImageData(person)) {
if ((&ABPersonCopyImageDataWithFormat) != nil ) {
img= [UIImage imageWithData:(__bridge NSData *)ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail)];
}
} else {
NSString *imageUrlString = #"http://www.google.co.in/intl/en_com/images/srpr/logo1w.png";
NSURL *url = [NSURL URLWithString:imageUrlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
img= [UIImage imageWithData:data];
}
NSString *string ;//
string =[NSString stringWithFormat:#"%#",img];
NSLog(#"%#",img);
self.name.text=name;
self.number.text=phone;
[self.nameArray addObject:name];
[self.imageArray addObject:string];
NSLog(#"%#",self.nameArray);
NSLog(#"%#",self.imageArray);
[self.collectionView reloadData];
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:nil];
}
finally an image array i got like this
(
"add-button.png",
"<UIImage: 0x17e56c80>, {148, 148}"
)
On image array every image like display .PNG format it will display fine ,then how can modify it.
Can you please suggest me how can you solve this,thank you.
I don't fully agree with everything you're doing there but I think you're getting your data wrong. Try using this instead when you're fetching the ABPerson image data.
if (person != nil) {
CFDataRef imageData = ABPersonCopyImageData(person);
NSData *data = CFBridgingRelease(imageData);
if (data != nil && data.length > 10){ //arbitrary length to make sure our data object isnt' really empty
img = [UIImage imageWithData:data];
} else {
NSString *imageUrlString = #"http://www.google.co.in/intl/en_com/images/srpr/logo1w.png";
NSURL *url = [NSURL URLWithString:imageUrlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
img= [UIImage imageWithData:data];
}
Then don't store your images as Strings in your array. Store them either as NSData or UIImage, but NOT STRINGS.
so
[myArray addObject:img]; //not the string.
And when you fetch it later, make sure you treat is as an image and not as a string
on your storyboard, select the image and look at the properties panel.
there are "Installed" options at the bottom. check the topmost "Installed" box.
I think there might be issue with conversion of image to string
NSString *string ;//
string =[NSString stringWithFormat:#"%#",img];
Add image to image array without converting to string
[self.imageArray addObject:img];
I do it like this in my app. Assuming 'person' is an ABRecordRef.
NSMutableDictionary *contactInfoDict = [[NSMutableDictionary alloc]
initWithObjects:#[#"", #"", #"", #""]
forKeys:#[#"firstName", #"lastName", #"birthday", #"picture"]];
CFTypeRef generalCFObject;
// Firtname
generalCFObject = ABRecordCopyValue(person, kABPersonFirstNameProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:#"firstName"];
CFRelease(generalCFObject);
}
// Lastname
generalCFObject = ABRecordCopyValue(person, kABPersonLastNameProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:#"lastName"];
CFRelease(generalCFObject);
}
// Birthday
generalCFObject = ABRecordCopyValue(person, kABPersonBirthdayProperty);
if (generalCFObject) {
[contactInfoDict setObject:(__bridge NSString *)generalCFObject forKey:#"birthday"];
NSLog(#"Date : %#", [contactInfoDict objectForKey:#"birthday"]);
CFRelease(generalCFObject);
}
// User image
CFDataRef photo = ABPersonCopyImageData(person);
if (photo) {
CFRelease(photo);
UIImage *image = [UIImage imageWithData:(__bridge NSData*)photo];
[contactInfoDict setObject:image forKey:#"picture"];
}
Related
i´m trying to obtain the imagen from this url[#"file:///var/mobile/Media/DCIM/100APPLE/IMG_0158.JPG"], but i can´t.
Always is nil.
this is my code:
NSData *data = [NSData dataWithContentsOfURL: #"file:///var/mobile/Media/DCIM/100APPLE/IMG_0158.JPG"];
UIImage *image = [UIImage imageWithData:data];
self.pruebaTmp.image = image;
i obtain the url with this code:
if (asset) {
// get photo info from this asset
PHImageRequestOptions * imageRequestOptions = [[PHImageRequestOptions alloc] init];
imageRequestOptions.synchronous = YES;
[[PHImageManager defaultManager]
requestImageDataForAsset:asset
options:imageRequestOptions
resultHandler:^(NSData *imageData, NSString *dataUTI,
UIImageOrientation orientation,
NSDictionary *info)
{
NSURL *path = [info objectForKey:#"PHImageFileURLKey"];
//asignamos el path de la imágen seleccionada en galeria
self.pathImagen = path;
}];
}
if someone could help i would be very grateful, because i can´t load the image with the url obtained.
you can`t not get UIimage or metadata from that url.
you can get UIImage from local Identifier of access
PHFetchResult *savedAssets = [PHAsset fetchAssetsWithLocalIdentifiers:#[localIdentifier] options:nil];
[savedAssets enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) {
//this gets called for every asset from its localIdentifier you saved
//PHImageRequestOptionsDeliveryModeHighQualityFormat
PHImageRequestOptions * imageRequestOptions = [[PHImageRequestOptions alloc] init];
imageRequestOptions.synchronous = NO;
imageRequestOptions.deliveryMode = PHImageRequestOptionsResizeModeFast;
imageRequestOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
[[PHImageManager defaultManager]requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFill options:imageRequestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(#"get image from result");
if (result) {
}
}];
imageRequestOptions = nil;
}];
My app when I run it on my phone I get this error:
I just tried to parse a json and trying to use images in two column of custom cell, but my images on scroll are mis-placed.
int index=indexPath.row*2;
int newindex=index+1;
NSDictionary *u = [[results objectAtIndex:index]mutableCopy ];
NSLog(#"NSDictionary *u = [results objectAtIndex:index] %#",u);
NSDictionary *u1 = [[results objectAtIndex:newindex]mutableCopy];
NSLog(#"NSDictionary *u1 = [results objectAtIndex:newindex] %#",u1);
But if i use both index and newindex same value it works.
:-
:-
Code :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil suffix:(NSString *)_suffix{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.suffix = _suffix;
}
return self;
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)_tableView{
return 1;
}
//my new
- (NSInteger)tableView:(UITableView *)_tableView numberOfRowsInSection:(NSInteger)section{
int resultCount = [results count];
labelResultsCount.text = [NSString stringWithFormat:#"%d",resultCount];
return resultCount/2;
}
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// NSString* CellIdentifier = [NSString stringWithFormat:#"ident_%d",indexPath.row];
static NSString *CellIdentifier = #"ResultCell";
ResultCell *cell = (ResultCell *)[_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
NSArray *a = [[NSBundle mainBundle] loadNibNamed:#"ResultCell" owner:self options:nil];
cell = (ResultCell *)[a objectAtIndex:0];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
int index=[(indexPath.row*2) copy];
int newindex=[(index+1) copy];
// save badge in dictionaory and get here and show in lable
NSDictionary *u = [[results objectAtIndex:index]mutableCopy ];
NSLog(#"NSDictionary *u = [results objectAtIndex:newindex] %#",u);
NSDictionary *u1 = [[results objectAtIndex:newindex]mutableCopy];
NSLog(#"NSDictionary *u1 = [results objectAtIndex:indexPath.row*2+1 newindex] %#",u1);
#try {
/* fullName */
NSString *nickName = [u objectForKey:#"nickName"];
cell.labelName.text = nickName;
NSString *nickName1 = [u1 objectForKey:#"nickName"];
cell.labelName1.text = nickName1;
/* chat notification*/
cell.imageViewNotification.hidden=0;
cell.imageViewNotification1.hidden=0;
NSString *badge = [u objectForKey:#"badge"];
NSString *badge1 = [u1 objectForKey:#"badge"];
if([badge intValue]>0)
{
cell.imageViewNotification.hidden=0;
cell.labelNotification.text = badge;
NSLog(#"inside > 0 %#",badge);
}
else if([badge intValue]<=0)
{
cell.imageViewNotification.hidden=1;
cell.labelNotification.text=#"";
NSLog(#"%#",badge);
}
if([badge1 intValue]>0)
{
cell.imageViewNotification1.hidden=0;
cell.labelNotification1.text = badge1;
NSLog(#"inside > 0 %#",badge1);
}
else if([badge1 intValue]<=0)
{
cell.imageViewNotification1.hidden=1;
cell.labelNotification1.text=#"";
NSLog(#"%#",badge1);
}
/*..................*/
/* distance */
id distance = [u objectForKey:#"distance"];
if([distance isKindOfClass:[NSString class]]){
cell.labelDistance.text = distance;
cell.imageViewDistance.hidden = 0;
}else{
cell.imageViewDistance.hidden = 1;
cell.labelDistance.text = #"";
}
id distance1 = [u1 objectForKey:#"distance"];
if([distance1 isKindOfClass:[NSString class]]){
cell.labelDistance1.text = distance1;
cell.imageViewDistance1.hidden = 0;
}else{
cell.imageViewDistance1.hidden = 1;
cell.labelDistance1.text = #"";
}
/* online */
NSNumber *online = [u objectForKey:#"online"];
cell.imageViewOnline.image = [online intValue] ? [UIImage imageNamed:#"circle_online.png"] : [UIImage imageNamed:#"circle_offline_red.png"];
NSNumber *online1 = [u1 objectForKey:#"online"];
cell.imageViewOnline1.image = [online1 intValue] ? [UIImage imageNamed:#"circle_online.png"] : [UIImage imageNamed:#"circle_offline_red.png"];
/* buttonProfile */
id d = [u objectForKey:#"thumbnails"];
id d1 = [u1 objectForKey:#"thumbnails"];
if([d isKindOfClass:[NSDictionary class]] ||[d1 isKindOfClass:[NSDictionary class]]){
if([[d allKeys] count]>0 ||[[d1 allKeys] count]>0){
NSString *imageSuffix = [d objectForKey:#"icon"];
NSString *imageSuffix1 = [d1 objectForKey:#"icon"];
NSLog(#"[d allKeys] count]%#", d);
NSLog(#"[d1 allKeys] count]%#", d1);
UIImage *image = [[SharingCenter sharedManager] imageFromCache:imageSuffix];
UIImage *image1 = [[SharingCenter sharedManager] imageFromCache:imageSuffix1];
if(image||image1)
{
[cell.buttonUserProfile setBackgroundImage:image forState:UIControlStateNormal];
[cell.buttonUserProfile1 setBackgroundImage:image1 forState:UIControlStateNormal];
}
else{
NSString *gender = [u objectForKey:#"gender"];
NSString *gender1 = [u1 objectForKey:#"gender"];
UIImage *profileDefualtImage = [gender isEqualToString:#"M"] ? [UIImage imageNamed:#"no_photo_male.png"] : [UIImage imageNamed:#"no_photo_female.png"];
UIImage *profileDefualtImage1 = [gender1 isEqualToString:#"M"] ? [UIImage imageNamed:#"no_photo_male.png"] : [UIImage imageNamed:#"no_photo_female.png"];
[cell.buttonUserProfile setBackgroundImage:profileDefualtImage forState:UIControlStateNormal];
[cell.buttonUserProfile1 setBackgroundImage:profileDefualtImage1 forState:UIControlStateNormal];
/* downlowd Image */
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#",WebServicePrefix,imageSuffix]];
__block
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
request.delegate = self;
[request setPostValue:[NSString stringWithFormat:#"%f",[[SharingCenter sharedManager] currentCoordinate].latitude] forKey:#"lat"];
[request setPostValue:[NSString stringWithFormat:#"%f",[[SharingCenter sharedManager] currentCoordinate].longitude] forKey:#"lon"];
// [[[SharingCenter sharedManager] imagesCache] removeAllObjects];
[request setCompletionBlock:^{
NSData *imageData = [request responseData];
if(imageData){
UIImage *image = [UIImage imageWithData:imageData];
if(image){
[[[SharingCenter sharedManager] imagesCache] setObject:image forKey:imageSuffix];
if([[self.tableView indexPathsForVisibleRows] containsObject:indexPath]){
ResultCell *cell = (ResultCell *)[self.tableView cellForRowAtIndexPath:indexPath];
[cell.buttonUserProfile setBackgroundImage:image forState:UIControlStateNormal];
}
}
}
}];
[request setFailedBlock:^{
NSError *error = request.error;
NSLog(#"%#",error);
}];
/* downlowd Image */
NSURL *url1 = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#",WebServicePrefix,imageSuffix1]];
__block
ASIFormDataRequest *request1 = [ASIFormDataRequest requestWithURL:url1];
request1.delegate = self;
[request1 setPostValue:[NSString stringWithFormat:#"%f",[[SharingCenter sharedManager] currentCoordinate].latitude] forKey:#"lat"];
[request1 setPostValue:[NSString stringWithFormat:#"%f",[[SharingCenter sharedManager] currentCoordinate].longitude] forKey:#"lon"];
// [[[SharingCenter sharedManager] imagesCache] removeAllObjects];
[request1 setCompletionBlock:^{
NSData *imageData1 = [request1 responseData];
if(imageData1){
UIImage *image1 = [UIImage imageWithData:imageData1];
if(image1){
[[[SharingCenter sharedManager] imagesCache] setObject:image1 forKey:imageSuffix1];
if([[self.tableView indexPathsForVisibleRows] containsObject:indexPath]){
ResultCell *cell = (ResultCell *)[self.tableView cellForRowAtIndexPath:indexPath];
[cell.buttonUserProfile1 setBackgroundImage:image1 forState:UIControlStateNormal];
}
}
}
}];
[request1 setFailedBlock:^{
NSError *error = request1.error;
NSLog(#"%#",error);
}];
[[self networkQueue] addOperation:request];
[[self networkQueue] addOperation:request1];
}
}
}
else{
NSString *gender = [u objectForKey:#"gender"];
NSString *gender1 = [u1 objectForKey:#"gender"];
UIImage *profileDefualtImage = [gender isEqualToString:#"M"] ? [UIImage imageNamed:#"no_photo_male.png"] : [UIImage imageNamed:#"no_photo_female.png"];
[cell.buttonUserProfile setBackgroundImage:profileDefualtImage forState:UIControlStateNormal];
UIImage *profileDefualtImage1 = [gender1 isEqualToString:#"M"] ? [UIImage imageNamed:#"no_photo_male.png"] : [UIImage imageNamed:#"no_photo_female.png"];
[cell.buttonUserProfile1 setBackgroundImage:profileDefualtImage1 forState:UIControlStateNormal];
}
/* pickStatus */
NSNumber *pickStatus = [u objectForKey:#"pick_status"];
NSNumber *pickStatus1 = [u1 objectForKey:#"pick_status"];
switch ([pickStatus intValue]) {
case 0:
cell.imageViewBorder.image = [UIImage imageNamed:#"border_yellow_transperent.png"];
cell.buttonUserPick.enabled = 1;
[cell.buttonUserPick setBackgroundImage:[UIImage imageNamed:#"button_circle_pick.png"] forState:UIControlStateNormal];
break;
case 1:
cell.imageViewBorder.image = [UIImage imageNamed:#"border_red_transperent.png"];
cell.buttonUserPick.enabled = 0;
[cell.buttonUserPick setBackgroundImage:[UIImage imageNamed:#"button_circle_wait.png"] forState:UIControlStateDisabled];
break;
case 2:
cell.imageViewBorder.image = [UIImage imageNamed:#"border_red_transperent.png"];
cell.buttonUserPick.enabled = 1;
[cell.buttonUserPick setBackgroundImage:[UIImage imageNamed:#"button_circle_pick.png"] forState:UIControlStateNormal];
break;
case 3:
cell.imageViewBorder.image = [UIImage imageNamed:#"border_red_transperent.png"];
cell.buttonUserPick.enabled = 0;
[cell.buttonUserPick setBackgroundImage:[UIImage imageNamed:#"button_circle_date.png"] forState:UIControlStateDisabled];
break;
default:
break;
}
switch ([pickStatus1 intValue]) {
case 0:
cell.imageViewBorder1.image = [UIImage imageNamed:#"border_yellow_transperent.png"];
cell.buttonUserPick1.enabled = 1;
[cell.buttonUserPick1 setBackgroundImage:[UIImage imageNamed:#"button_circle_pick.png"] forState:UIControlStateNormal];
break;
case 1:
cell.imageViewBorder1.image = [UIImage imageNamed:#"border_red_transperent.png"];
cell.buttonUserPick1.enabled = 0;
[cell.buttonUserPick1 setBackgroundImage:[UIImage imageNamed:#"button_circle_wait.png"] forState:UIControlStateDisabled];
break;
case 2:
cell.imageViewBorder1.image = [UIImage imageNamed:#"border_red_transperent.png"];
cell.buttonUserPick1.enabled = 1;
[cell.buttonUserPick1 setBackgroundImage:[UIImage imageNamed:#"button_circle_pick.png"] forState:UIControlStateNormal];
break;
case 3:
cell.imageViewBorder1.image = [UIImage imageNamed:#"border_red_transperent.png"];
cell.buttonUserPick1.enabled = 0;
[cell.buttonUserPick1 setBackgroundImage:[UIImage imageNamed:#"button_circle_date.png"] forState:UIControlStateDisabled];
break;
default:
break;
}
}
#catch (NSException * e) {
NSLog(#"%#",e);
}
#finally {
return cell;
}
}
Educated guess:
This line causes your problem:
if([d isKindOfClass:[NSDictionary class]] ||[d1 isKindOfClass:[NSDictionary class]]){
if([[d allKeys] count]>0 ||[[d1 allKeys] count]>0){
There are 4 different possibilities how the first if will come out:
d and d1 are both NSStrings. Line 2 will not be called
d is NSDictionary, d1 is a NSString. Line 2 will be called
d is NSString, d1 is a NSDictionary. Line 2 will be called
d and d1 are both NSDictionaries. Line 2 will be called.
First case is no problem at all. Last case neither. In case 2 and 3 allKeys will be called on a object that is not a NSDictionary.
You should probably replace it with an "if" that needs both tests to be true.
if([d isKindOfClass:[NSDictionary class]] && [d1 isKindOfClass:[NSDictionary class]]){
^^
Another option would be to check individually.
if([d isKindOfClass:[NSDictionary class]]) {
x = [d allKeys];
}
if([d1 isKindOfClass:[NSDictionary class]]) {
x = [d1 allKeys];
}
You are probably doing something to those NSDictionary objects somewhere, reading their allKeys. But my guess is that the objects you try to fetch from that results array aren't NSDictionary objects but NSString objects.
Try logging their class property to see what you are dealing with (you can also find this out by just looking at the JSON of course).
NSDictionary *u = [[results objectAtIndex:index]mutableCopy ];
NSLog(#"u Class: %#", [u class]);
Also, why are you making a mutableCopy of the object right to a non-mutable NSDictionary object.
Using the following should do the trick normally:
NSDictionary* u = [results objectAtIndex:index];
NSLog(#"u Class: %#", [u class]);
That's a lot of code to look through, but I think this could be the problem:
if([d isKindOfClass:[NSDictionary class]] ||[d1 isKindOfClass:[NSDictionary class]]){
if([[d allKeys] count]>0 ||[[d1 allKeys] count]>0){
This if statement will pass if either d or d1 is a dictionary. If one isn't, it would cause that error you see on the second line. Log the class of d and d1 to see if they're both dictionaries.
My code:
- (void)metadata {
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:self.fileURL options:nil];
NSArray *artworks = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyArtwork keySpace:AVMetadataKeySpaceCommon];
NSArray *titles = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
NSArray *artists = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyArtist keySpace:AVMetadataKeySpaceCommon];
NSArray *albumNames = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyAlbumName keySpace:AVMetadataKeySpaceCommon];
AVMetadataItem *artwork = [artworks objectAtIndex:0];
AVMetadataItem *title = [titles objectAtIndex:0];
AVMetadataItem *artist = [artists objectAtIndex:0];
AVMetadataItem *albumName = [albumNames objectAtIndex:0];
if ([artwork.keySpace isEqualToString:AVMetadataKeySpaceID3]) {
NSDictionary *dictionary = [artwork.value copyWithZone:nil];
self.currentSongArtwork = [UIImage imageWithData:[dictionary objectForKey:#"data"]];
}
else if ([artwork.keySpace isEqualToString:AVMetadataKeySpaceiTunes]) {
self.currentSongArtwork = [UIImage imageWithData:[artwork.value copyWithZone:nil]];
}
self.currentSongTitle = [title.value copyWithZone:nil];
self.currentSongArtist = [artist.value copyWithZone:nil];
self.currentSongAlbumName = [albumName.value copyWithZone:nil];
self.currentSongDuration = self.audioPlayer.duration;
}
This works for fetching artwork from m4a files, but doesn’t work for mp3 files. If the asset points to an mp3 file, artworks is empty. What am I doing wrong and how do I fix it?
I found that the artworks were being loaded asynchronously while the image was being set synchronously. I solved it this way:
- (void)metadata {
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:self.fileURL options:nil];
NSArray *titles = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon];
NSArray *artists = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyArtist keySpace:AVMetadataKeySpaceCommon];
NSArray *albumNames = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata withKey:AVMetadataCommonKeyAlbumName keySpace:AVMetadataKeySpaceCommon];
AVMetadataItem *title = [titles objectAtIndex:0];
AVMetadataItem *artist = [artists objectAtIndex:0];
AVMetadataItem *albumName = [albumNames objectAtIndex:0];
NSArray *keys = [NSArray arrayWithObjects:#"commonMetadata", nil];
[asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
NSArray *artworks = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata
withKey:AVMetadataCommonKeyArtwork
keySpace:AVMetadataKeySpaceCommon];
for (AVMetadataItem *item in artworks) {
if ([item.keySpace isEqualToString:AVMetadataKeySpaceID3]) {
NSDictionary *d = [item.value copyWithZone:nil];
self.currentSongArtwork = [UIImage imageWithData:[d objectForKey:#"data"]];
} else if ([item.keySpace isEqualToString:AVMetadataKeySpaceiTunes]) {
self.currentSongArtwork = [UIImage imageWithData:[item.value copyWithZone:nil]];
}
}
}];
self.currentSongTitle = [title.value copyWithZone:nil];
self.currentSongArtist = [artist.value copyWithZone:nil];
self.currentSongAlbumName = [albumName.value copyWithZone:nil];
self.currentSongDuration = self.audioPlayer.duration;
}
I just found the answer to that here: How can I extract metadata from mp3 file in ios development and was now looking to see why that code doesn't work on an m4a file.
I took a little bit from your code and present the following which seems to work for both m4a and mp3. Note that I left the code which works for mp3 as an open else clause without the qualifier - if anybody gains more experience with this they are welcome to refine!
- (void)getMetaDataForSong:(MusicItem *)musicItem {
AVAsset *assest;
// filePath looks something like this: /var/mobile/Applications/741647B1-1341-4203-8CFA-9D0C555D670A/Library/Caches/All Summer Long.m4a
NSURL *fileURL = [NSURL fileURLWithPath:musicItem.filePath];
NSLog(#"%#", fileURL);
assest = [AVURLAsset URLAssetWithURL:fileURL options:nil];
NSLog(#"%#", assest);
for (NSString *format in [assest availableMetadataFormats]) {
for (AVMetadataItem *item in [assest metadataForFormat:format]) {
if ([[item commonKey] isEqualToString:#"title"]) {
musicItem.strSongTitle = (NSString *)[item value];
}
if ([[item commonKey] isEqualToString:#"artist"]) {
musicItem.strArtistName = (NSString *)[item value];
}
if ([[item commonKey] isEqualToString:#"albumName"]) {
musicItem.strAlbumName = (NSString *)[item value];
}
if ([[item commonKey] isEqualToString:#"artwork"]) {
UIImage *img = nil;
if ([item.keySpace isEqualToString:AVMetadataKeySpaceiTunes]) {
img = [UIImage imageWithData:[item.value copyWithZone:nil]];
}
else { // if ([item.keySpace isEqualToString:AVMetadataKeySpaceID3]) {
NSData *data = [(NSDictionary *)[item value] objectForKey:#"data"];
img = [UIImage imageWithData:data] ;
}
musicItem.imgArtwork = img;
}
}
}
}
As Ryan Heitner pointed out in a comment to Andy Weinstein, the way to retrieve the binary artwork data from the AVMetadataKeySpaceID3 has changed somewhere from IOS7 to IOS8. Casting blindly item to NSDictionary will crash in the ID3 case nowadays. To make code bullet proof just check dataValue, otherwise the Classes. In fact today item.value points to item.dataValue and has the NSData class.
- (UIImage*)imageFromItem:(AVMetadataItem*)item
{
NSData* data=nil;
if (item.dataValue!=nil) {
data=item.dataValue;
} else if ([item.value isKindOfClass:NSData.class]) { //never arrive here nowadays
data=(NSData*)item.value;
} else if ([item.value isKindOfClass:NSDictionary.class]) { //never arrive here nowadays...
NSDictionary* dict=(NSDictionary*)item.value;
data=dict[#"data"];
}
if (data==nil) {
return nil;
}
return [UIImage imageWithData:data];
}
I'm very new to programming, and I jumped right into a project (I know thats not the smartest thing to do, but I'm learning as I go). The app that I'm writing has 10 UIImageViews that display a picture from the users camera roll. The code I'm using needs each of the UIImageViews to have tags. I'm currently using NSData to save the array images, and it works great, but I can't use this method anymore because NSData doesn't support the use of tags. I also can't use NSUserDefaults, because I can't save images to a plist. Here is how I'm attempting to do this (using the NSData method, which works but I have to edit this so that my tags work.)
This is my current code:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)img editingInfo:(NSDictionary *)editInfo {
if (imageView.image == nil) {
imageView.image = img;
[self.array addObject:imageView.image];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
if (imageView2.image == nil) {
imageView2.image = img;
NSLog(#"The image is a %#", imageView);
[self.array addObject:imageView2.image];
[picker dismissModalViewControllerAnimated:YES];
[self.popover dismissPopoverAnimated:YES];
return;
}
...
- (void)applicationDidEnterBackground:(UIApplication*)application {
NSLog(#"Image on didenterbackground: %#", imageView);
[self.array addObject:imageView.image];
[self.array addObject:imageView2.image];
[self.user setObject:self.array forKey:#"images"];
[user synchronize];
}
- (void)viewDidLoad
{
self.user = [NSUserDefaults standardUserDefaults];
NSLog(#"It is %#", self.user);
self.array = [[self.user objectForKey:#"images"]mutableCopy];
imageView.image = [[self.array objectAtIndex:0] copy];
imageView2.image = [[self.array objectAtIndex:1] copy];
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:app];
[super viewDidLoad];
}
Any help or suggestions on how to edit this code so that I can save the images, while using tags is much appreciated, thanks!
EDIT: Here is my updated code:
-(IBAction)saveButtonPressed:(id)sender {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) objectAtIndex:0];
for (UIImageView *imageView in self.array) {
NSInteger tag = self.imageView.tag;
UIImage *image = self.imageView.image;
NSString *imageName = [NSString stringWithFormat:#"Image%i.png",tag];
NSString *imagePath = [docsDir stringByAppendingPathComponent:imageName];
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:YES];
}
NSLog(#"Saved Button Pressed");
}
- (void)applicationDidEnterBackground:(UIApplication*)application {
}
-(void)viewDidLoad {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0];
NSArray *docFiles = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:docsDir error:NULL];
for (NSString *fileName in docFiles) {
if ([fileName hasSuffix:#".png"]) {
NSString *fullPath = [docsDir stringByAppendingPathComponent:fileName];
UIImage *loadedImage = [UIImage imageWithContentsOfFile:fullPath];
if (!imageView.image) {
imageView.image = loadedImage;
} else {
imageView2.image = loadedImage;
}
}
}
}
You need to use "Fast Enumeration" to parse the array's objects, and write each object to disk sequentially. First, you're going to need to add the UIImageView objects to the array instead of the UIImage property of the UIImageView, so you can recover the tag. So instead of writing
[self.array addObject:imageView.image];
It will be
[self.array addObject:imageView];
Try to follow along with my code. I inserted comments on each line to help.
-(void)applicationDidEnterBackground:(UIApplication *)application {
//Obtain the documents directory
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainmask,YES) objectAtIndex:0];
//begin fast enumeration
//this is special to ObjC: it will iterate over any array one object at a time
//it's easier than using for (i=0;i<array.count;i++)
for (UIImageView *imageView in self.array) {
//get the imageView's tag to append to the filename
NSInteger tag = imageView.tag;
//get the image from the imageView;
UIImage *image = imageView.image;
//create a filename, in this case "ImageTAGNUM.png"
NSString *imageName = [NSString stringWithFormat:#"Image%i.png",tag];
//concatenate the docsDirectory and the filename
NSString *imagePath = [docsDir stringByAppendingPathComponent:imageName];
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:YES];
}
}
To load the images from disk, you'll have to look at your viewDidLoad method
-(void)viewDidLoad {
//get the contents of the docs directory
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainmask,YES) objectAtIndex:0];
//Get the list of files from the file manager
NSArray *docFiles = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:docsDir error:NULL]);
//use fast enumeration to iterate the list of files searching for .png extensions and load those
for (NSString *fileName in docFiles) {
//check to see if the file is a .png file
if ([fileName hasSuffix:#".png"]) {
NSString *fullPath = [docsDir stringByAppendingPathComponent:fileName];
UIImage *loadedImage = [UIImage imageWithContentsOfFile:fullPath];
//you'll have to sort out how to put these images in their proper place
if (!imageView1.image) {
imageView1.image = loadedImage;
} else {
imageView2.image = loadedImage;
}
}
}
}
Hope this helps
One thing you need to be aware of is that when an app enters the background it has about 5 seconds to clean up its act before it's suspended. The UIPNGRepresentation() function takes a significant amount of time and is not instantaneous. You should be aware of this. It would probably be better to write some of this code in other places and do it earlier than at app backgrounding. FWIW
You can use the [NSbundle Mainbundel] to store that images.
To get path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
First, there's still a problem in your for loop.
for (UIImageView *imageView in self.array) {
NSInteger tag = self.imageView.tag;
UIImage *image = self.imageView.image;
// ...
}
Before you make any other changes, you must understand why. imageView is your for loop control variable, which changes on each iteration through the loop. self.imageView is a different thing. It is the first of the 10 imageViews attached to your viewController. Every time this loop cycles, it looks at the first imageView, and only the first.
As for why saving doesn't work, it's probably because the arrays elsewhere aren't working. Add some logging to make sure there's something in the array, and that it has as many elements as you expect.
-(IBAction)saveButtonPressed:(id)sender {
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) objectAtIndex:0];
// Log to make sure the views expected have previously been stored.
// If the array is empty, or shorter than expected, the problem is elsewhere.
NSLog(#"Image view array before saving = %#", self.array);
for (UIImageView *imageViewToSave in self.array) {
NSInteger tag = imageViewToSave.tag;
UIImage *image = imageViewToSave.image;
NSString *imageName = [NSString stringWithFormat:#"Image%i.png",tag];
NSString *imagePath = [docsDir stringByAppendingPathComponent:imageName];
// Log the image and path being saved. If either of these are nil, nothing will be written.
NSLog(#"Saving %# to %#", image, imagePath);
[UIImagePNGRepresentation(image) writeToFile:imagePath atomically:NO];
}
NSLog(#"Save Button Pressed");
}
I'm trying to change the image of a selected contact in peoplePickerNavigationController, but when I choose a contact, does not change the image and shows no error.
Well, far as I know, it's all right! Something is missing?
This is the code:
ABAddressBookRef aBook = ABAddressBookCreate();
UIImage *img = [UIImage imageNamed:#"90x90.png"];
NSData *dataRef = UIImagePNGRepresentation(img);
CFDataRef cfdata = CFDataCreate(NULL, [dataRef bytes], [dataRef length]);
CFErrorRef error;
if(ABPersonRemoveImageData(person, &error)){
NSLog(#"OK");
}
if(ABAddressBookSave(aBook, &error)){
NSLog(#"OK");
}
if(ABPersonSetImageData(person, cfdata, &error)){
NSLog(#"OK");
}
if(ABAddressBookSave(aBook, &error)){
NSLog(#"OK");
}
CFRelease(cfdata);
[self dismissModalViewControllerAnimated:YES];
return NO;
Remembering that the above code is within the BOOL:
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { }
Thanks!
Managed to solve, for those who have the same question in the future, just use the ABRecordGetRecordID and ABAddressBookGetPersonWithRecordID and follows the code below:
ABAddressBookRef aBook = ABAddressBookCreate();
NSNumber *recordId = [NSNumber numberWithInteger:ABRecordGetRecordID(person)];
ABRecordRef pID = ABAddressBookGetPersonWithRecordID(aBook,recordId.integerValue);
UIImage *img = [UIImage imageNamed:#"90x90.png"];
NSData *dataRef = UIImagePNGRepresentation(img);
CFDataRef cfdata = CFDataCreate(NULL, [dataRef bytes], [dataRef length]);
CFErrorRef error;
ABPersonRemoveImageData(pID, &error);
ABAddressBookSave(aBook, &error);
ABPersonSetImageData(pID, cfdata, &error);
ABAddressBookSave(aBook, &error);
CFRelease(cfdata);
[self dismissModalViewControllerAnimated:YES];
return NO;
Thanks!