UITableView在运行时切换到不同的CustomCell

时间:2014-05-10 16:02:00

标签: ios objective-c uitableview uiresponder

我有一个UITableView,有两个部分,第二部分在其标题中包含UISegmentedControl。我希望用户可以通过选择UISegmentedControl中的细分来更改tableview内容。我的TableView也通过呈现我使用NIB创建的不同自定义单元来更改单元格外观。我的一个要求是记住我的tableview中加载数据的表格视图的滚动位置,这样当用户点击我的段控件以更改tableview内容并再次点击前一个段时,我的tableview将能够呈现具有用户记住的滚动位置的数据。

代码:

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 2;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    if (section == kUserCoverSection) {
        return 0;
    }
    return 30;
}


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    if (section == kUserCoverSection) {
        return 1;
    }
    switch (self.userAchievementsType) {
        case kUserSilverCollections:
        {
            return [userSilverArray count];
        }
            break;
        case kUserBronzeCollections:
        {
            return [userBronzeArray count];
        }
            break;
        case kUserGoldsCollections:{
            return [userGoldsArray count];
        }
            break;

        default: return 0;
            break;
    }
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    if (indexPath.section == kUserCoverSection) {
        return 145;
    }else{
        switch (self.userAchievementsType) {
            case kUserSilverCollections:
            case kUserBronzeCollections:
            {
                return 40;
            }
                break;
            case kUserGoldsCollections:{
                return 358;
            }
                break;
            default:{
                return 40;
            }
                break;
        }
    }


}

-(UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section {
    if (section == kUserAchievementSection) {
        SegmentControlHeader *sectionHeaderView = [self.mTableView dequeueReusableHeaderFooterViewWithIdentifier:SegmentHeaderViewIdentifier];
        [sectionHeaderView setDelegate:self];
        [sectionHeaderView.segmentControl setSelectedSegmentIndex:self.userAchievementsType];
        return sectionHeaderView;
    }
    return nil;
}
-(UITableViewCell*)tableView:(UITableView*)aTableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
    switch (indexPath.section) {
        case kUserCoverSection:
        {
            static NSString* bannerCellType = @"kCoverBannerCellIdentifier";
            CoverBannerCell *cell = (CoverBannerCell*)[aTableView dequeueReusableCellWithIdentifier:bannerCellType];

            cell.tag = indexPath.row;
            if (cell == nil) {
                NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CoverBannerCell" owner:nil options:nil];
                cell = (CoverBannerCell*)[nib objectAtIndex:0];
            }

            return cell;
        }
        break;

        case kUserAchievementSection:
        {
            switch (self.userAchievementsType) {
                case kUserGoldsCollections:
                { 
                    static NSString* cellType = @"kUserGoldsViewCellIdentifier";
                    UserGoldsViewCell *cell = (UserGoldsViewCell*)[aTableView dequeueReusableCellWithIdentifier:cellType];
                    cell.tag = indexPath.row;
                    if (cell == nil) {
                        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"UserGoldsViewCell" owner:nil options:nil];
                        cell = (UserGoldsViewCell*)[nib objectAtIndex:0];
                    }

                    return cell;
                }
                    break;
                case kUserBronzeCollections:
                case kUserSilverCollections:{
                    static NSString* cellType = @"kUserSilverCellIdentifier";
                    UserSilverCell *cell = (UserSilverCell*)[aTableView dequeueReusableCellWithIdentifier:cellType];
                    cell.tag = indexPath.row;
                    if (cell == nil) {
                        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"UserSilverCell" owner:nil options:nil];
                        cell = (UserSilverCell*)[nib objectAtIndex:0];
                    }
                    return cell;
                }
                break;

                default: { 
                    return [self defaultCell];
                }
                break;
            }

        }
        break;

        default:
            return nil;
            break;
    }

}

