我对以下代码有疑问:
UICollectionViewCell *cell;
if (_peopleNotTasks == NO) {
static NSString *CellIdentifier = @"TaskCollectionCell";
cell = (TaskCollectionCell *)[cv dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
} else {
static NSString *CellIdentifier = @"PeopleCollectionCell";
cell = (PeopleCollectionCell *)[cv dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
}
//both cells have property x
//this does not work:
cell.x = @"this is an awesome string";
return cell;
为什么这不起作用?
TaskCollectionCell和PeopleCollectionCell都是UICollectionViewCell
的子类。
预期:
访问TaskCollectionCell和PeopleCollectionCell的属性。
如果我在抽象类中创建一个出口(现在是TaskCollectionCell和PeopleCollectionCell的超类)我无法连接它?
修改 找到了找到父(抽象)子类的出口的方法:
修改 使用父子类实现解决方案:
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ParentCell *cell;
if (_onlyUsersTasks == NO) {
static NSString *CellIdentifier = @"TaskCollectionCell";
cell = (TaskCollectionCell *)[cv dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
} else {
static NSString *CellIdentifier = @"PeopleCollectionCell";
cell = (PeopleCollectionCell *)[cv dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
}
cell.commonString = @"Thanks Jonathan";
return cell;
}
答案 0 :(得分:4)
问题很简单,编译器只知道cell
是UICollectionViewCell *
,而且该类型没有属性x
。因此,您需要为编译器提供所需的信息。一种方法是从包含属性x
的某个常见超类派生您的单元格类型,然后将该类型用于cell
ivar。一种更简单的方法是声明具有该属性的协议,并在您的单元格类型中采用该协议。然后,您可以简单地将单元格指定为采用该协议的标准单元格,如下所示:
UICollectionViewCell<MyProperty> *cell;
答案 1 :(得分:3)
您将单元格声明为UICollectionViewCell
,但没有x property
。您还将单元格的实例强制转换为自定义类,但仍将单元格变量声明为UICollectionViewCell
。相反,您可以为TaskCollectionCell
和PeopleCollectionCell
创建一个超类,它声明x property
。
E.g。
NSString * const PeopleCollectionCellIdentifier = @"PeopleCollectionCell";
NSString * const TaskCollectionCellIdentifier = @"TaskCollectionCell";
CustomSuperClass * cell = (self.arePeopleNotTasks) ? [cv dequeueReusableCellWithReuseIdentifier:PeopleCollectionCellIdentifier forIndexPath:indexPath] : [cv dequeueReusableCellWithReuseIdentifier:TaskCollectionCellIdentifier forIndexPath:indexPath];
cell.x = @"this is an awesome string";
if ([cell.reuseIdentifier isEqualToString:PeopleCollectionCellIdentifier])
{
PeopleCollectionCell * peopleCollectionCell = (PeopleCollectionCell *)cell;
peopleCollectionCell.peopleOnlyProperty = nil;
}
else if ([cell.reuseIdentifier isEqualToString:TaskCollectionCellIdentifier])
{
TaskCollectionCell * taskCollectionCell = (TaskCollectionCell *)cell;
taskCollectionCell.taskOnlyProperty = nil;
}
return cell;
答案 2 :(得分:3)
您已将cell
声明为UICollectionViewCell
,其中没有属性x
。面向对象的事情是创建一个声明属性UICollectionViewCell
的{{1}}的抽象子类。然后,您的x
和TaskCollectionCell
可以继承此类。然后,您将声明PeopleCollectionCell
属于此类类。
答案 3 :(得分:-1)
如果您在类cell
的{{1}}上创建了一个实例,但是当您执行UICollectionViewCell
时仍然会收到错误,那么它可能是对象的类{{1} }}没有cell.x
字段,或者无法从该范围访问。
我在子类上声明了字段但仍然不起作用,为什么?
假设您有一个名为cell
的基类,然后是一个名为x
的子类。
如果声明类型为Person
的变量并在其上存储Children
对象,则无法访问Person
未在{{1}上声明的字段}。这是对象范式的原则。