I have UICollectionView that has two UICollectionResuabeView(Custom View) and one UICollectionViewCell. The form a single entity in UICollectionView. I put Delete button on one of UICollectionResuabeView and by pressing it want to delete the row (if i call it right).
This is the screenshot form Storyboard:
I tried getting section of it my many means, but non works. Guess I just dont have enough knowledge of how UICollectionView works. Here is some code I tried:
I know its I mess, but at least I was trying ))
I ve tried this toget indexPath, but none works.
-(IBAction)deletePressed:(UIButton* )sender{
RecipeCollectionHeaderView *contentView = (RecipeCollectionHeaderView *)[sender superview];
RecipeViewCell *cell = (RecipeViewCell *)[contentView superview];
cell = (RecipeViewCell *)[contentView superview];
// determine indexpath for a specific cell in a uicollectionview
NSIndexPath *editPath = [self.collectionView indexPathForCell:cell];
NSInteger rowIndex = editPath.row;
NSInteger secIndex = editPath.section;
// NSIndexPath *indexPath = nil;
// indexPath = [self.collectionView indexPathForItemAtPoint:[self.collectionView convertPoint:sender.center fromView:sender.superview]];
// NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
// NSSet *touches = [event allTouches];
//
// UITouch *touch = [touches anyObject];
//
// CGPoint currentTouchPosition = [touch locationInView:self.collectionView];
//
// NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint: currentTouchPosition];
NSLog(#"IndexPath CollectionView %ld", (long)rowIndex);
}
I also tried make it work like in this post, but it does not give a result:how to access from UICollectionViewCell the indexPath of the Cell in UICollectionView
Thank you all!
EDIT!
I found this works well:
-(IBAction)deletePressed:(UIButton* )sender{
[self.ordersArray removeObjectAtIndex:0];
[self.collectionView reloadData];
}
The only thing I need now is to get section of UICollectionView by UIBotton that been pressed, to delete section I want. How to do it?)
You also need to remove item from the array and UICollectionView as well.
Try to use this code.
-(void) deleteRow:(NSInteger)index {
[self.contentView performBatchUpdates:^{
[arrayForRows removeObjectAtIndex:i];
NSIndexPath *indexPath =[NSIndexPath indexPathForRow:i inSection:0];
[self.contentView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
} completion:^(BOOL finished) {
}];
}
For cell selection use this code snippet:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
//Item position that you would like to delete.
indexPath.row;
}
Related
I'm trying to implement peek and pop feature in my application.but since I can't test it yet, I wanted to know if I was doing it correctly, I feel something is wrong?
- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location
{
NSLog(#"TEST");
NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:location];
if (indexPath) {
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
NSDictionary *dict = [self.array objectAtIndex:indexPath.row];
cell.textLabel.text = [dict objectForKey:#"name"];
DetailViewController *previewController = [[DetailViewController alloc] init];
// previewController.content = content;
previewingContext.sourceRect = cell.frame;
return previewController;
}
return nil;
}
I'm currently implementing this in our app and that looks mostly right. A problem I encountered is that the coordinates given to you in location are for the UIViewController's view, not the UITableView. Depending on your setup, they may be the same, but in my case, I needed to convert the location to the UITableView's coordinates.
CGPoint convertedLocation = [self.view convertPoint:location toView:self.tableView];
Of course, your mileage may vary.
You should not need to correct the location if you registered the previewDelegate with the correct sourceView. So instead of
[self registerForPreviewingWithDelegate:self sourceView:self.view];
you should register it this way:
[self registerForPreviewingWithDelegate:self sourceView:self.tableView];
Then location you get from the delegate call takes scrolling / contentOffset into account.
The only problem with your code is the way to get convertedLocation is not right.
Below code will get correct location even after you scroll the table view.
CGPoint convertedLocation = [self.tableView convertPoint:location fromView:self.view];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:convertedLocation];
I have developed a UITableView with some cells that could have subcells.
Example:
My app allows users to move cells position but, when a table has got one or more cell with subcells, I collapse all of them in order to allow only move cells with the same identation (or in the same level)
If the table is pretty long, when I collapse cells with subelements, I use indexPath of that cell to remove the subelements from the table. My problem is that some of that cells are not in memory so I get a crash.
How can I detect that a cell is not being showed in order only remove the element from the dataSource?
This is my method to collapse/expand elements:
- (void)expandCollapseSubtasks:(UIButton *)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:_taskTableView]; //when CGPoint = 0,0 not remove cells?
NSIndexPath *indexPath = [_taskTableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
Task *task = [_tasks objectAtIndex:indexPath.row];
TaskTitleCell *cell = (TaskTitleCell *)[_taskTableView cellForRowAtIndexPath:indexPath];
UILabel *subtasksNumberLabel = (UILabel *)[cell viewWithTag:107];
UIButton *subtasksButton = (UIButton *)[cell viewWithTag:108];
NSMutableArray *subtasksIndexPaths = [[NSMutableArray alloc] init];
NSNumber *hidden;
//Expand
if (!subtasksButton.selected){
hidden = #0;
subtasksNumberLabel.textColor = [UIColor colorWithRed:72.0/255.0 green:175.0/255.0 blue:237.0/255.0 alpha:1.0];
NSDictionary *subtasksAndIndexesDictionary = [task getSubtasksIndexesInTaskCollection:_tasks ofList:task.list];
NSIndexSet *indexes = [subtasksAndIndexesDictionary objectForKey:#"indexes"];
NSArray *subtasks = [subtasksAndIndexesDictionary objectForKey:#"subtasks"];
[_tasks insertObjects:subtasks atIndexes:indexes];
[indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
NSIndexPath *subtaskIndexPath = [NSIndexPath indexPathForRow:idx inSection:0];
[subtasksIndexPaths addObject:subtaskIndexPath];
}];
[_taskTableView insertRowsAtIndexPaths:subtasksIndexPaths withRowAnimation:UITableViewRowAnimationTop];
//Collapse
}else{
hidden = #1;
subtasksNumberLabel.textColor = [UIColor whiteColor];
NSArray *subtasks = [task getSubtasks];
[_tasks removeObjectsInArray:subtasks];
for (int i=1;i<=subtasks.count; i++){
NSIndexPath *subtaskIndexPath = [NSIndexPath indexPathForRow:indexPath.row+i inSection:0];
[subtasksIndexPaths addObject:subtaskIndexPath];
}
[_taskTableView deleteRowsAtIndexPaths:subtasksIndexPaths withRowAnimation:UITableViewRowAnimationBottom];
}
subtasksButton.selected = !subtasksButton.selected;
task.hidesubtasks = hidden;
[[NSManagedObjectContext defaultContext] saveToPersistentStoreAndWait];
}
}
And the call
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
UITableViewCell *cell = [_taskTableView cellForRowAtIndexPath:indexPath];
UIButton *subtasksButton = (UIButton *)[cell viewWithTag:108];
[self expandCollapseSubtasks:subtasksButton];
Where idx is the position of the element in the dataSource
You can get array of NSIndexPath for all visible cells:
NSArray *array = [self.tableView indexPathsForVisibleRows];
You can also get array of cells itself instead of NSIndexPath:
[tableView visibleCells]
That what you need to find out the invisible cells.
My question is clear,
I have a UITableView and UIMapView with annotations, when an annotation is tapped on the map, it will be found on the table and be selected since the user can recognize it.
But, if i try something it is only in visible cells, i am not able to do as i expected.
- (void)annotationTapped:(UITapGestureRecognizer *)recognizer{
if ( recognizer.state == UIGestureRecognizerStateEnded ) {
//NSLog(#"%#",[recognizer.view subviews]);
UIImageView *temp = (UIImageView*)[recognizer.view viewWithTag:1000];
UILabel *temp2 = (UILabel*)[temp viewWithTag:1001];
NSArray *tapAndFind;
if(isFiltered)
{
tapAndFind = filteredListContent;
}
else
{
tapAndFind = eczaneler;
}
for(int i=0;i<tapAndFind.count;i++)
{
Pharma *tempPharm = [tapAndFind objectAtIndex:i];
if([tempPharm.CustomerIndex isEqualToString:temp2.text])
{
EczaneCell *cell = (EczaneCell*)[tableView1 cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
for(EczaneCell * cell2 in [tableView1 visibleCells])
{
cell2.selected = NO;
}
cell.selected = YES;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[tableView1 indexPathForCell:cell].row
inSection:[tableView1 indexPathForCell:cell].section];
[tableView1 scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
}
}
This is because your UITableView is just a presentation of your data, not a data itself. So, when you tap on annotation, you should somehow find a correspondence with a data, the position of your annotation data in collection. Then you may calculate/find out the index of row in table, and then you can perform UITableView's scrollToRowAtIndexPath:atScrollPosition. Alternatively, you can mark the cell to make it distinguishable.
In your code
EczaneCell *cell = (EczaneCell*)[tableView1 cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
can return nil for cell when the cell for given index path is invisible. That's why you should check against data, not table cells.
how can i find out in which section i clicked? i need the number to send the item to another view:
- (IBAction)mapButton:(id)sender {
UIButton * myButton = sender;
int row=myButton.tag;
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:row inSection:0];
MapViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"mapView"];
self.selectedStandort = [self.fetchedResultsController objectAtIndexPath:indexPath];
detail.currentStandort = self.selectedStandort;
[self.navigationController pushViewController:detail animated:YES];
}
Is the mapButton a subview of the UITableViewCell?
Then I would do the following:
NSView *contentView = [sender superview];
NSTableViewCell *cell = (UITableViewCell *)[contentView superview];
NSIndexPath *cellIndexPath = [myTableView indexPathForCell:cell];
NSInteger section = cellIndexPath.section;
You can also use the row from the cellIndexPath, so you don't have to keep your tag value up to date (e.g. on reuse, reorder and delete) which makes your implementation less error-prone.
Sorry I'm pretty new to iOS dev.
I have a UITableView setup from cells being pulled from a single XiB nib. I've created a on/off switch in the nib, and I am trying to save the state of the switch upon viewWillDisappear for the number of cells that I have. (6 cells to be exact).
How can I loop through all the cells and save this information?
I tried this in my UIViewController to get the info for one cell:
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
UITableView *tv = (UITableView *)self.view;
UITableViewCell *tvc = [tv cellForRowAtIndexPath:0];
}
it gives me the error "Program received signal: "EXC_BAD_INSTRUCTION".
How can I accomplish this?
You have to pass a valid NSIndexPath to cellForRowAtIndexPath:. You used 0, which means no indexPath.
You should use something like this:
UITableViewCell *tvc = [tv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
BUT. Don't do this. Don't save state in the UITableViewCell.
Update your dataSource when a switch changed its state.
If you have implemented the UITableViewDataSource methods the right why your tableView reuses cells. That means the state of your cells will vanish when the cells are reused.
Your approach might work for 6 cells. But it will fail for 9 cells.
It will probably even fail if you scroll the first cell off screen.
I wrote a quick demo (if you don't use ARC add release where they are necessary) to show you how you should do it instead:
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataSource = [NSMutableArray arrayWithCapacity:6];
for (NSInteger i = 0; i < 6; i++) {
[self.dataSource addObject:[NSNumber numberWithBool:YES]];
}
}
- (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];
UISwitch *aSwitch = [[UISwitch alloc] init];
[aSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = aSwitch;
}
UISwitch *aSwitch = (UISwitch *)cell.accessoryView;
aSwitch.on = [[self.dataSource objectAtIndex:indexPath.row] boolValue];
/* configure cell */
return cell;
}
- (IBAction)switchChanged:(UISwitch *)sender
{
// UITableViewCell *cell = (UITableViewCell *)[sender superview];
// NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
CGPoint senderOriginInTableView = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:senderOriginInTableView];
[self.dataSource replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:sender.on]];
}
as you see it's not very complicated to not store state in the cells :-)
Moving [super viewDidDisappear:animated]; to the end of your method may be the most expedient way to address the problem. If that does not work, move the logic into viewWillDisappear:animated:.
A better way to deal with this would be to avoid reading the current state from the view at all. Rather, the view should pass the state to the model on each update. This way you would be able to harvest the current state from your model, entirely independently from the state of your view.