iOS返回不同的子类

时间:2014-04-06 00:08:40

标签: ios objective-c uicollectionviewcell subclassing

我对以下代码有疑问:

 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的超类)我无法连接它? enter image description here

修改 找到了找到父(抽象)子类的出口的方法:

enter image description here

修改 使用父子类实现解决方案:

- (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;
}

4 个答案:

答案 0 :(得分:4)

问题很简单,编译器只知道cellUICollectionViewCell *,而且该类型没有属性x。因此,您需要为编译器提供所需的信息。一种方法是从包含属性x的某个常见超类派生您的单元格类型,然后将该类型用于cell ivar。一种更简单的方法是声明具有该属性的协议,并在您的单元格类型中采用该协议。然后,您可以简单地将单元格指定为采用该协议的标准单元格,如下所示:

 UICollectionViewCell<MyProperty> *cell;

答案 1 :(得分:3)

您将单元格声明为UICollectionViewCell,但没有x property。您还将单元格的实例强制转换为自定义类,但仍将单元格变量声明为UICollectionViewCell。相反,您可以为TaskCollectionCellPeopleCollectionCell创建一个超类,它声明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}}的抽象子类。然后,您的xTaskCollectionCell可以继承此类。然后,您将声明PeopleCollectionCell属于此类类。

答案 3 :(得分:-1)

如果您在类cell的{​​{1}}上创建了一个实例,但是当您执行UICollectionViewCell时仍然会收到错误,那么它可能是对象的类{{1} }}没有cell.x字段,或者无法从该范围访问。

我在子类上声明了字段但仍然不起作用,为什么?

假设您有一个名为cell的基类,然后是一个名为x的子类。

如果声明类型为Person的变量并在其上存储Children对象,则无法访问Person未在{{1}上声明的字段}。这是对象范式的原则。