This is kind of a long way to go to ask a simple question, but given how confusing pointers in Objective-C are for some, maybe verifying what's going on here will help others, as well as myself.
So, in a nutshell, I have a UITableView whereby 开发者_开发知识库you can enable editing and delete a row. I want to delete the row from the table view, and the data source(s). The original data source is in a model class, but I have a pointer/property containing the data in my local table view controller. When I delete a row from the table view via editing, it appears to work and delete the data...but I don't understand why. I think it's because of my fundamental misunderstanding of pointers.
In my model class with an NSMutableArray:
@property (nonatomic,retain) NSMutableArray *allAlarms;
// ... plist gets read and serialized to an array ...
allAlarms = [NSMutableArray arrayWithArray:[plistValues objectForKey:@"Alarms"]];
In a UITableViewController class, I pull that mutable array in via a property during viewWillAppear:
@property (nonatomic, retain) NSMutableArray *alarms;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// retrieve values from data controller
self.alarms = [dataController returnAllAlarms];
[self.tableView reloadData];
}
When the delegate method for editing is exercised, I do this, and it works...
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the local data source
[self.alarms removeObjectAtIndex:indexPath.row];
// The above line appears to delete it in the local pointer as well as in the original property in the model class
// so I just have to tell the data controller to save plist for when it's read back in via viewWillAppear
[dataController writePlist];
// Delete the row from the table view
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
Why does what is going on in my tableView:commitEditingStyle:forRowAtIndexPath ultimately work? Does removing an item from a pointer to an NSMutableArray in my local class also remove it in the original pointer in the remote class because the former is a pointer to the latter?
I need to understand because there are other operations I'll be performing on this local pointer and want to make sure I'm not being redundant in wanting to perform it on the remote property, etc. Is there anything about what I'm doing unintuitive and redundant, or will it make more sense as I continue to learn Objective-C & use pointers more?
Yes, it sounds like you don't quite understand how pointers work. Rather than trying to explain it all myself, I'll point you to this thorough chapter on pointers.
One thing to note is that in Objective-C, you never allocate objects on the stack1. Objects are always allocated on the heap, and a pointer returned to you. (like malloc()
.) This is why there is always an asterisk (*
) in the type of an object2. Both your model and controller have pointers to the same underlying array. self.alarms = [dataController allAlarms]
doesn't copy the array, it copies the pointer3.
When you call removeObjectAtIndex:
, it doesn't change anything about the pointer—a pointer is just a number—it dereferences the pointer and operates on the underlying object in memory.
1. With one minor exception, Blocks.
2. Excluding id
, which is typedef
'ed.
3. If you do want to copy the array, use the (copy)
property attribute rather than (retain)
.
精彩评论