FYI - Noob iOS developer here.
My current setup is a UIViewController with a UIView within, then a UITableView within the UIVIew. So it goes like this...
UIViewController --> UIView --> UITableView
The reason for this is because I have other elements wrapped with the tableview. The UIViewController loads dynamic content into the table view. I have a segmented Control in which I want to use to switch the content within the table view.
I've read something on [table reload] and [table beginUpdate] but don't understand how to use it. Any help would be great.
You need to implement a method for UIControlEventValueChanged event ofUISegmentedControl for this.
[yourSegmentedControl addTarget:self action:#selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];
And implement the segmentChanged method like:
- (void)segmentChanged:(id)sender
{
UISegmentedControl *mySegment = (UISegmentedControl *)sender;
switch ([mySegment selectedSegmentIndex])
{
case 1:
//load first contents
break;
case 2:
//load second contents
break;
default:
break;
}
[self.yourTableView reloadData];
}
Ok, so [table reloadData] will reload the data (so if you change the data and want to update the table with the necessary data call this), but straight after you call that make sure to call [table setNeedsDisplay] to refresh the UI.[table beginUpdates]
begins a series of method calls that insert, delete, or select rows and sections of the receiver. You end the processes with [table endUpdates];
Make sure you set your table view's dataSource and delegate to self, this can be done through the xib and programmatically like this:
[table setDelegate: self];
or
[table setDataSource: self];
As said:
Call this delegate method for UISegmentedControl
- (void)segmentedControl:(UISegmentedControl*)segmentedControl didSelectIndex:(NSUInteger)selectedIndex
{
if(selectedIndex == 0)
{
// Update the data
}
else if(selectedIndex == 1)
{
// Update the data
}
[table reloadData];
[table setNeedsDisplay];
}
For example,
Your UIView named *myView and your UITableView named *myTableView,
the time you want to reload tableview, in your UIViewController , you should reload tableview like this:
[self.myView.myTableView reload];
and make sure tableview's delegate and dataSourceDelegate is set correctly.
Need to set the delegate & data source for tableview in ViewController.h file like
UITableViewDataSource, UITableViewDelegate.
Implement delegate & datasource methods in ViewController.m file
[tableview SetDelagate:self];
[tableview SetDatasource:self];
Implement the delegate methods.
And reload the table using
[tableView reloadData];
method.
Related
I have a subclass of UITableViewController.
By default, it creates a UITableView when it is initialized. To that tableview I have set a header that I created in Interface Builder in the screen that is controlled by the controller. The header has two buttons:
one to enter editing mode for the tableview (called "Edit")
one to add a random item to the tableview (called "New").
I linked an IBOutlet property called headerView to the header from Interface Builder and I set it to be the header of the UITableView created at initialization in the viewDidLoad method.
The problem is that when I press the "New" button (which adds a new row with a new item to the tableview) the header of the tableview falls down to the bottom of the tableview.
Any idea why? How can I make it stick to the top?
This is the viewDidLoad method:
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"UITableViewCell"];
[self.tableView setTableHeaderView:self.headerView];
}
This is the method that gets executed when the "New" button is pressed:
- (IBAction)addNewItem:(id)sender {
Item *newItem = [[ItemStore sharedStore] createItem];
NSInteger lastRow = [[[ItemStore sharedStore] allItems] indexOfObject:newItem];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:lastRow inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
Thanks.
Possibly you've set up the layout for table header view in a wrong way. Was there any layout constraint on it?
By the way, this project on GitHub is a very simple example to demonstrate how simply it is to achieve what you want in the storyboard. It will produce the result like below:
Please use this project to compare with your current configuration.
I hope this helps in one way or another.
I have placed a button within a uicollectionviewcell and when that button is pressed, it is programmatically setting the cell as selected.
- (void) deleteItem:(id)sender
{
self.selected = YES;
[self.cellOptionsDelegate deleteItem];
}
It then delegates to the uicollectionviewcontroller to deleted the item that is selected.
- (void) deleteItem
{
NSArray* selectedItemsIndexPaths = [self.collectionView indexPathsForSelectedItems];
// Delete the items from the data source.
[self.taskArray removeObjectAtIndex:[[selectedItemsIndexPaths objectAtIndex:0] row]];
// Now delete the items from the collection view.
[self.collectionView deleteItemsAtIndexPaths:selectedItemsIndexPaths];
}
However, when i get the selected items using the uicollectionview method indexPathsForSelectedItems, it is not seeing that I have selected the item and the list is empty. I am using the press to select delegate method for another functionality so I was hoping to do something along the lines of what I explained above. Is there a way to make this work or a better way to inform the controller that the button pressed in the cell was tied to a cell at a specific index path?
Thank you.
Just send a cell pointer from your cell's deleteItem method
- (void) deleteItem:(id)sender
{
self.selected = YES;
[self.cellOptionsDelegate deleteItem:self];
}
and change uicollectionviewcontroller's method to
- (void) deleteItem:(UICollectionViewCell*)cellToDelete
{
NSIndexPath indexPathToDelete = [self indexPathForCell: cellToDelete];
// Delete the items from the data source.
[self.taskArray removeObjectAtIndex:[indexPathToDelete row]];
// Now delete the items from the collection view.
[self.collectionView deleteItemsAtIndexPaths:#[indexPathToDelete]];
}
Do not forget to update '(void) deleteItem:(UICollectionViewCell*)cellToDelete' declaration in your *.h file.
Solved by sending the cell through the delegate method and using this:
NSIndexPath* indexPath = [self.collectionView indexPathForCell:cell];
animated:
[self.collectionView performBatchUpdates:^ {
[_array removeObject:file];
[self.collectionView deleteItemsAtIndexPaths:#[indexPath]];
} completion:nil];
In the Apple reminders App, and in the details screen of a remind,
when you switch on the control "Remind me at a location", a row "Location" is added (in fact a table view cell).
I would like to do the same in one of my application, when a switch control is actived 2 cells are added... how can i do this?
Thank you for your help
Check out this Project
https://github.com/singhson/Expandable-Collapsable-TableView
It may helps you.
in the method handling the change of your UISwitch you could either just reload the complete tableview using -(void)reloadData or (much nicer) use - (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
You can use UISwitch as accessory view in one of your cells. However, you can face problems with reusing cells. If you need only one row with switch, you can simply add the UISwitch as a strong property in your TableViewController. You have to create it when initializing the controller:
self.locationSwitch = [[UISwitch alloc] init];
[self.locationSwitch addTarget:self action:#selector(handleSwitchValueChanged:) forControlEvents:UIControlEventValueChanged];
And then you can use it as an accessory view for your UITableViewCell:
cell.accessoryView = self.locationSwitch;
And you have to add (or remove) rows when switch value changes":
-(void)handleSwitchValueChanged:(id)sender
{
NSIndexPath* indexPath = // calculate your index path;
if(self.locationSwitch.on) {
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
else {
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
And also remember to update your data source, so the value returned by tableView:numberOfRowsInSection is consistent with value of self.locationSwitch.
I created a custom UITableViewCell subclass with multiple fields and some other properties. Since I used this new cell in my UITableViewController, the cells do not react on the "swipe to delete" gesture.
To test if I'm missing something in my delegate I added a plain standard UITableView to my xib, hooked up dataSource and delegate and returned a regular UITableViewCell from -tableView:cellForRowAtIndexPath: this enabled the gesture again.
I searched on the net and one suggested to plain implement -layoutSubviews which didn't work too.
Is there something I would have to implement in my subclass?
After hours of searching and not finding anything on the internet, I did a whole day trial and error to find out that in my XIB the Editing was set to Multiple Selection During Editing.
I didn't know that this would disable the "Swipe-To-Delete-Functionallity".
As I need both possibilities (s2d unless editing and multiple selection while editing) I added these two lines in my -toggleEditing: method:
if(![_tableView isEditing]) {
[_tableView setAllowsMultipleSelectionDuringEditing:YES]; // <----
[_tableView setAllowdSelectionDuringEditing:YES]; // <----
[_tableView setEditing:YES animated:YES];
}
else {
[_tableView setAllowsMultipleSelectionDuringEditing:NO]; // <----
[_tableView setAllowdSelectionDuringEditing:NO]; // <----
[_tableView setEditing:NO animated:YES];
}
I would like to manipulate table cells in my UITableView as it comes back from its detail view, to remind the user what row they last selected. The UITableView was created in IB and there currently isn't a #property or custom class for the UITableView or any other handle. Clearly, it exists when, the user is coming back from the detail view and viewWillAppear is called but I don't see any handle in the debugger for my UITableView.
Any way to simply get a handle to the IB tableView object?
// - The Containing ViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSIndexPath *selected = [self.tableView indexPathForSelectedRow];
if(selected){
//Do something stylish with the last-selected row
NSLog(#"Last row selected was: %#",selected);
}
}
I solved this by creating a class member of NSIndexPath * and set it inside didSelectRowAtIndexPath. Then, when viewWillAppear executes, when the user navigates back fram the table view detail, I have the last-selected row so I can easily highlight it or treat it any way I want:
//The Containing View Controller
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if(self.lastSelectedRow){
[self.tableView selectRowAtIndexPath:self.lastSelectedRow animated:YES scrollPosition:UITableViewScrollPositionNone];
}
}