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];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With