I'm still fairly new to Obj-C and the idea of blocks. I read this post about displaying images from url retrieved from ALAssets: display image from URL retrieved from ALAsset in iPhone
Besides being able to view picture files in a UITableView using the ALAsset framework, I want to be able to play a video that is stored in the pictures folder as well. The video asset shows up just as a picture would, so I would like to be able to tap that video listing in the table and have it play. (In other words, I want to play a video using the Assets Library Framework)
Can this be done with MPMoviePlayerController?
From that post above I'm gathering I need code inside this function to get an asset URL for a video file:
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
{
};
If this is right, what code would I need to put inside that function so that I could successfully play the video via MPMoviePlayerController?
Just for reference, my code for displaying the assets in a UITableView is here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"id";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[[cell imageView] setImage:[UIImage imageWithCGImage:[[assets objectAtIndex:indexPath.row] thumbnail]]];
[[cell textLabel] setText:[NSString stringWithFormat:#"Item %d", indexPath.row+1]];
return cell;
}
This is my first post so I'm sorry if I post it wrong. Thanks for your help
Even easier
MPMoviePlayerViewController *moviePlayerVC =[[MPMoviePlayerViewController alloc] initWithContentURL:[[asset defaultRepresentation] url]];
Okay I found out one can use this block to spit out a log of the asset library address:
void (^assetEnumerator)(struct ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop)
{
if(result != nil) {
NSLog(#"See Asset: %#", result);
[assets addObject:result];
}
};
which will spit out something like
"See Asset: ALAsset - Type:Video, URLs:{
"com.apple.m4v-video" = "assets-library://asset/asset.m4v?id=100&ext=m4v"; "
So I can send this asset library address to MPMoviePlayerController and it will work!
Like so:
NSString *urlAddress = #"assets-library://asset/asset.m4v?id=100&ext=m4v";
NSURL *theURL = [NSURL URLWithString:urlAddress];
mp = [[MPMoviePlayerController alloc] initWithContentURL:theURL];
etc...
now I just gotta figure out how to get that URL string out of the ALAsset object dynamically, which shouldn't be too hard to figure out.. hopefully
You can get the url of an asset by using:
[result defaultRepresentation] url];
#go2 answer is correct but The MoviePlayerController doesn't show anything.
so you also need to add moviePlayerController.movieSourceType=MPMovieSourceTypeFile;
see below code to play this.
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:fileURL];
[moviePlayerController.view setFrame:self.view.frame];
moviePlayerController.movieSourceType=MPMovieSourceTypeFile;
moviePlayerController.fullscreen = YES;
[moviePlayerController play];
Related
Sequence of audio files in collection view cell is wrong. In first cell it plays nothing, in second cell it plays first audio file, in third cell it plays second audio file , in fourth cell it plays third audio file and when clicking on first cell again it plays fourth audio file.
Why is that. What i m doing wrong in code.
Here is my code
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
audioArray =[[NSArray alloc] initWithObjects:#"0", #"1", #"2", #"3", nil];
NSString *filePath = [audioArray objectAtIndex:indexPath.row];
NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:audioToLoad ofType: #"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: audioFilePath];
audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:fileURL error:nil];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;
{
// custom UICollectionViewCell, hold an image and its label
Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:kCellID forIndexPath:indexPath];
// make the cell's title the actual NSIndexPath value
cell.label.text = [NSString stringWithFormat:#"{%ld,%ld}", (long)indexPath.row, (long)indexPath.section];
// load the image for this cell
NSString *imageToLoad = [NSString stringWithFormat:#"%d.jpg", indexPath.row];
cell.image.image = [UIImage imageNamed:imageToLoad];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
why audio files from array is not loading in correct order in the collection view cells.
Thanks for help.
I know this is old, but will try to answer it anyway.
Usually when you're working with the collection view you specify the type of file that corresponds to the project files that you wish to show. So for example, if you were loading images you would specify the type as .jpg or .png etc. For audio it might be .aiff or .mp3 .wav etc.
Once you've done this you'd use the %ld which represents numbers starting from 0. that would assist in loading your files in the correct order.
https://developer.apple.com/library/ios/samplecode/CollectionView-Simple/Introduction/Intro.html
Would give you a good starting point on collection view method alternatives - this uses the named method and applies to .jpg try chaning the code to suite for audio.
Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ConvoreCell";
ConvoreCell * cell = (ConvoreCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ConvoreCell" owner:nil options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (ConvoreCell *) currentObject;
break;
}
}
}
NSMutableDictionary *cellValue = [results objectAtIndex:indexPath.row];
NSString *picURL = [[cellValue objectForKey:#"creator"] objectForKey:#"img"];
if ([picURL isEqualToString:#"https://secure.gravatar.com/avatar/1f043010eb1652b3fab3678167dc0487/?default=https%3A%2F%2Fconvore.com%2Fmedia%2Fimages%2Feric.png&s=80"])
picURL = #"https://convore.com/media/images/eric.png";
if ((picURL != (NSString *) [NSNull null]) && (picURL.length !=0)) {
NSLog(#"%#", picURL);
NSData *imgData = [[[NSData dataWithContentsOfURL:
[NSURL URLWithString:
picURL]] autorelease] retain];
[cell.pic initWithImage:[[UIImage alloc] initWithData:imgData]];
} else {
cell.pic = nil;
}
//NSLog(#"Name is : %#", [cellValue objectForKey:#"name"]);
cell.title.text = [cellValue objectForKey:#"name"];
cell.info.text = (#"Created by: %#", [[cellValue objectForKey:#"creator"] objectForKey:#"name"]);
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Configure the cell...
return cell;
}
For some reason the image is not showing up. What am I doing wrong here? The URL of the image is valid, I checked.
Also I don't want to have the accessory view on the TableViewCell, I did specify that as no in IB, but it still shows up... i set the accessory attribute to none already
you have some issues in your code.
NSData *imgData = [[[NSData dataWithContentsOfURL:
[NSURL URLWithString:
picURL]] autorelease] retain];
the former is not a real issue (maybe by coincidence?!), but it's ugly and confusing. get rid of the autorelease and the retain. The object you get from dataWithContentsOfURL: is already autoreleased.
[cell.pic initWithImage:[[UIImage alloc] initWithData:imgData]];
And your real issue might be this. From what I know you should call init exactly one time; after you've allocated an object.
So if cell.pic is an UIImageView I would try to change the code to something like this:
cell.pic.image = [[[UIImage alloc] initWithData:imgData] autorelease];
Once you see your images you should change your code so that it saves the images in the data you use to populate the cell. You are downloading the image every time a cell appears. That's something you shouldn't do. But this is beyond this question.
EDIT:
Also I don't want to have the
accessory view on the TableViewCell, I
did specify that as no in IB, but it
still shows up... i set the accessory
attribute to none already
You do? But I can see this line of code:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
You should be able to get an UIImage by just
[cell.pic initWithImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSUrl NSURL picURL]]]];
You're not showing your cellForRowAtIndexPath method, which is the key to analyzing what's going on. The typical paradigm is that UITableViewCell objects get reused repeatedly by the UITableView. You should be setting the UIImage into the cell when the UITableView calls cellForRowAtIndexPath.
The problem causing your immediate crash is that the nib for ConvoreCell is trying to set an IBOutlet you have declared but finding no way to actually set it. I would check that you have synthesized your pic property.
There are other problems here. The line
[cell.pic initWithImage:[[UIImage alloc] initWithData:imgData]];
Is wrong; you do not call init on an object that already exists, but only when you are allocating an object. Do something like
cell.pic = [[[WhateverClassPicIS alloc] initWithImage:[[UIImage alloc] initWithData:imgData]];
Also, you are using NSData dataWithContentsOfURL on the main thread. This will lock up your user interface for an indeterminate time as you connect to the network. Use asynchronous calls instead.
I'm try to create thumbnail image from video url.
I use AV Foundation Programming Guide.
My project have a button and an imageview. When button pressed so thumbnail image will load on uiimageview.
my code can't work,it's:
- (IBAction) btnClick : (id)sender
{
NSURL *url = [NSURL URLWithString:#"http://www.youtube.com/watch?v=bgN62D70VLk"];
AVURLAsset *myAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:myAsset];
Float64 durationSeconds = CMTimeGetSeconds([myAsset duration]);
CMTime midpoint = CMTimeMakeWithSeconds(durationSeconds/2.0, 600);
NSError *error = nil;
CMTime actualTime;
CGImageRef halfWayImage = [imageGenerator copyCGImageAtTime:midpoint actualTime:&actualTime error:&error];
if (halfWayImage != NULL) {
NSString *actualTimeString = (NSString *)CMTimeCopyDescription(NULL, actualTime);
NSString *requestedTimeString = (NSString *)CMTimeCopyDescription(NULL, midpoint);
NSLog(#"got halfWayImage: Asked for %#, got %#", requestedTimeString, actualTimeString);
[actualTimeString release];
[requestedTimeString release];
// Do something interesting with the image.
CGImageRelease(halfWayImage);
}
UIImage *image = [UIImage imageWithCGImage:halfWayImage];
[imageView setImage:image];
[imageGenerator release];
}
Help me for this problem,please!
Thanks!
MPMoviePlayerController has some method to handle this -
thumbnailImageAtTime:timeOption:
requestThumbnailImagesAtTimes: timeOption:
cancelAllThumbnailImageRequests:
I see a few problems in your code:
http://www.youtube.com/watch?v=bgN62D70VLk is the URL of a web page, but AVAssets must be video or audio files. Note: YouTube does not advertise the URLs of its video files.
Your call to [myAsset duration] will block. You should instead use the AVAsynchronousKeyValueLoading protocol (see loadValuesAsynchronouslyForKeys).
You are using halfwayImage after releasing it.
I would recommend watching the AVFoundation sessions from WWDC 2010, and looking at the session sample code.
This is very late but it will help some other who comes to this question.
Look into this answer for the same problem, Hope will help to other guys.
I built a simple mac data entry tool I use with an iPhone application. I've recently added thumbnail which I added via an Image Well using simple bindings. Its a transformable data type which seems to work fine.
The iPhone application however won't show the images. The attribute isn't null but I can't get an image to appear. The following is for cellForRowAtIndexPath
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSManagedObject *entity = nil;
if ([self.searchDisplayController isActive])
entity = [[self filteredListContent] objectAtIndex:[indexPath row]];
else
entity = [fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [entity valueForKey:#"name"];
//cell.imageview.image = [UIImage imageNamed:#"ImageB.jpeg"]; //works fine
cell.imageView.image = [entity valueForKey:#"thumbnail"];//no error, but no file
return cell;
I'm thinking either the problem is with the transformable (I'm using the default NSKeyedUnarchiveFromData), or how I'm calling the thumbnail. I'm a newbie so any help would be greatly appreciated.
Sounds like you are storing the image as an NSImage on the desktop and that object does not exist on the iPhone. Your desktop app needs to store the image in something that is portable, a PNG or JPG, etc. Then you will be able to load it back into your iPhone application as a UIImage.
Update re transformable
Sounds like you are still passing in a NSImage to the attribute and it is thinking you are handling it data. You need to convert it to a "standard" format first, like this:
NSBitmapImageRep *bits = [[myImage representations] objectAtIndex: 0];
NSData *data = [bits representationUsingType:NSPNGFileType properties:nil];
[myManagedObject setImage:data];
I recommend writing custom accessors to handle this, like the following:
#ifdef IPHONEOS_DEPLOYMENT_TARGET
- (void)setImage:(UIImage*)image
{
[self willChangeValueForKey:#"image"];
NSData *data = UIImagePNGRepresentation(image);
[myManagedObject setImage:data];
[self setPrimitiveValue:data forKey:#"image"];
[self didChangeValueForKey:#"image"];
}
- (UIImage*)image
{
[self willAccessValueForKey:#"image"];
UIImage *image = [UIImage imageWithData:[self primitiveValueForKey:#"image"];
[self didAccessValueForKey:#"image"];
return image;
}
#else
- (void)setImage:(NSImage*)image
{
[self willChangeValueForKey:#"image"];
NSBitmapImageRep *bits = [[image representations] objectAtIndex: 0];
NSData *data = [bits representationUsingType:NSPNGFileType properties:nil];
[myManagedObject setImage:data];
[self setPrimitiveValue:data forKey:#"image"];
[self didChangeValueForKey:#"image"];
}
- (NSImage*)image
{
[self willAccessValueForKey:#"image"];
NSImage *image = [[NSImage alloc] initWithData:[self primitiveValueForKey:#"image"]];
[self didAccessValueForKey:#"image"];
return [image autorelease];
}
#endif
This will give you a conditional compile and will store the data as NSData (in PNG format) that can be retrieved on any device.
I have problem with loading images from the Documents folder of iPhone application into the tableView.
In a separate request, I check on the server all the images available and download them into the "images" folder under Documents. I am pretty sure that the images are saved correctly.
NSString *filePath = [imagesFolderPath stringByAppendingPathComponent:imageFileName];
[urlData writeToFile:filePath atomically:NO];
NSLog(#"Saved to file: %#", filePath);
2010-01-22 17:07:27.307 Foo[2102:207] Saved to file: /Users/Hoang/Library/Application Support/iPhone Simulator/User/Applications/6133A161-F9DC-4C92-8AE6-5651022EAA94/Documents/images/86_2.png
[NSBundle mainBundle] is not suitable for loading the images because at runtime, the application tries to connect to the server to download the images, they are not static.
But loading the images from Documents/images folder does not give me the image on the TableView.
static NSString *CellIdentifier = #"CellCategory";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
UIImageView *imageView = cell.imageView;
MenuItem *item = (MenuItem *) [arrayMenuItems objectAtIndex:indexPath.row];
cell.textLabel.text = item.descrizione;
NSString *strImagePath = [[imagesFolderPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%d_%d", item.idItem, item.idNode]] stringByAppendingPathExtension:#"png"];
NSLog(#"strImagePath: %#", strImagePath);
imageView.image = [[UIImage imageWithContentsOfFile:strImagePath] autorelease];
2010-01-22 17:07:42.842 Foo[2102:207] strImagePath: /Users/Hoang/Library/Application Support/iPhone Simulator/User/Applications/6133A161-F9DC-4C92-8AE6-5651022EAA94/Documents/images/86_2.png
Is there anyone having the same problem?
I have looked around in stackoverflow but have not succeeded.
Thanks in advance.
I've just had the same problem with loading images from application's Documents folder to UITableViewCell. This works:
[UIImage imageWithContentsOfFile:fullPath];
hardcoding the path is a bad idea since it can change during a redeploy,
try something like this..
NSString *imagessDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/images"];
and verify the file/image is even there with nsfilemanager
Edited: ANSWER
Be sure to check the response on NSData to see if there are images. In my case, all codes are ok, but the response from server give nothing. It is still able to save the image to the file on the documents/images folder, and still not raise any error, until I realized that all the images are not exist on the server. THAT WAS THE ERROR, not relates anything to the Documents folder
Original answer
There must be some problems with the initialization code of UIImage.
I have tried already three initialization functions for image having the path on the Documents directory.
But it just does not work.
Here you can see, the code always fall into the (exist) block, the first line is to load the image from the Documents/images directory, it always fails.
The second line inside the (exist) block, I tried to get the image from the bundle, it works perfect, but it is not what I want.
Fourth line of code, I get the original link of the images on the server and it gets what I nearly want. (Actually, what I want is to save all the images from the server into the Documents/images directory before hand, and then load them from there)
NSString *strImagePath = [[imagesFolderPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%d_%d", item.idItem, item.idNode]] stringByAppendingPathExtension:#"png"];
NSLog(#"strImagePath: %#", strImagePath);
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:strImagePath];
if (exists){
//UIImage *menuImage = [UIImage imageWithContentsOfFile:strImagePath];
//UIImage *menuImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"ALT" ofType:#"png"]];
//imageView.image = menuImage;
NSString *strImagePathURL = [NSString stringWithFormat:#"http://foo.com/%d_%d.png", item.idItem, item.idNode];
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:strImagePathURL]];
imageView.image = [[UIImage alloc] initWithData:imageData];
}
else {
imageView.image = [UIImage imageNamed:#"ALT.png"];
}