ReactiveCocoa:如何将按钮的标题绑定到文本属性?

时间:2022-06-01 18:00:43

I've got a UIButton whose title for state normal/highlighted should keep synced with a property of its container object.

我有一个UIButton,其状态正常/突出显示的标题应该与其容器对象的属性保持同步。

How can I bind button title for specific state with a string property?

如何使用字符串属性绑定特定状态的按钮标题?

Edit:

I know that using RACObserve and change the button title in subcribeNext block is a solution.
I'm looking for something more specifically designed for UIButton like:

我知道使用RACObserve并更改subcribeNext块中的按钮标题是一种解决方案。我正在寻找更专门为UIButton设计的东西,如:

RACBindButtonTitle(button, property, state1, state2);

I don't know if there is some "RAC sugar" like this.

我不知道是否有这样的“RAC糖”。

3 个解决方案

#1


If you mean they're synced with one property, something like this:

如果你的意思是他们与一个属性同步,这样的事情:

[RACAble(self.buttonTitle) subscribeNext:^(NSString *newTitle) {
    NSString *normalTitle = [NSString stringWithFormat:@"Normal %@", newTitle];
    NSString *highlightedTitle = [NSString stringWithFormat:@"Highlighted %@", newTitle];
    [self.button setTitle:normalTitle forState:UIControlStateNormal];
    [self.button setTitle:highlightedTitle forState:UIControlStateHighlighted];
}];

If you mean there're two properties, something like this:

如果你的意思是有两个属性,就像这样:

[RACAble(self.normalButtonTitle) subscribeNext:^(NSString *newTitle) {
    [self.button setTitle:newTitle forState:UIControlStateNormal];
}];

[RACAble(self.highlightedButtonTitle) subscribeNext:^(NSString *newTitle) {
    [self.button setTitle:newTitle forState:UIControlStateHighlighted];
}];

#2


Here's a way to do it without explicit subscription. Explicit subscription should be avoided whenever possible so that you don't have to go through the whole @weakify(self) @strongify(self) dance.

这是一种没有明确订阅的方法。应尽可能避免明确订阅,这样您就不必经历整个@weakify(自我)@strongify(自我)舞蹈。

[self.button rac_liftSelector:@selector(setTitle:forState:)
                withSignals:
                            RACObserve(self, normalButtonTitle),
                            [RACSignal return:@(UIControlStateNormal)],
                            nil];
[self.button rac_liftSelector:@selector(setTitle:forState:)
                withSignals:
                            RACObserve(self, selectedButtonTitle),
                            [RACSignal return:@(UIControlStateSelected)],
                            nil];

liftSelector:withSignals: will subscribe eagerly to its signals, unlike many another RAC functions.

liftSelector:withSignals:与许多其他RAC功能不同,将热切地订阅其信号。

#3


Please refer to this gist.

请参考这个要点。

You can't use RAC() directly on a UIButton because of the UIKit design:

由于UIKit设计,您不能直接在UIButton上使用RAC():

RAC(self.button.titleLabel, text) = titleSignal;  // Don't do this.

One of the solutions is using dynamic property to support RAC() binding macro:

其中一个解决方案是使用动态属性来支持RAC()绑定宏:

// .h
@interface UIButton (RACTitleSupport)
@property (strong, nonatomic) NSString *racExt_Title;
@end

// .m
@implementation UIButton (RACTitleSupport)
@dynamic racExt_Title;
- (void)setRacExt_Title:(NSString *)racExt_Title
{
  [self setTitle:racExt_Title forState:UIControlStateNormal];
}
- (NSString *)racExt_Title
{
  return [self titleForState:UIControlStateNormal];
}
@end

Now you can use RAC() binding macro like this:

现在您可以像这样使用RAC()绑定宏:

RAC(self, button.racExt_Title) = titleSignal;

Cheers <3

#1


If you mean they're synced with one property, something like this:

如果你的意思是他们与一个属性同步,这样的事情:

[RACAble(self.buttonTitle) subscribeNext:^(NSString *newTitle) {
    NSString *normalTitle = [NSString stringWithFormat:@"Normal %@", newTitle];
    NSString *highlightedTitle = [NSString stringWithFormat:@"Highlighted %@", newTitle];
    [self.button setTitle:normalTitle forState:UIControlStateNormal];
    [self.button setTitle:highlightedTitle forState:UIControlStateHighlighted];
}];

If you mean there're two properties, something like this:

如果你的意思是有两个属性,就像这样:

[RACAble(self.normalButtonTitle) subscribeNext:^(NSString *newTitle) {
    [self.button setTitle:newTitle forState:UIControlStateNormal];
}];

[RACAble(self.highlightedButtonTitle) subscribeNext:^(NSString *newTitle) {
    [self.button setTitle:newTitle forState:UIControlStateHighlighted];
}];

#2


Here's a way to do it without explicit subscription. Explicit subscription should be avoided whenever possible so that you don't have to go through the whole @weakify(self) @strongify(self) dance.

这是一种没有明确订阅的方法。应尽可能避免明确订阅,这样您就不必经历整个@weakify(自我)@strongify(自我)舞蹈。

[self.button rac_liftSelector:@selector(setTitle:forState:)
                withSignals:
                            RACObserve(self, normalButtonTitle),
                            [RACSignal return:@(UIControlStateNormal)],
                            nil];
[self.button rac_liftSelector:@selector(setTitle:forState:)
                withSignals:
                            RACObserve(self, selectedButtonTitle),
                            [RACSignal return:@(UIControlStateSelected)],
                            nil];

liftSelector:withSignals: will subscribe eagerly to its signals, unlike many another RAC functions.

liftSelector:withSignals:与许多其他RAC功能不同,将热切地订阅其信号。

#3


Please refer to this gist.

请参考这个要点。

You can't use RAC() directly on a UIButton because of the UIKit design:

由于UIKit设计,您不能直接在UIButton上使用RAC():

RAC(self.button.titleLabel, text) = titleSignal;  // Don't do this.

One of the solutions is using dynamic property to support RAC() binding macro:

其中一个解决方案是使用动态属性来支持RAC()绑定宏:

// .h
@interface UIButton (RACTitleSupport)
@property (strong, nonatomic) NSString *racExt_Title;
@end

// .m
@implementation UIButton (RACTitleSupport)
@dynamic racExt_Title;
- (void)setRacExt_Title:(NSString *)racExt_Title
{
  [self setTitle:racExt_Title forState:UIControlStateNormal];
}
- (NSString *)racExt_Title
{
  return [self titleForState:UIControlStateNormal];
}
@end

Now you can use RAC() binding macro like this:

现在您可以像这样使用RAC()绑定宏:

RAC(self, button.racExt_Title) = titleSignal;

Cheers <3