1

我正在使用 QuickDialog 和 Reactive Cocoa 构建一个相当长的表单,我希望能够编写一个工厂方法来从同一个表单设置我的 QElements。

这是我现在如何做的例子。

self.root = [[QRootElement alloc] init];
self.root.title = self.title;
self.root.grouped = YES;

self.basic = [[QSection alloc] init];
self.basic.title = @"Basic Information";
[self.root addSection:self.basic];

QEntryElement *address = [[QEntryElement alloc] init];
address.title = @"Address";
RAC(address, textValue) = [RACObserve(self, viewModel.address) distinctUntilChanged];
RAC(self, viewModel.address) = [RACObserve(address, textValue) distinctUntilChanged];
[self.basic addElement:address];

QEntryElement *city = [[QEntryElement alloc] init];
city.title = @"City";
RAC(city, textValue) = [RACObserve(self, viewModel.city) distinctUntilChanged];
RAC(self, viewModel.city) = [RACObserve(city, textValue) distinctUntilChanged];
[self.basic addElement:city];

QEntryElement *state = [[QEntryElement alloc] init];
state.title = @"State";
RAC(state, textValue) = [RACObserve(self, viewModel.state) distinctUntilChanged];
RAC(self, viewModel.state) = [RACObserve(state, textValue) distinctUntilChanged];
[self.basic addElement:state];

QEntryElement *postal = [[QEntryElement alloc] init];
postal.title = @"Zip";
RAC(postal, textValue) = [RACObserve(self, viewModel.postalCode) distinctUntilChanged];
RAC(self, viewModel.postalCode) = [RACObserve(postal, textValue) distinctUntilChanged];
[self.basic addElement:postal];

QEntryElement *phone = [[QEntryElement alloc] init];
phone.title = @"Phone";
RAC(phone, textValue) = [RACObserve(self, viewModel.phoneNumber) distinctUntilChanged];
RAC(self, viewModel.phoneNumber) = [RACObserve(phone, textValue) distinctUntilChanged];
[self.basic addElement:phone];

我希望能够调用如下方法:

-(QEntryElement *)racEntryElementWithTitle:(NSString *)title andModel(ViewModel *)model andProperty:(NSString*)property;

有没有办法做到这一点?

4

2 回答 2

1

一般来说,如果要双向数据绑定,应该使用RACChannel,这样就不必显式使用-distinctUntilChanged来防止双向数据绑定死循环。要使用 KVO 执行此操作,您需要创建两个 RACChannel(每个 KVO 属性一个)并将一个通道分配给另一个通道followingTerminalfollowingTerminal属性。这通常由RACChannelTo()宏为您完成,但如果您想以 NSString 的形式动态提供键路径,则不能使用该宏;您需要深入研究并直接使用 RACKVOChannel 类:

(此代码未经测试。)

- (QEntryElement *)entryElementWithTitle:(NSString *)title boundWithModel(ViewModel *)model atKeyPath:(NSString*)keyPath
{
    QEntryElement *ee = [[QEntryElement alloc] init];
    ee.title = title;
    RACChannel *modelChannel = [[RACKVOChannel alloc] initWithTarget:model keyPath:keyPath nilValue:@""];
    RACChannelTo(ee, textValue, @"") = modelChannel.followingTerminal;
    return ee;
}


// later...

self.root = [[QRootElement alloc] init];
self.root.title = self.title;
self.root.grouped = YES;

self.basic = [[QSection alloc] init];
self.basic.title = @"Basic Information";
[self.root addSection:self.basic];

[self.basic addElement:[self entryElementWithTitle:@"Address" boundWithModel:self.viewModel atKeyPath:@"address"];
[self.basic addElement:[self entryElementWithTitle:@"City"    boundWithModel:self.viewModel atKeyPath:@"city"];
[self.basic addElement:[self entryElementWithTitle:@"State"   boundWithModel:self.viewModel atKeyPath:@"state"];
[self.basic addElement:[self entryElementWithTitle:@"Zip"     boundWithModel:self.viewModel atKeyPath:@"postalCode"];
[self.basic addElement:[self entryElementWithTitle:@"Phone"   boundWithModel:self.viewModel atKeyPath:@"phoneNumber"];
于 2014-05-27T01:45:39.457 回答
0

您无疑面临的问题是那些宏。解决此问题的一种方法是运行预处理器以查看宏的输出是什么样的。

例如,这一行:

RAC(postal, textValue) = [RACObserve(self, viewModel.postalCode) distinctUntilChanged];

扩展为以下内容:

[[RACSubscriptingAssignmentTrampoline alloc] initWithTarget:(postal) nilValue:(((void *)0))][@(((void)(__objc_no && ((void) postal. textValue, __objc_no)), "textValue"))] = [[(id)(self) rac_valuesForKeyPath:@(((void)(__objc_no && ((void)self.viewModel.postalCode, __objc_no)), "viewModel.postalCode")) observer:self] distinctUntilChanged];

这应该允许您参数化您需要的部分。

于 2014-05-25T13:02:39.520 回答