因此,我想知道表视图单元格如何与其表视图通讯。例如,单元格如何通知表视图它的删除按钮已被点击,并需要从表视图中移除?
有几种可能的方案,但我不确定苹果公司使用的是哪种方案,因为UITableView或UITableViewCell的头文件没有揭示这一点(或者我漏看了什么)。
最终目标是让单元格和网格视图进行私有通信,也就是说,不公开任何公共方法或协议(如果可能的话)。
现在删除按钮可能是一个不好的例子,因为iOS有一个内置的方法,允许您删除行并通知您的数据源,该方法称为:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
然而,为了理解,如果您想在表视图单元格中添加一个按钮,并执行不在标准iOS库中的操作,则可以在单元格中创建一个委托,并将您的tableview的数据源文件设置为委托。
基本上,您可以像这样子类化UITableViewCell
MyCustomCell.h
@protocol MyCustomCellDelegate;
@interface MyCustomCell : UITableViewCell
@property (nonatomic, unsafe_unretained) id <MyCustomCellDelegate> delegate; //Holds a reference to our tableView class so we can call to it.
@property (nonatomic, retain) NSIndexPath *indexPath; //Holds the indexPath of the cell so we know what cell had their delete button pressed
@end
/* Every class that has <MyCustomCellDelegate> in their .h must have these methods in them */
@protocol MyCustomCellDelegate <NSObject>
- (void)didTapDeleteButton:(MyCustomCell *)cell;
@end
MyCustomCell.m
@synthesize delegate = _delegate;
@synthesize indexPath = _indexPath;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
/* Create a button and make it call to a method in THIS class called deleteButtonTapped */
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(5, 5, 25, 25);
[button addTarget:self action:@selector(deleteButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
/**
* This is the method that is called when the button is clicked.
* All it does is call to the delegate. (Whatever class we assigned to the 'delegate' property)
*/
- (void)deleteButtonTapped:(id)sender
{
[self.delegate didTapDeleteButton:self];
}
MyDataSource.h
/* We conform to the delegate. Which basically means "Hey you know those methods that we defined in that @protocol I've got them and you can safely call to them" */
@interface MyDataSource : UIViewController <MyCustomCellDelegate, UITableViewDelegate, UITableViewDataSource>
@property (nonatomic,retain) NSArray *tableData;//We will pretend this is the table data
@property (nonatomic,retain) UITableView *tableView;// We will pretend this is the tableview
@end
MyDataSource.m
//We will pretend we synthesized and initialized the properties
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier: @"MyCustomCell"];
if (!cell)
cell = [[DownloadQueueCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: @"MyCustomCell"];
cell.delegate = self; // Make sure we set the cell delegate property to this file so that it calls to this file when the button is pressed.
cell.indexPath = indexPath;// Set the indexPath for later use so we know what row had it's button pressed.
return cell;
}
- (void)didTapDeleteButton:(MyCustomCell *)cell;
{
// From here we would likely call to the apple API to Delete a row cleanly and animated
// However, since this example is ignoring the fact that they exist
// We will remove the object from the tableData array and reload the data
[self.tableData removeObjectAtIndexPath:cell.indexPath];
[self.tableView reloadData];
}
UITableViewCell
项是 UITableView
的子视图。因此,您可以使用它来在单元格和 tableView 之间进行通信。反过来,UITableView
具有委托和数据源与其控制器进行通信。这可能会有所帮助。
[[(UITableView *)self.superview delegate] performSelector:@selector(someButtonPressedInCell:) withObject:self]
。 - voromax我不确定是否需要一个私人通信渠道。
表视图通过调整表视图单元格的大小并在空白处创建一个新视图,使删除视图与给定单元格相邻。
强制执行的删除视图是使用表视图、索引路径和表视图委托实例化的。删除视图处理触摸并向表视图委托发送消息,包括表视图和索引路径。表视图委托完成从数据源中删除条目的工作,动画地移除单元格并刷新表视图。刷新后,表视图根据数据源重新绘制所有可见单元格。
您可以让自定义的单元格 UIView 拥有一个类型为您的网格视图的私有属性。当您将这些单元格添加到您的网格视图中时,更新该属性以指向网格视图。
我有自己的自定义网格视图,并且是通过这种方式实现的。
另一种方法是在您的网格视图中拥有一个处理单元格并返回其索引的方法,UITableView 也有这些方法。这样,当用户按下单元格中的按钮时,您只需要获取该单元格并将其传递给网格视图,获取该单元格的索引,然后使用该索引来访问数据...
您可以使用类别。
您可以在单独的类别中声明私有方法,并将其放置在单独的文件中。在想要使用这些私有方法的类的实现文件中,您需要导入带有私有类别的此文件,并使用私有方法。因此,使用它们的类的公共.h文件保持不变。
例如:
MyGridViewCell.h:
@interface MyGridViewCell : UIView
// ...
@end
MyGridViewCell.m:
@implementation MyGridViewCell : UIView
// ...
@end
现在是私有方法类别接口:
MyGridViewCellPrivate.h:
@interface MyGridViewCell (Private)
- (void) privateMethod1;
@end
实现:
MyGridViewCellPrivate.m:
@implementation MyGridViewCell (Private)
- (void) privateMethod1
{
// ...
}
@end
标题与之前相同:
MyGridView.h:
@interface MyGridView : UIView
- (void) publicMethod1;
@end
但实现可能会使用私有 API:
MyGridView.m:
#import "MyGridViewCell.h"
#import "MyGridViewCellPrivate.h"
- (void) publicMethod1
{
// Use privateMethod1
}