My main goal is to be able to click on a table view item and load a video. The table view is populated with the contents of the documents directory and I have been able to do this successfully and add the filename to the cell's label, I have done this with the following code:
void)viewDidLoad
{
[super viewDidLoad];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = documentsDirectory;
filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:dataPath error:nil];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [filePathsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [filePathsArray objectAtIndex:indexPath.row];
return cell;
}
However the part I am finding difficult is opening the file part. This is my code so far:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"didSelectRowAtIndexPath");
myURL=[NSURL URLWithString:[filePathsArray objectAtIndex:indexPath.row]];
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:myURL];
[self.view addSubview:moviePlayerController.view];
moviePlayerController.fullscreen = YES;
[moviePlayerController play];
[self setController:moviePlayerController];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
What happens when a user clicks on a UITableView cell is that the video player opens full screen and it just says "loading..." the entire time and the video does not load, no errors are reported either in the debugger. What should the variable myURL be set equal to? Any help would be greatly appreciated.
Finally figured it out after a while there was two problems it was only fetching the name not the full file directory e.g. var/mobile... and there was a problem with the video player too, this is the working code for anyone wanting to do the same as me:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"didSelectRowAtIndexPath");
NSString *currentFileName = [filePathsArray[indexPath.row] lastPathComponent];
NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documentsDirectoryPath stringByAppendingPathComponent:currentFileName];
//Play the movie now
NSURL *videoURL =[NSURL fileURLWithPath:filePath];
MPMoviePlayerViewController *videoPlayerView = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];
videoPlayerView.moviePlayer.fullscreen=TRUE;
[self presentMoviePlayerViewControllerAnimated:videoPlayerView];
[videoPlayerView.moviePlayer play];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
A NSURL is different from a path as in it contains the protocol used to access the resource.
For example, the http:// in the http://stackoverflow.com
I guess the problem is that you're creating a URL from a path string, try this:
NSString *urlStr = [NSString stringWithFormat:#"file://%#", [filePathsArray objectAtIndex:indexPath.row]];
myURL = [NSURL URLWithString:urlStr];
Related
I'm working on a project that enables you to play a sound when a cell in a tableview is selected. To make things a bit easier, I've implemented a search function. Problem is, it's not working quite right. when you click on a result, the sound that plays comes from the original array, rather than the newly filtered one. I know my error lies somewhere in here, and I'd like a bit of help finding it.
//Create new Sound Object
Sounds *sound = nil;
//check to see whether the normal table or search results table is being displayed and set the Sound object from the appropriate array
if (tableView == self.searchDisplayController.searchResultsTableView) {
sound = [filteredSoundArray objectAtIndex:indexPath.row];
}else{
sound = [soundArray objectAtIndex:indexPath.row];
}
//Configure the cell
[[cell textLabel]setText:[sound name]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSString *selectedSoundFile = [[soundArray objectAtIndex:indexPath.row]name];
NSString *path = [[NSBundle mainBundle]pathForResource:selectedSoundFile ofType:#"mp3"];
if(path){
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[self.theAudio play];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[self.theAudio play];
}
}
Thank you!
change the array in didSelectRowAtIndexPath
NSString *selectedSoundFile = [[soundArray objectAtIndex:indexPath.row]name];
if you are palying from search results then use filteredSoundArray instead soundArray..
The condition which you are playing on select should be played from the array which you are using to display in table view. But you are using the array that have all sounds.
change as follows in didSelectRowIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSString *selectedSoundFile;
if (tableView == self.searchDisplayController.searchResultsTableView) {
selectedSoundFile = [[filteredSoundArray objectAtIndex:indexPath.row]name];
}else{
selectedSoundFile = [[soundArray objectAtIndex:indexPath.row]name];
}
NSString *path = [[NSBundle mainBundle]pathForResource:selectedSoundFile ofType:#"mp3"];
if(path){
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[self.theAudio play];
}
}
I am saving an object from core data to a cell as listed bellow. The URL is being saved to the cell correctly and working great. My problem is that, when a user taps on a cell, I would like the URL that is saved to that cell to be passed to my detailedViewController for use. I have some code that I have tried but the url is nil in the detailedViewController. If you have any better way of accomplishing the same thing, that would be fine. The code is listed bellow -
Here is where I save it to the cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
PhotoCell *cell = (PhotoCell *)[self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[PhotoCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
// Configure the cell...
FeedEntity *feed = [_fetchedResultsController objectAtIndexPath:indexPath];
NSData *data = feed.imageData;
self.feedImage = [UIImage imageWithData:data];
cell.thumbImage = self.feedImage;
NSData *stringData = feed.urlString;
self.stringForURL = [[NSString alloc] initWithData:stringData encoding:NSUTF8StringEncoding];
self.stringForURL = [self.stringForURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
self.finalURL = [NSURL URLWithString:self.stringForURL];
cell.finalURL = self.finalURL;
return cell;
}
Here is where I retrieve the url from the cell and pass it to the detailedViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
// Code to create detailed view and set properties
self.detailsViewController = [[DetailsViewController alloc] init];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
FeedEntity *feed = [_fetchedResultsController objectAtIndexPath:path];
NSData *stringData = feed.urlString;
NSString *stringURL = [[NSString alloc] initWithData:stringData encoding:NSUTF8StringEncoding];
NSLog(#"Here is the string before: %#", stringURL);
stringURL = [self.stringForURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *urlForDetail = [NSURL URLWithString:self.stringForURL];
NSLog(#"Here is the url before it goes to the detailed: %#", urlForDetail);
self.detailsViewController.finalURL = urlForDetail;
[self.navigationController pushViewController:self.detailsViewController animated:YES];
}
Save the video (in didFinishPickingMediaWithInfo:):
self.videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
NSData *videoData = [NSData dataWithContentsOfURL:self.videoURL];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingFormat:#"/vid1.mp4"];
self.urlForSave = [NSURL fileURLWithPath:path];
//Look at YES
[videoData writeToFile:path atomically:YES];
[self saveImageAndVideo];
Here is SaveVideoAndPhoto:
- (void)saveImageAndVideo {
NSManagedObjectContext *context = [self managedObjectContext];
FeedEntity *feedEntity = [NSEntityDescription insertNewObjectForEntityForName:#"FeedEntity" inManagedObjectContext:context];
NSData *imageData = UIImageJPEGRepresentation(self.thumbImage, 0.8f);
self.photoData = imageData;
NSString *stringForSave = [self.urlForSave absoluteString];
NSLog(#"URL before save: %#", stringForSave);
//NSData * stringData = [stringForSave dataUsingEncoding:NSUTF8StringEncoding];
[feedEntity setValue:imageData forKey:#"imageData"];
[feedEntity setValue:[NSDate date] forKey:#"timeStamp"];
[feedEntity setValue: stringForSave forKey:#"urlString"];
NSError *error = nil;
if (![self.managedObjectContext save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
} else {
NSLog(#"URL's are being saved");
}
}
Your problem is in the code in cellForRowAtIndexPath:
self.finalURL = [NSURL URLWithString:self.stringForURL];
You are setting the URL as a property of SELF, which in this case is your viewController. You want to set it on the CELL. Change all that code when you create the cell from self.whatever to cell.whatever if you want to save them as properties of the cell. It might help you if you did some reading up on scope in objective-c.
Also, on a side note, there are a few things you are doing that are unnecessary. Firstly is this:
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
You don't need to create an indexPath object inside this function, because you are already provided it by the function itself with the variable indexPath:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
Secondly, inside of didSelectRowAtIndexPath, if you want to get the url, you should be doing something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// deselect the row if you want the cell to fade out automatically after tapping
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// get a reference to the cell that the user tapped
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// get the url from the cell, assuming your cell has a property called finalURL on it that you set some value
// to originally when it was created
NSURL *url = cell.finalURL;
// do something with that URL here...
}
Keep in mind this is slightly unorthodox. You really should get the information from your tableView's datasource. If you have an array of objects that you are using to populate your tableView, it's probably a better idea to simply get the object itself from our array with the given indexPath rather than save the information on the cell as a property and access it that way. I would highly suggest watching some tutorial videos or do some reading up, preferably in the iOS docs themselves, to try to learn best practices for UITableViews.
New to coding and trying to create a simple check list (like a shopping list) for part of my iOS programme. Selecting a cell changes the accessory icon ok and changing the BOOL value in the dictionary manually before running the simulator also changes the acc' icon fine. So the problem seems to be with the code for altering the BOOL value in the plist after a cell is selected. Any help would massively appreciated. As I said pretty new to it so apologies for any shoddy code or obvious mistakes.
*CODE EDITED SO NO LONGER READING AND WRITING LIST FROM MAIN BUNDLE
#import "CheckListViewController.h"
#import "ListItem.h"
#interface CheckListViewController ()
#end
#implementation CheckListViewController
{
NSMutableArray *eventList;
}
#synthesize tableView = _tableView;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* dataPath = [documentsDirectory stringByAppendingPathComponent:#"CheckList.plist"];
if ( ![[NSFileManager defaultManager] fileExistsAtPath:dataPath]) {
NSString* resourceaPath = [[NSBundle mainBundle] pathForResource:#"CheckList" ofType:#"plist"];
[[NSFileManager defaultManager] copyItemAtPath:resourceaPath toPath:dataPath error:NULL];
}
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"CheckList.plist"];
NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
ListItem *listItem1 = [ListItem new];
listItem1.itemName = #"Read Guide";
listItem1.itemSelected = [dict valueForKey:#"Read Guide"];
.....
eventList = [NSMutableArray arrayWithObjects:listItem1, listItem2, listItem3, listItem4, listItem5, listItem6, listItem7, listItem8, nil];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//Return the number of rows in the section.
return eventList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
ListItem *listItem = [eventList objectAtIndex:indexPath.row];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
if (listItem.itemSelected == [NSNumber numberWithBool:YES]) {
(cell.accessoryType = UITableViewCellAccessoryCheckmark);
} else {
(cell.accessoryType = UITableViewCellAccessoryNone);
}
}
cell.textLabel.text = listItem.itemName;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:NO];
ListItem *listItem = [eventList objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath: indexPath];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"CheckList.plist"];
NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// Reflect selection in data model
[dict setObject:[NSNumber numberWithBool:YES] forKey:listItem.itemSelected];
[dict writeToFile:path atomically:YES];
} else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
// Reflect deselection in data model
[dict setObject:[NSNumber numberWithBool:NO] forKey:listItem.itemSelected];
[dict writeToFile:path atomically:YES];
}
}
#end
Sorry for the massive chunk of code but thought any of it could potentially be problematic.
It looks like the path you are saving to and load from are different. You are loading from a bundle path, and then saving to a relative path with writeToFile:atomically. If my guess is correct, the default path for that method is not back into the bundle, but the documents directory of the app. On iOS, you cannot write back to the main bundle, so there a very good chance the file is not being saved where you think it is.
I am parsing RSS to UITableview and the data looks as it should but when I select one of the field in the UITableview it opens different data then what it should. Also when I scroll the tableview the same field that I have selected gives again different data.
So please where could I made my mistake?
The RSS link: http://www.luaikalkatawi.me/picksound
Thanks from now.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *trimed = [[containerObject.track init] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"The link is %#", trimed);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* cellIdentifier = #"ImgCell";
ImgCell *cell = (ImgCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellIdentifier owner:nil options:nil];
cell = (ImgCell*)[nib objectAtIndex:0];
}
containerObject = [objectCollection objectAtIndex:indexPath.row];//use the common object again for holding the corresponding array object
///// Image reloading from HJCacheClasses
[cell.img clear];
NSString *str1 = containerObject.image; //we use image property of rss object to set the image
NSString *trimmedString = [str1 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSURL *url = [NSURL URLWithString:trimmedString];
cell.img.url = url; //set the url to img view
[self.imgMan manage:cell.img];
cell.mainText.text = containerObject.title; //title member variable for setting title
cell.detailText.text = containerObject.description;//desc variable foe
return cell;
}
I don't know why this is confusing to you, but the correct containerObject, should be accessed in the didSelectRowAtIndexPath.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
containerObject = [objectCollection objectAtIndex:indexPath.row];
NSString *trimed = [[containerObject.track init] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"The link is %#", trimed);
}
I am trying to setup a UITableView that displays the data from the Documents Directory.
I am a bit lost for code, as I have tried many examples from Google and forums etc.
I am creating my app without Storyboard, so it is all in code.
I have got the UITableView displayed, so the delegates and DataView are set - I just need the content.
I have this code to show you, but it is not showing any data:
- (void)viewDidLoad
{
[super viewDidLoad];
_firstViewWithOutNavBar = [[UIView alloc] init];
_firstViewWithOutNavBar.frame = CGRectMake(self.view.frame.origin.x, 0, self.v iew.frame.size.width, self.view.frame.size.height);
_firstViewWithOutNavBar.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_firstViewWithOutNavBar];
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = CGRectMake(self.view.frame.origin.x, 0, self.view.frame.size.width, self.view.frame.size.height);
tableView.delegate = self;
tableView.dataSource = self;
[_firstViewWithOutNavBar addSubview:tableView];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//alloc and init view with custom init method that accepts NSString* argument
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:indexPath.row];
NSString*pathToPass = [documentsDirectory stringByAppendingPathComponent:
[tableView cellForRowAtIndexPath:indexPath].textLabel.text]; //pass this.
NSLog(#"%#", pathToPass);
//_nsarray = [[NSArray alloc] initWithContentsOfFile:pathToPass];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_nsarray count];
NSLog(#"%#", _nsarray);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"%#",[_nsarray objectAtIndex:indexPath.row]];
return cell;
}
Any help would be great.
The array _nsarray which is used as table view data source in numberOfRowsInSection and cellForRowAtIndexPath, is never initialized in your code. You should do something like
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
_nsarray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:docPath error:NULL];
in viewDidLoad.
Did you place the breakpoints in numberOfRowsInSection method to check whether this method has been invoked or not. As I can see in your code you don't have initialize your _nsarray and didn't add any object in that array.
So basically your array contains 0 objects so no row will be created.
In your numberOfRowsInSection method You have placed the nslog after the return statement and this will never be executed please place it before the return statement so that you can actually see the array values.
I hope this will help you.