切换式按钮:在这种情况下如何切换标题?

时间:2011-09-01 15:56:11

标签: objective-c cocoa core-data button

我有一个CoreData应用程序使用TableView,textfields,按钮显示数据......它处理人们的情况,其中一个按钮是一个标题为“关闭”的切换式按钮。当我们考虑用户的案例关闭时,我们按下它并使用对属性值的简单绑定来更改实体中布尔类型属性的状态,表示案例的关闭/打开状态。按钮标题也会变为“重新打开”,因为将来可能会重新打开。

然后在按下按钮时必须对数据进行其他操作,因此我必须创建一个IBAction方法,而不是简单地使用前一个绑定。问题:按下按钮时,操作完成,但按钮标题未切换。这是有道理的,因为没有任何东西告诉它再切换。

我决定从IBAction中移除对布尔值的操作并再次使用值绑定,因此布尔更改由绑定执行,其他操作由IBAction执行。问题:它意外地修改了数据,有时工作正常,有时没有像预期的那样以连贯的方式完成所有事情。

所以我回来了IBAction处理的所有更改,这次,我使用Title / Alternate标题绑定而不是值绑定。现在按钮标题切换,但不显示“关闭”和“重新打开”字样,而是显示布尔值“0”和“1”。

我也许应该使用“setTitle”来处理IBAction中的按钮标题更改,但后来我发现了一个新问题。在app启动时,它将如何选择适当的实体记录以供参考?如果桌子处于“无选择”状态怎么办?看起来像是一个非常广泛的代码来处理这么小的问题......

欢迎任何有关处理此问题的简短直接方式的建议。感谢。

1 个答案:

答案 0 :(得分:0)

听起来你可能有几个不同的选择。

这个第一个选项比其他选项更复杂,但是对于记录来说仍然很有用。此选项基本上不会对关闭/重新打开按钮使用绑定,而是以编程方式设置标题等。基本的游戏计划如下:

  • 文档打开时关闭/重新打开按钮的初始标题是在nib文件中设置的(例如Close)。

  • 或者,当文档打开时,您可以禁用-awakeFromNib中的按钮,因为表格视图没有初始选择。

  • 需要更改按钮标题或启用状态的唯一操作是1)当更改tableview的选择时,以及2)当您单击关闭/重新打开按钮以切换案例时状态。

要获得所需的结果,如果您还没有,请在关闭/重新打开按钮上创建IBOutlet。然后,您将tableview的delegate插座连接到控制器类,这将让您的控制器类知道何时更改了tableview的选择(通过- (void)tableViewSelectionDidChange:(NSNotification *)notification <NSTableViewDelegate>协议方法)。您还需要更新关闭/重新打开IBAction方法,以确保在单击后切换按钮上的标题(因为在该操作期间,tableview选择不会更改)。控制器类的代码可能如下所示:

// add this declaration to avoid compiler warnings:
@interface LHController (LHPrivate)
- (void)updateCloseReopenButtonTitle;
@end

- (void)awakeFromNib {
   [self updateCloseReopenButtonTitle];
}

- (void)tableViewSelectionDidChange:(NSNotification *)notification {
   [self updateCloseReopenButtonTitle];
}

- (IBAction)toggleCloseReopenButton:(id)sender {
    // do your existing code here and then add:
   [self updateCloseReopenButtonTitle];
}

- (void)updateCloseReopenButtonTitle {
    // assuming 'casesController' is an IBOutlet to your NSArrayController
    NSArray *selectedObjects = [casesController selectedObjects];
    // loop through the selected cases to determine whether
    // they're all closed, all open, or mixed to set
    // the title of the button appropriately
    BOOL allClosed = YES;
    for (LHCase *case in selectedCases) {
        if ([case isOpen]) {
           allClosed = NO;
           break;
        }
    }
    [closeReopenButton setTitle:(allClosed ? @"Reopen" : @"Close")];
    [closeReopenButton setEnabled:[selectedObjects count] > 0];
}

在绑定出现之前,这就是我们过去常常做的事情。

另一种选择可能是重新考虑您的用户界面:也许您需要切换其标题的推/切按钮,而不是只有一个标题为Closed的复选框,这将表示所选案例是否已关闭或不。您可以对复选框的状态使用绑定,如下图所示:

enter image description here

然后,您可以使用IBAction方法处理需要处理的额外内容。您可以向casesController询问-selectedObjects,然后循环浏览它们。只要您确定复选框Allows Mixed状态,就可以选择具有混合打开/关闭状态的复杂情况(复选框是破折号而不是完整状态),可以更好地表示混合情况。检查)。

如果您想坚持使用切换按钮,另一个选项是为标题和备用标题绑定创建并指定custom NSValueTransformer。该值变换器将采用案例的布尔闭合/打开状态,并将其转换为比0或1更合适的字符串(这就是现在显示的内容)。它可能看起来像这样:

+ (Class)transformedValueClass {
    return [NSString class];
}

+ (BOOL)allowsReverseTransformation {
    return NO;
}

- (id)transformedValue:(id)value {
    BOOL isClosed;

    if (value == nil) return nil;

    // Attempt to get a reasonable value from the
    // value object.
    if ([value respondsToSelector: @selector(boolValue)]) {
        isClosed = [value boolValue];
    } else {
        [NSException raise: NSInternalInconsistencyException
                    format: @"Value (%@) does not respond to -boolValue.",
        [value class]];
    }
    return (isClosed ? @"Reopen" : @"Close");
}