-(void)didChangeSegmentValue:(UISegmentedControl *)segment{
    NSInteger index = segment.selectedSegmentIndex;
    NSInteger lastSelectedIndex = self.userAchievementsType;
    switch (lastSelectedIndex) {
        case kUserGoldsCollections: offsetsArray [kUserGoldsCollections] = @(mTableView.contentOffset.y);
            break;
        case kUserSilverCollections: offsetsArray [kUserSilverCollections] = @(mTableView.contentOffset.y);
            break;
        case kUserBronzeCollections: offsetsArray [kUserBronzeCollections] = @(mTableView.contentOffset.y);
            break;
        default:
            break;
    }
    //check if last table scroll header hit top
    if ([offsetsArray[lastSelectedIndex] floatValue] > 144) {
        for (int i = 0; i < [offsetsArray count]; i++) {
            if ([offsetsArray[i] floatValue] < 145 && offsetsArray[lastSelectedIndex] != offsetsArray[i]) {
                offsetsArray[i] = @(145);
            }
        }
    }else{
        for (int i = 0; i < [offsetsArray count]; i++) {
            if ([offsetsArray [i] floatValue] <= 145 && offsetsArray[lastSelectedIndex]!=offsetsArray[i]) {
                CGFloat newOffset;
                newOffset = [offsetsArray[i] floatValue] + ([offsetsArray[lastSelectedIndex] floatValue] -[offsetsArray[i] floatValue] );
                offsetsArray [i] = @(newOffset);
            }else{
                CGFloat newOffset = [offsetsArray[lastSelectedIndex] floatValue];
                offsetsArray [i] = @(newOffset);
            }

        }
    }
    NSRange range = NSMakeRange(1, 1);
    NSIndexSet *section = [NSIndexSet indexSetWithIndexesInRange:range];
    self.userAchievementsType = index;
    [self.mTableView beginUpdates];
    [self.mTableView reloadSections:section withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.mTableView endUpdates];
    [mTableView setContentOffset:CGPointMake(0, [offsetsArray[self.userAchievementsType] floatValue])];

}

我的TableView正确显示正确的数据和正确的滚动位置。 您会注意到我的代码kUserSilverCollectionskUserBronzeCollections显示相同的自定义单元格,并且具有相同的高度,但加载了不同的数据源。当用户选择kUserGoldsCollections时,我遇到此问题({{1比kUserGoldsCollections&amp; kUserSilverCollections类型更高的高度,并返回到kUserBronzeCollectionskUserSilverCollections类型,自定义单元格不再响应触摸,内部按钮细胞和细胞本身不识别触摸,也有最后几个细胞正在响应的情况。但其余的不是。

我在iOS 7.1 SDK中编写代码。请帮我找出导致这个问题的原因:) 谢谢!

修改

我发现导致问题的原因是,我kUserBronzeCollections现在感到愚蠢:D我的问题是缺乏像我的手机设置这样的细节。我应该在这个问题中包含我的单元格代码。我会将解决方案/细节作为未来读者的答案发布。

2 个答案:

答案 0 :(得分:1)

我不知道你为Nib使用这种方法的原因:

NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"UserSilverCell" owner:nil options:nil];
cell = (UserSilverCell*)[nib objectAtIndex:0];

使用它,可能是你的问题:

在你的viewDidLoad中只需注册你的笔尖以获取一个cellIdenfier:

[_yourTableView registerNib:[UINib nibWithNibName:@"UserSilverCell" 
                     bundle:[NSBundle mainBundle]] 
     forCellReuseIdentifier:@"kUserSilverCellIdentifier"];

然后在cellForRowAtIndexPath

UserSilverCell *cell = (UserSilverCell *)[tableView     
            dequeueReusableCellWithIdentifier:@"kUserSilverCellIdentifier" 
                                 forIndexPath:indexPath];

您还必须将其应用于您的其他类型的单元格。

这可能是问题所在,但如果不是以这种方式维持,因为Nib会更好。

答案 1 :(得分:1)

我找到了导致这个问题的原因。我的UserGoldsViewCell覆盖了hitTest:withEvent方法。下面是我对该方法的旧实现:

- (UIView *)hitTest:(CGPoint) point withEvent:(UIEvent *)event {
    if ([self pointInside:point withEvent:event]) {
        return scrollView;
    }

    return nil;
}

我覆盖了这种方法,因为我的UserGoldsViewCell中有UISrollView,而reason我需要覆盖它。我UserSilverCell选择UserGoldsViewCell后未对触摸事件做出响应的原因是因为即使呈现的单元格为UserSilverCell个实例,我hitTest:withEvent中的UserGoldsViewCell仍然存在被调用并返回其'scrollView。我改变了这个方法的实现,如下所示:

-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
    UIView* childObj = nil;
    if ((childObj = [super hitTest:point withEvent:event]) == self)
        return self.scrollView;     
    return childObj;
}