reordering control in UITableView - iphone

I am developing a game in which I am using a UITableView which has custom cell (UItableViewCell subclass).
In editing mode:
Only the reordering control of the UITableView should show.
Right now I am getting the delete and the reordering control.
How to get only reordering control while editing ?

I know this answer might be late, but I'm putting it just for people who still need it.
Just implement the following methods:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
}

You should use this method for hiding delete button.
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}

thanks a lot oxigen it worked ....
i was writing this in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
cell.showsReorderControl = YES; // to show reordering control
return cell;
}
but i dint write the method which you have given
Thanks a tons

Swift 5.0
If you want to disable all other editing options for your tableView's cells except the one that allows you to reorder them then just implement those methods from UITableViewDelegate:
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
true
}
// Removes the ability to delete current cell
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
.none
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
true
}

tableView.showsReorderControl = YES; // to show reordering control
To dissmiss delete control, in your UITableViewDelegate add
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}

Related

TableView do not enter in willDisplayCell

My goal is define my own cell style, with background, font and size. I try this.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ScreenListElements *currentScreenElement = [self.screenDefBuild.elementsToTableView objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:currentScreenElement.objectName];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:currentScreenElement.objectName];
}
cell.textLabel.text = currentScreenElement.objectName;
return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.contentView.backgroundColor = [UIColor blackColor];
}
I would like to change cell backgrond, but my app doesn't enter to willDisplayCell method. I have declared my class as:
#interface MyTableView : UIViewController <UITableViewDataSource,NSCopying> {
}
Should i have something else? Or maybe is a better way to declare own cell style.
#interface MyTableView : UIViewController <UITableViewDataSource, UITableViewDelegate ,NSCopying> {
}
the method
tableView:willDisplayCell:forRowAtIndexPath
is delegate method of UITableView
EDITED (to make it correct & accepted answer)
setting delegate
[myTableView setDelegate:self];
Ok, i saw, that you didn't implement the "UITableViewDelegate" protocol, only dataSource...
So it surely doesn't enter delegate methods.
Be sure it is like so:
#interface MyTableView : UIViewController <UITableViewDataSource, UITableViewDelegate ,NSCopying> {
}
Check UITableviewCell Delegate Protocol :
- (void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath{
cell.contentView.backgroundColor = [UIColor blackColor];
}
I had the same issue where I set all the things correct but if you have your function written manually you might miss the syntax and this error occurs:
(Instance method 'tableView(tableView:willDisplayCell:forRowAtIndexPath:) nearly
matches optional requirement tableView(_:willDisplay:forRowAt:) of
protocol UITableViewDelegate
This way the function is not going to be recognised, write the function correctly:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
If the delegate is assigned to self this will work, else it's gonna show the error as you write the code.

When moving cells in UITableView, how do I make a cell remain stationary?

I have a list of people that occupy spots. I want the user to be able to rearrange these people into different spots, however, some spots are off limits. I thought this would be most easily accomplished using UITableView's rearrangement capabilities. However, I can't figure out how to keep my unavailable spots stationary.
For example, I want to move Activia Boulanger to spot 5. The grey cells should be the immoveable cells.
The beginning view:
What the UITableView does automatically:
What I want UITableView to do:
Setting tableView:canMoveRowAtIndexPath: seems to just prevent you from being able to move a cell, but does not prevent the cell from moving in reaction to other cells' movements.
Any help would be greatly appreciated.
Thanks
UPDATE:
Below is some sample code with a setup for the problem. I have not included my efforts at a solution because they have all failed and would clutter things up.
#import "LDYViewController.h"
static NSString * unmoveableCellId = #"NoMove";
static NSString * moveableCellId = #"OkMove";
#implementation LDYViewController
#synthesize tableView;
#synthesize peopleList;
- (void)viewDidLoad
{
[super viewDidLoad];
peopleList = [[NSMutableArray alloc] initWithObjects:
#"Belinda Boomer", #"Activia Boulanger", #"Arnold Carter", [NSNull null], #"Attila Creighton", [NSNull null], #"Bruce Cleary", [NSNull null], nil];
[tableView setEditing:YES];
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return peopleList.count;
}
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
if([peopleList objectAtIndex:indexPath.row] == [NSNull null]) {
cell = [tableView dequeueReusableCellWithIdentifier:unmoveableCellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:unmoveableCellId];
cell.userInteractionEnabled = NO;
cell.contentView.backgroundColor = [UIColor grayColor];
}
} else {
cell = [tableView dequeueReusableCellWithIdentifier:moveableCellId];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:moveableCellId];
NSString * name = [peopleList objectAtIndex:indexPath.row];
cell.textLabel.text = name;
}
}
return cell;
}
- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
}
- (NSIndexPath *)tableView:(UITableView *)tableView
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
return proposedDestinationIndexPath;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
if([peopleList objectAtIndex:indexPath.row] == [NSNull null]) {
return NO;
}
return YES;
}
#end
Try this:
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath*)sourceIndexPath
toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
You can check the proposedDestinationIndexPath, if you don't want to move row to it, you can return the sourceIndexPath then row will be moved back, otherwise return the proposedDestinationIndexPath.
Do the normal rearrange logic on your model, then when it's done, put the nulls back in where you want them. Posted code doesn't include the model, so here's a plausible model to illustrate:
// always leave our array with a null at indexes 3,5,7
// i'm sure you have better logic about where nulls go, but just to illustrate
- (void)addNulls {
NSMutableArray *answer = [NSMutableArray array];
for (id object in self.peopleList) {
if (![object isKindOfClass:[NSNull self]]) {
[answer addObject:object];
}
}
assert(answer.count >= 4);
[answer insertObject:[NSNull null] atIndex:3];
[answer insertObject:[NSNull null] atIndex:5];
[answer insertObject:[NSNull null] atIndex:7];
self.peopleList = answer;
}
// build a pretend model with nulls
- (NSMutableArray *)peopleList {
if (!_peopleList) {
_peopleList = [NSMutableArray array];
[_peopleList addObject:#"Moe"];
[_peopleList addObject:#"Larry"];
[_peopleList addObject:#"Curly"];
[_peopleList addObject:[NSNull null]];
[_peopleList addObject:#"Groucho"];
[_peopleList addObject:[NSNull null]];
[_peopleList addObject:#"Chico"];
[_peopleList addObject:[NSNull null]];
[_peopleList addObject:#"Harpo"];
}
return _peopleList;
}
// normal rearrange logic, then fix your array up
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
// reorder the list with the typical logic, ignoring nulls
NSString *stringToMove = [self.peopleList objectAtIndex:fromIndexPath.row];
[self.peopleList removeObjectAtIndex:fromIndexPath.row];
[self.peopleList insertObject:stringToMove atIndex:toIndexPath.row];
// now put nulls into the positions you want them
[self addNulls];
[self.tableView reloadData];
}
I faced similar problem and solved it.
create 2 section and put all gray color rows in section 2.
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{
if (proposedDestinationIndexPath.section == 1)
return sourceIndexPath;
else
return proposedDestinationIndexPath;
}
You can do this by using :
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath{
In this method you need to check the from indexIndexPath and toIndexPath to check if the user is moving to an invalid position. The modify the tableview's datasource to either put the cell back or move it to the correct position.
Swift Implementation
class TableViewMovable: UITableView, UITableViewDelegate, UITableViewDataSource {
var arrDataSource = [[String:Int]]()
override func awakeFromNib() {
super.awakeFromNib()
commonInit()
}
func commonInit(){
dataSource = self
delegate = self
isEditing = true
register(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrDataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cell") {
cell.textLabel?.text = arrDataSource[indexPath.row].keys.first!
let val = arrDataSource[indexPath.row].values.first!
cell.backgroundColor = val % 2 == 0 ? UIColor.gray.withAlphaComponent(0.5) : UIColor.lightGray.withAlphaComponent(0.5)
return cell
}else{
return UITableViewCell()
}
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .none
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let movedObject = arrDataSource[sourceIndexPath.row]
arrDataSource.remove(at: sourceIndexPath.row)
arrDataSource.insert(movedObject, at: destinationIndexPath.row)
debugPrint("\(sourceIndexPath.row) => \(destinationIndexPath.row)")
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
}
Hope this might help someone.

Renaming the "Delete" button in edit mode of tableviewcontroller

Can we rename the "Delete" button when put a table view in edit mode to something else?
The UITableView delegate just has to implement:
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
Implement
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
And return your custom title for delete.
From UITableViewDelegate docs
In Swift:
override func tableView(tableView: UITableView, titleForDeleteConfirmationButtonForRowAtIndexPath indexPath: NSIndexPath) -> String? {
return "Remove"
}
Code:
*- (NSString *)tableView:(UITableView *)tableView
titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return #"Rename"; // or put something else
}*

iPhone - How add a final line in a UITableView to add items, preventing rearranging of this line

I have a UITableView put in edited mode.
self.tableView.editing = YES;
In this table view, I have some lines displayed in a custom cell, and I'd like to add one at the end that would allow the user to add an item (using another view).
So I wrote some lines :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return "number of lines" + 1;
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row+1 != [tableView numberOfRowsInSection:0]) {
return UITableViewCellEditingStyleDelete;
}
else {
return UITableViewCellEditingStyleInsert;
}
}
- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row + 1 == [tableView numberOfRowsInSection:0]) {
cell.textLabel.text = #"Add a line...";
}
else {
do the stuff in the custom cell
}
}
Doing this way, the UITableView allows to rearrange any line. I can move the first line after the "add line", and move the "add line" in first position.
How may I remove the arrange button on the "add line" cell and prevent other lines to go under this one ?
Or is there a better way to code this ?
Implement
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return ([indexPath row] != INDEX_OF_SPECIAL_ROW)
}
and
- (NSIndexPath *)tableView:(UITableView *)tableView
targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
if ([proposedDestinationIndexPath row] < NUMBER_OF_ROWS)
{
return proposedDestinationIndexPath;
}
NSIndexPath *otherPath = [NSIndexPath indexPathForRow:NUMBER_OF_ROWS-1 inSection:0];
return otherPath;
}
The much easier way would be to set a tableFooterView. You can place any UIView in there, so not only are you allowed to add a UITableViewCell but also a completely custom subclass. Doing it this way you will avoid all the unnecessary checks.
return UITableViewCellEditingStyleNone
For that row in - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
And check out – tableView:moveRowAtIndexPath:toIndexPath:

iPhone UITableView with Multiple Sections

Apologies if this is a simple question but googling hasn't been able to help me.
I am planning to display 3 arrays of data in a Table View that has each array in a different section in the Table View.
Can any one provide me with a link to a good tutorial or sample code that could help me with this?
Once again I apologize if this is a simple question and answer but I am a newbie to Xcode and working on my first serious project for it.
Thanks!
In your TableViewController implement:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[self getDataArray:section]count];//implement getDataArray
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
NSObject *data = [[self getDataArray:indexPath.section]objectAt:indexPath.row];//implement getDataArray
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
//add Code to populate cell with data
}
return cell;
}
Other methods to probably implement:
- (UIView *)tableView: (UITableView *)tableView viewForHeaderInSection: (NSInteger)section
- (CGFloat)tableView:(UITableView *)aTableView heightForHeaderInSection:(NSInteger)section