如何在选择UITableViewCell后延迟关闭模态窗口

时间:2011-11-01 17:17:50

标签: iphone objective-c ios uitableview

我做了一些搜索,我希望我不会创建副本(毕竟是凌晨4点)。我也希望这对大师来说很容易回答,但我现在找不到它。

我有一个UITableView用于应用程序设置。当您选择其中一行时,它会添加复选标记附件。由于它是一个模态窗口,我将其设置为在您选择它时关闭窗口。但是,我当前的代码在您选择它时立即关闭窗口,您无法看到选择动画(以及随后出现的复选标记)。我的模态窗口代码基于AddMusic示例项目。

在执行关闭命令之前,有没有办法让表格行闪烁几次,以便明显选择哪一行?

作为参考,我的模态窗口是UIViewController <UITableViewDelegate>

我的选择行代码如下:

- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:self.selectedIndexPath];
    oldCell.accessoryType = UITableViewCellAccessoryNone;

    UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
    newCell.accessoryType = UITableViewCellAccessoryCheckmark;

    [self setSelectedIndexPath:indexPath];
    [tableView deselectRowAtIndexPath: indexPath animated: YES];

    // close the window when an option is selected.
    [self.delegate movieCinemaViewControllerDidFinish: self];
}

3 个答案:

答案 0 :(得分:3)

要延迟结束,请更改

[self.delegate movieCinemaViewControllerDidFinish: self];

为:

[self.delegate performSelector:@selector(movieCinemaViewControllerDidFinish:) withObject:self afterDelay:5];

要闪存,您可以使用类似的技术排队多个de/selectRowAtIndexPath:。在此过程中禁用用户交互可能也是明智之举。就个人而言,我认为闪烁单元格是不必要的 - 只需将退出延迟一小时就足以突出显示?


或者安排NSTimer在延迟后调用-(void)complete方法,并让该方法调用委托人的选择器。

答案 1 :(得分:2)

实际上,如果您的委托只有id,那么您不能指望performSelector:withObject:afterDelay方法,因为它是来自NSObject的NSDelayedPerforming类别的方法。鉴于此,问题是并非所有id必定都是NSObject个类(您id可能指向NSProxy个对象,该对象不会从NSObject继承,例如)

所以,你可以做的是使用一些GCD来实现延迟

double delayInSeconds = 0.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [self.delegate movieCinemaViewControllerDidFinish: self];
});

答案 2 :(得分:1)

我将使用其中的动画方法创建一个子类UITableViewCell来描述一个单元格选择。单元格将具有一个协议,该协议将在动画完成时通知委托,因此委托(在本例中为UIViewController)仅在单元格告知动画完成时才会关闭模式。

步骤1将在UITableViewCell的标头中创建一个委托协议,其方法类似于subclassedCellSelected:(NSIndexPath *)myIndexPath

步骤2将在您的单元格中声明一个ivar,它存储单元格的索引路径。将此ivar声明为属性(当然要合成它),以便当您的UIViewController在cellForRowAtIndexPath中创建单元格时,可以在单元格上设置indexPath ivar。这告诉单元格它是索引路径的位置,当它通知代表有关它的选择时会有用。

步骤3将实现实际的动画方法:

- (void)startPulse
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    [UIView setAnimationDuration:0.1];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(endPulse)];

    CGAffineTransform transform = CGAffineTransformMakeScale(0.9, 0.9);
    self.transform = transform;
    self.alpha = 0.5;

    [UIView commitAnimations];
}

- (void)endPulse
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
    [UIView setAnimationDuration:0.1];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(completeAction)];

    CGAffineTransform transform = CGAffineTransformMakeScale(1, 1);
    self.transform = transform;
    self.alpha = 1;

    [UIView commitAnimations];
}

- (void)completeAction
{
    if([self.delegate respondsToSelector:@selector(subclassedCellDelegate:)])
        [self.delegate subclassedCellSelected:self.indexPath];
}

在视图控制器的didSelectRowAtIndexPath方法中,您现在应该在单元格上调用startPulse方法。您可以按如下方式执行此操作:

CustomTableViewCell *myCell = (CustomTableViewCell*)[tableView cellForRowAtIndexPath:indexPath]

[myCell startPulse];

要传递的indexPath是从didSelectRowAtIndexPath回调中获得的索引。

现在将要发生的是,单元格将启动它的动画方法,一旦动画完成,将发布sublassedCellSelected的委托回调。

您的UIViewController应订阅自定义单元格的协议,并在您的类文件中实现委托回调方法,如下所示:

- (void)subclassedCellSelected(NSIndexPath*)cellIndexPath
{
    //dismiss the modal here
}

如果您在设置委托协议方面需要帮助,请在此处查看我的答案:dismissModalViewController AND pass data back

此代码最终会做的是显示一个简单的动画,其中我们的单元格在执行所需操作之前“反弹”进出。