I have a problem where i cant seem to reload the data in my tableView.
What i am trying to do is populate my tableView with files in the documents directory with a csv extension (which i have done), then press a button which deletes all the displayed files and the updates the tableView.
The button when pressed deletes the files in the documents directory but does not reload the tableView with the updated content.
I have used breakpoints to confirm that reloadData is being run.
I have tried using removeAllObjects to clear my array before running
reloadData using NSLog to confirm the array is empty, however this
does not update the table.
I have tried setting the array to nil before running reloadData, this does not work either.
I have tried setting the data in the array to myArray = #[]; before
running reloadData, this overwrites the array with blank data but
does not update the table.
I have tried using this method without
any success:
dispatch_sync(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
I have checked my delegates for the tableView and they appear
correct, (all other functionality in the tableView works including
selecting/deselecting multiple items and deleting individual items
and on each occasion the tableView updates).
I have also searched multiple different questions similar to mine and still have not found an answer.
Could someone please check my method below and tell me why the tableView is not reloading properly? i'm sure its something i have done wrong somwhere but i cant find it.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [filePathsArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MainCell"];
}
_docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [_docPath objectAtIndex:0];
_fileList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:nil];
NSPredicate *fltr = [NSPredicate predicateWithFormat:#"self ENDSWITH '.csv'"];
_csvFilesCell = [_fileList filteredArrayUsingPredicate:fltr];
NSLog(#"Contents of directory: %#", _csvFilesCell);
filePathsArray = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:documentsDirectory error:nil];
cell.textLabel.text = [_csvFilesCell objectAtIndex:indexPath.row];
return cell;
}
-(IBAction) deleteStoredData:(id)sender
{
NSLog(#"Delete data button pressed");
UIAlertController*alert = [UIAlertController alertControllerWithTitle:#"Delete stored Data" message:#"Are you sure?" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* OK = [UIAlertAction actionWithTitle:#"Delete" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
NSFileManager *manager = [NSFileManager defaultManager];
// the preferred way to get the apps documents directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
// grab all the files in the documents dir
NSArray *allFiles = [manager contentsOfDirectoryAtPath:documentsDirectory error:nil];
// filter the array for only csv files
NSPredicate *fltr = [NSPredicate predicateWithFormat:#"self ENDSWITH '.csv'"];
NSArray *csvFiles = [allFiles filteredArrayUsingPredicate:fltr];
// use fast enumeration to iterate the array
for (NSString *csvFile in csvFiles) {
NSLog(#"PATH %# : FILE %#", documentsDirectory, csvFile);
NSError *error = nil;
[[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:#"%#/%#", documentsDirectory, csvFile]
error:&error];
NSLog(#"Error: %#", error);
NSLog(#"OK button selected, all data deleted");
[self updateDeleteButton];
[self.tableView reloadData];
[alert dismissViewControllerAnimated:YES completion:nil];
}
}];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
NSLog(#"Cancel button selected, no data deleted");
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:OK];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
}
After seeing your code, I came up with the following solution, hope it helps you !!
_docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [_docPath objectAtIndex:0];
_fileList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:nil];
NSPredicate *fltr = [NSPredicate predicateWithFormat:#"self ENDSWITH '.csv'"];
_csvFilesCell = [_fileList filteredArrayUsingPredicate:fltr];
NSLog(#"Contents of directory: %#", _csvFilesCell);
filePathsArray = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:documentsDirectory error:nil];
The above code should be triggered at the click of delete button, not in the tableview's data-source method. After that you should reload your tableview and your cellForRowAtIndexPath method should be like :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MainCell"];
}
cell.textLabel.text = [_csvFilesCell objectAtIndex:indexPath.row];
return cell;
}
Related
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.
I just want the user to just delete a picture by just tapping the picture using a collection view. I am doing this for a month and can't get things straight and even getting confused. My code for to do this is below. I am also getting a memory warning sometimes aswell, If i use the instruments app to look for detail the memory allocation does not get freed and just builds up until crash.
- (void)viewDidLoad
{ Trash = [NSMutableArray array];
filenames = [NSMutableArray new];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *locationStrings = [[NSArray alloc]initWithObjects:#"Bottoms", #"Dress", #"Coats", #"Others", #"hats", #"Tops",nil ];
for(NSString* location in locationStrings){
NSString *fPath = [documentsDirectory stringByAppendingPathComponent:location];
NSError *error;
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:fPath error:&error];
collectionTrash.delegate =self;
collectionTrash.dataSource=self;
for(NSString *str in directoryContent){
NSString *finalFilePath = [fPath stringByAppendingPathComponent:str];
[filenames addObject:finalFilePath];
}
}
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
NSLog(#"j");
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [filenames count];
NSLog(#"b");
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"ReuseID";
TrashCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[cell viewWithTag:1];
NSString *cacheKey = filenames[indexPath.item];
imageInCell.image = [self.imageCache objectForKey:cacheKey];
if (imageInCell.image == nil) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image = [UIImage imageWithContentsOfFile:filenames[indexPath.item]];
if (image) {
[self.imageCache setObject:image forKey:cacheKey];
dispatch_async(dispatch_get_main_queue(), ^{
TrashCell *updateCell = (id)[collectionView cellForItemAtIndexPath:indexPath];
UIImageView *imageInCell = (UIImageView*)[updateCell viewWithTag:1];
imageInCell.image = image;
});
}
});
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"s:%d", [Trash count]);
NSString *trashBin = [Trash objectAtIndex:indexPath.row];
NSLog(#"k%#l",trashBin);
[filenames removeObjectAtIndex:indexPath.row];
[Trash removeObjectAtIndex:indexPath.row];
[self deleteMyFiles:trashBin];
[collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]];
}
NSString *myFileName;
-(void) deleteMyFiles:(NSString*)filePath {
NSError *error;
if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
} else {
NSLog(#"%#",filePath);
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
[self.imageCache removeAllObjects];
}
When I try to tap a log comes out saying below.
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
(0x30afbe83 0x3ae5c6c7 0x30a31d95 0x638e9 0x3349d76f 0x3349d495 0x33406ea3 0x33406ea3 0x332781a1 0x332af9fd 0x332af3ab 0x33284d79 0x33283569 0x30ac6f1f 0x30ac63e7 0x30ac4bd7 0x30a2f471 0x30a2f253 0x357632eb 0x332e4845 0x628a5 0x3b355ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
Your Trash array not content any objects.
And you are trying to access object from Trash array
NSString *trashBin = [Trash objectAtIndex:indexPath.row];
Which is the cause of crash.
Note: object name should start with small letters.
In your code, Trash = [NSMutableArray array]; will be autoreleased at some time, so when you access it in '-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath', it has been released. If you are sure there is reason to use this variable instead of using only filenames, you can do this Trash = [[NSMutableArray array] retain]; or Trash = [[NSMutableArray alloc] init]; in your '- (void)viewDidLoad'.
It is not clear what you are trying to do. The notion of "Trash" suggests you are trying to implement a two-stage delete: put items in the trash and at some later time, empty the trash (delete them for good when the user selects an "Empty the Trash" button). But your post and your code suggest a single-stage delete (the user selects to delete with no chance to undo).
Your collectionView:didSelectItemAtIndexPath: delegate method looks particularly confused. As Bhumeshwer correctly points out, your Trash is empty and trying to access any index is causing your crash. No where in this code are you putting anything in Trash But, by simply removing that line of code, I don't think the method will do what you want.
If you are implementing a two-stage delete, I think you simply want to remove the string from filenames and add it to Trash. Don't remove the object from Trash and don't delete files in Trash. Somewhere else (like when the "Empty the Trash" button is selected), call deleteMyFiles to empty the trash.
If you are implementing a single-stage delete, get rid to Trash all together: don't allocate it in viewDidLoad and don't empty it in didSelectItemAtIndexPath. Simply, remove the object from filenames AND update the imageInCell!
Suggestions:
move
collectionTrash.delegate =self;
collectionTrash.dataSource=self;
to wherever collectionTrash is being created and initialized. Inside viewDidLoad and inside the for loop, it is out of context. Your mixing unrelated lines of code making your code unorganized and confusing. At least, move it out of the for loop.
think model-view-controller. What's the model here? Is it filenames or Trash? Is the CollectionView a view of filenames or Trash? What is collectionTrash?
Trash should be trash (as Bhumeshwer points out);
what is NSString *myFileName; and what's it doing there?
don't forget to manage your imageCache. You put images in but don't take them out. When you remove a file from filenames, remove the image from imageCache.
I could go on, but will stop here. Good luck.
I am loading an array of items from a plist. A user can select any item and add it to a new array of items which is shown on screen.
I am doing this but a user can also delete a player from any row. My problem is when a user deletes the object it shuffles the list up. Where as I want to keep that row blank.
My deletion code:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *user_id = [prefs objectForKey:#"user_id"];
NSString *fixture_id = [prefs objectForKey:#"fixture_id"];
// Get path to documents directory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
[self.usersSelectionArray removeObjectAtIndex:indexPath.row];
if (self.usersSelectionArray == nil) {
// disable swipe to delete?
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if ([paths count] > 0)
{
// Path to save array data
NSString *arrayPath = [[paths objectAtIndex:0]
stringByAppendingPathComponent:[NSString stringWithFormat:#"%#-%#",user_id, fixture_id]];
// Write array
[self.usersSelectionArray writeToFile:arrayPath atomically:YES];
}
// If blank array delete the file as not required
if (self.usersSelectionArray.count == 0) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#-%#", user_id, fixture_id]];
NSError *error;
if(![[NSFileManager defaultManager] removeItemAtPath:path error:&error])
{
//TODO: Handle/Log error
}
}
[self.tableView reloadData];
}
It also checks if the count is 0 and deletes the plist, re-creates on load if required.
So you want to remove an object from your data array, but keep an empty cell for it in the table?
In that case I recommend replacing the removed object with an NSNull instance.
[myMutableArray replaceObjectAtIndex:index withObject:[NSNull null]];
You can then check if the object for a cell is NSNull and return an empty cell in the cellForRowAtIndexPath: data source method.
id object = // get the correct object from your data array, depending on the index
BOOL isEmpty = [object isKindOfClass:[NSNull class]];
if (isEmpty) {
// return empty table cell
else {
// return a normal cell
}
Instead of [self.usersSelectionArray removeObjectAtIndex:indexPath.row];, try [self.usersSelectionArray replaceObjectAtIndex:indexPath.row withObject:[NSNull null]];. That will keep the row but it will contain practically nothing
Firstly = I apologize because I have already tried to ask this once before here
I am really struggling with this:
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the row from the data source.
[_mainTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
By using the code above I know it is possible to delete an entry from an array that is displayed in a UITableView. However I am wanting to delete files form my Documents Directory that are downloaded by the user and no longer required.
Now I in the mean time and after more searching this code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *file = [[NSString alloc] init];
for(int i=0; i<[paths count]; i++)
{
file = [documentsDirectoryPath stringByAppendingFormat:#"/%#",_fileArray];
NSLog(#"%#", file);
}
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:file error:NULL];
Allows me to list all the files that are in the array in my console and this code:
- (void)removeFile:(NSString*)fileName {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.mp3", fileName]];
[fileManager removeItemAtPath: fullPath error:NULL];
NSLog(#"image removed");
}
together with: [self removeFile: _filename]; allows me to delete a specific file.
so I am making head way. But I am really stuck when it comes to a user being able to swipe and delete a file. Of Course I do not know what file is going to be in the directory.
Secondly - How do I handle being able to load the tableView once all the files are deleted?
If I do that using this code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if ([paths count] > 0)
{
NSLog(#"Path: %#", [paths objectAtIndex:0]);
NSError *error = nil;
NSFileManager *fileManager = [NSFileManager defaultManager];
// Remove Documents directory and all the files
BOOL deleted = [fileManager removeItemAtPath:[paths objectAtIndex:0] error:&error];
}
I get the an termination error - I think that is because the directory has also been removed.
I know there is a bit of code here, but I really hope someone and guide me through this:-)
If i correctly understood, you want step by step guide.
Lets consider that you have a working UITableView (mainTableView) that take data from NSMutableArray (mainArray).
This will return document directory path.
-(NSString*)filePath{
NSString *path=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSLog(#"%#",path);
return path;
}
Somewhere we need to init array ,i did it on viewDidLoad.
- (void)viewDidLoad
{
[super viewDidLoad];
mainDataArray=[[NSMutableArray alloc]init];
[self loadContentsOfDirectory:[self filePath]];
}
//here i am adding names of files from documents directory
-(void)loadContentsOfDirectory:(NSString*)path
{
NSError *error=nil;
NSArray *pathArray=[[NSFileManager defaultManager]contentsOfDirectoryAtPath:path error:&error];
if (error) {
NSLog(#"ERROR: %#",error);
}else{
if (pathArray) {
[mainDataArray removeAllObjects];
[mainDataArray addObjectsFromArray:pathArray];
}
}
}
#pragma mark UITableView_Methods
//delete file then if file is deleted , remove filename from array and remove cell
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSString *fileName=[mainDataArray objectAtIndex:indexPath.row];
NSError *error=nil;
NSString *pathToDelete=[[self filePath]stringByAppendingPathComponent:fileName];
BOOL succes=[[NSFileManager defaultManager]removeItemAtPath:pathToDelete error:&error];
if (error) {
NSLog(#"ERROR: %#",error);
}
// if file is succes deleted
if (succes) {
//remove this item from array
[mainDataArray removeObject:fileName];
//and remove cell
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}else{
UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:#"Alert!" message:#"File can not be deleted" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertView show];
}
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [mainDataArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *reusableCell=#"cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:reusableCell];
if (cell==nil) {
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reusableCell];
}
cell.textLabel.text=[mainDataArray objectAtIndex:indexPath.row];
return cell;
}
I think your error is that you do not remove something maybe cell, object in array.
Hope this will help.
If you want to delete selected files from your Documents directory then.
First you have to get all files from Documents directory of your app like this
-(NSArray *)listFileAtPath:(NSString *)path
{
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
return directoryContent;
}
Then use return array from above function to display files to UITableView
NSArray *filesArray = [self listFileAtPath:documentDirectoryPath];
And finally when you delete selected files then you have to remove that file from Documents directory and also from filesArray for managing UITableView something like this:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the row from the data source.
[_mainTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
// Remove file from document directory
NSError *error = nil;
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL deleted = [fileManager removeItemAtPath:[paths objectAtIndex:0] error:&error];
// Remove file entry from filesArray
[filesArray removeObjectAtIndex:indexPath.row];
}
}
Hope will help you if you want to do something like this.
A friend and I are working on a grocery list app and having some trouble with [tableView reloadData];. We're storing our grocery lists in plists and have an add items subview. When you leave that subview to return to the list, the list doesn't contain the new items even though we are updating the plist and calling reloadData in viewWillAppear. It does work though; if we navigate back to the master list of all lists and then back into the specific list we just added items to, the items then show up. Similarly, we want to delete items from the list by just selecting the row and having a checkmark appear next to the item. The list doesn't automatically update when a row is selected though, even though we're calling reloadData in didSelectRowAtIndexPath as well. Again, the change shows up if we navigate back to the master list and then go back into the individual list. I've checked and the delegate and dataSource in the nib files are correctly linked up to File's Owner.
Here's the code for the viewWillAppear:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// THIS IS WHERE YOU PASS THE VARIABLE
iGrocerAppDelegate *passTest = [[UIApplication sharedApplication] delegate];
NSString *listName = [passTest passList];
[passTest setPassList:listName];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *fullListName = [NSString stringWithFormat:#"%#.plist", listName];
NSString *file = [[paths lastObject] stringByAppendingPathComponent:fullListName];
self.list = [[NSArray alloc] initWithContentsOfFile:file];
[listTableView reloadData];
}
and didSelectRowAtIndexPath:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:
indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
int row = [indexPath row];
NSString *deleteItem = [self.list objectAtIndex:row];
[self.itemsToDelete addObject:deleteItem];
// RECEIVE PASSED VARIABLE
iGrocerAppDelegate *test = (iGrocerAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *listName = [test passList];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *fullListName = [NSString stringWithFormat:#"%#.plist", listName];
NSString *file = [[paths lastObject] stringByAppendingPathComponent:fullListName];
//NSMutableArray *groceryLists = [[NSMutableArray alloc] initWithContentsOfFile:file];
//NSMutableArray *groceryList1 = [[NSMutableArray alloc] initWithContentsOfFile:file];
NSMutableArray *groceryList = [[NSMutableArray alloc] initWithContentsOfFile:file];
NSMutableArray *removeFromList = self.itemsToDelete;
int itemCount = [removeFromList count];
NSLog(#"Count: %d", itemCount);
for(int i=0; i < itemCount; i++) {
NSString *item = [removeFromList objectAtIndex:i];
NSLog(#"%#", item);
[groceryList removeObject:item];
NSLog(#"Middle ARRAY: %#", groceryList);
//[groceryList addObjectsFromArray: addToList];
}
NSLog(#"FINAL ARRAY: %#", groceryList);
if(![groceryList writeToFile:file atomically:YES]) {
NSLog(#"unsuccessful");
} else {
NSLog(#"successful");
}
NSLog(#"file name: %#",file);
self.list = [[NSArray alloc] initWithContentsOfFile:file];
NSLog(#"updated grocery list: %#", self.list);
[listTableView beginUpdates];
//[listTableView reloadData];
[listTableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:NO];
[listTableView endUpdates];
printf("list table view reloaded");
}
Any help would be much appreciated! Thanks in advance!
Solved.
It just needed to be:
[self.tableView reloadData];