使用自定义单元格编辑UITableView _without_时更改单元格外观?

时间:2010-12-06 21:49:18

标签: iphone uitableview ios4

如果我使用的是自定义UITableViewCell,我可以使用以下方法在转换状态时更改单元格的外观:

- (void)willTransitionToState:(UITableViewCellStateMask)state
- (void)didTransitionToState:(UITableViewCellStateMask)state

如果我没有使用自定义的tableview单元格,有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:3)

编辑:请参阅Daniel Hanly的评论。可以使用#import选择性地应用类别。我向任何可能被这个答案误导的人道歉。相关部分将被编辑以供将来参考。

好的,尝试排名第二。 据我所知,没有其他记录的方法可以实现您需要的功能而无需子类化UITableViewCell。值得注意的是,Apple的UITableViewCell文档特别提到状态转换方法是要实现的通过子类。话虽如此,如果绝对需要在没有子类的情况下实现它们,那么有一些不那么传统的解决方案。每个都有自己的问题,最终可能无法实现它们,但这仍然是一个有趣的问题。

声明

如果您只想要一个理智且相对简单的解释,那么请将您的问题的答案视为“不,没有办法做您想做的事。”我只提出以下选项断言他们会工作。我绝不赞同实际使用它们。考虑一下我的忏悔,为我的第一个答案提供如此明显的缺陷。

选项一 - 类别

通过覆盖自定义UITableViewCell类别中列出的方法,可以获得您正在寻找的功能。

问题是这种方法在99%的情况下都是一个非常糟糕的主意。在UITableViewCell上定义类别后,将为整个应用程序中的所有 UITableViewCell对象定义这些方法。除非你想为应用程序中的每个表格单元格提供完全相同的状态转换功能,否则这种方法不是很有帮助。

选项二 - 运行时魔术

您可以使用低级Objective-C运行时函数来动态更改任何方法的实现。与类别选项不同,此方法足够灵活,可以在您需要时重新定义预期的行为,而不是一次性交易。

例如,如果您尝试从UITableViewController管理状态转换,则可以执行以下操作:

CustomTableViewController.m

#import <objc/runtime.h>

- (void) customStateWillChange:(UITableViewCellStateMask)state
{
    //custom UITableViewCell code
}

- (void) viewDidAppear:(BOOL)animated
{
    //Store the original implementation
    Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], @selector(willTransitionToState:));
    originalStateWillChangeImplementation = method_getImplementation(originalStateWillChangeMethod); //variable declared in header file as type IMP

    //Get the new implementation
    Method newStateWillChangeMethod = class_getInstanceMethod([self class], @selector(customStateWillChange:));
    IMP newStateWillChangeImplementation = method_getImplementation(newStateWillChangeMethod);

    //Replace implementation
    method_setImplementation(originalStateWillChangeMethod, newStateWillChangeImplementation);

    //the rest of your viewDidAppear code
    [super viewDidAppear:animated];
}

- (void) viewDidDisappear:(BOOL)animated
{
    //restore the original implementation
    Method originalStateWillChangeMethod = class_getInstanceMethod([UITableViewCell class], @selector(willTransitionToState:));
    method_setImplementation(originalStateWillChangeMethod, originalStateWillChangeImplementation);

    //rest of viewDidDisappear code
    [super viewDidDisappear:animated];
}

此代码可能不符合您的确切用途,但我认为它提供了一个有用的示例。

这非常难看,因为这里定义的customStateWillChange:方法只是作为UITableViewCell类的一部分运行,但在这个例子中,它将被编译为好像它是CustomTableController类的一部分。在其他烦恼中,您必须避开属性点表示法,忽略编译器警告并放弃该方法主体的大部分(如果不是全部)编译时检查。

选项3 - 具有运行时魔法的类别

究竟是什么声音。在UITableViewCell上的类别(或多个类别)中定义您喜欢的任何自定义状态更改方法。确保每个名称都有一个单独的名称 - 添加两个类别,每个类别具有相同名称的方法将导致未定义的行为。此外,每个人都需要具有与要替换的方法相同的返回类型和参数类型。

然后,上面代码中对[self class]的引用将替换为[UITableViewCell类],customStateWillChange:方法将被移动到自定义类别。虽然仍然很难看,但至少可以依靠编译器来正确解释方法体。

当然,弄乱运行时会增加很多复杂性来跟踪。它可以很好地工作,但它不是很好的设计,它需要认真努力才能确保它安全正确地工作,这可能会给任何维护它的人带来痛苦和绝望。

参考

The Objective-C Programming Language - Categories and Extensions
Objective-C Runtime Reference

答案 1 :(得分:0)

绝对。 UITableViewDelegate协议指定了许多方法来管理表视图单元的状态转换。请查看UITableViewDelegate Class Reference,特别是“编辑表行”标题下列出的方法。

修改

对不起,你是对的。 UITableViewDelegate方法不响应对单元属性的直接更改。我找到了一种方法可行,但我会用不同的答案来避免混淆。