Jake Jake - 4 months ago 15
Objective-C Question

Possible implementations of editable UITableView data sources

I'm seeking to implement a UITableView that has sections representing the recent history and future queue of a media player. It seems to me that a Queue-type structure would be most applicable for this, as this represents the nature of the operation, but the requirement that the future queue part be editable poses some challenges.

I think that a linked list would be the best option here to store the media representations, as opposed to a vector type structure where all of the elements are stored contiguously. It seems to me that, in the case of moving or removing an object within the queue and adding object at the end, a linked list is more efficient than a vector, as simply assigning a few pointers different values seems more lightweight than moving entire chunks of memory. The internal implementation details of

NSMutableArray
seem quite obscure but I'm assuming it's a vector type.

However, I've never really seen a true linked-list implementation in Objective-C. Furthermore, the structure of
UITableViewDataSource
, requiring
cellForRowAtIndexPath:
to be called with a specific row rather than simply iterating through the list, exposes the weakness of linked list implementations, as seeking a specific index can be expensive. This would be irrelevant if
cellForRowAtIndexPath:
is only called in order, but it seems reckless to ignore the
indexPath
parameter in favor of just iterating through the list.

How are these structures typically implemented? Is iterating through a link list as proposed a bad idea?

Answer

Since Objective-C doesn't have an explicitly defined "linked list" object type, the closest alternative would be NSMutableArray.

You should never assume the order in which

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath;

will be called, and if you implement the UITableView correctly, it should only be called for the index paths of cells right before they appear on screen (thus the order it's called would alter based on the direction the user is scrolling in).

I recommend that you create a 2-dimensional NSMutableArray with the 1st representing the sections in the table and the 2nd representing the rows in each section. You would then initialize the array using something like:

self.sectionsArray = [NSMutableArray array];
[self.sectionsArray addObject:[NSMutableArray array]]; // history rows
[self.sectionsArray addObject:[NSMutableArray array]]; // queued rows

Which would allow you to easily retrieve the stored items using something along the lines of:

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    NSUInteger section = indexPath.section;
    NSUInteger row = indexPath.row;
    id fetchedObject = self.sectionsArray[section][row];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellReuseID"];
    // perform setup here based on the fetchedObject
    return cell;
}

I've listed some NSMutableArray methods you may find helpful below:

- (void)addObject:(ObjectType)anObject;
- (void)insertObject:(ObjectType)anObject atIndex:(NSUInteger)index;
- (void)removeObject:(ObjectType)anObject atIndex:(NSUInteger)index;
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(ObjectType)anObject;
- (void)removeLastObject;
Comments