ReactiveCocoa 连接到 UICollectionViewCell 子视图
ReactiveCocoa connection to UICollectionViewCell subview
我有一个 UICollectionView
,它加载我的自定义 UICollectionViewCell
,其中有一个 UITextField
和一个 UILabel
。
在我的 cellForItemAtIndexPath
中,我正在做这样的事情:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
BBCollectionViewTextFieldCell *textFieldCell = [collectionView dequeueReusableCellWithReuseIdentifier:[BBCollectionViewTextFieldCell reuseIdentifier] forIndexPath:indexPath];
NSString *label = @"";
switch (indexPath.item){
case 0:
label = @"Label One";
self.firstTextField = textFieldCell.textField;
textFieldCell.textField.text = self.viewModel.labelOneData;
break;
case 1:
label = @"Label Two";
self.secondTextField = textFieldCell.textField;
textFieldCell.textField.text = self.viewModel.labelTwoData;
break;
case 2:
label = @"Label Three";
self.thirdTextField = textFieldCell.textField;
textFieldCell.textField.text = self.viewModel.labelThreeData;
break;
}
textFieldCell.label.text = label;
textFieldCell.textField.delegate = self;
return textFieldCell;
}
然后我使用正常的 UITextFieldDelegate
方法来处理文本输入,就像这样:
-(void)textFieldDidEndEditing:(UITextField *)textField{
if (textField == self.firstTextField){
//Do something with it
}
//And so on for the rest...
}
到目前为止一切顺利...
这是什么问题?
问题是如果我重新加载 UICollectionView
会发生以下情况:
self.firstTextField
中将包含属于 self.thirdTextField
的数据
或其任意组合。 UILabel
都是正确的 - 但是实际的 UItextField
似乎已经混淆了。第一个 UICollectionViewCell
的 UitextField
实际上会有来自另一个单元格的文本字段的数据。
起初我认为这是一个重用问题 - 然而,因为我的单元格永远不会滚动到屏幕外并且数据非常静态,(总是有 X 数量的单元格,不多也不少) - 所以它可以'这不是重用问题。
我修改了代码,因此我的 UIViewController
中没有 UitextField
Properties
代码所在的位置 - 并依赖 indexPath
获取文本字段。像这样 cellForItemAtIndexPath
switch (indexPath.item){
case 0:
label = @"Label One";
textFieldCell.textField.text = self.viewModel.labeloneData;
break;
和:
-(void)textFieldDidEndEditing:(UITextField *)textField{
NSIndexPath *indexPath = [self.collectionView indexPathForCellContaininView:textField];
if(indexPath.item == 0){
//Do something with it
}
//And so on for the rest...
}
这解决了问题,但这不是我想要做的。我的 UIViewController
中需要 UItextField
属性
我在实现中声明了 UitextField
Properties
:
@property (strong, nonatomic) UITextField *firsttextField;
我也发布了一个非常相似的问题,但使用 UITableView
代替,并得出结论它与单元格重用有关 - 但我不相信它了(同样,该问题代码中的设置几乎相同对于这个问题 - 虽然是同样的问题)
我觉得问题出在哪里
我认为这与 UITableView
或 UiCollectionView
重用细胞的方式无关。我认为问题出在 viewController's
代码和我的 UItextField
属性的实例中。不过我可能在这里偏离了基础。
我知道我列出了一个可能的解决方法 - 但是我想深入了解这个问题并找出它发生的原因。
保持指向 UITableView/UICollectionView 单元格子视图的指针很麻烦,因为单元格在滚动时被重复使用——并且可能在重新加载时被打乱。重用后,您认为在一个索引路径中的子视图现在在另一个索引路径中。
最常见的解决方案是自定义单元格中的插座。其他人会在每次配置单元时更新标签。其他人喜欢快速搜索视图层次结构(例如,点击按钮)以找出子视图对应的索引路径。
但是由于 ReactiveCocoa 完全是关于模型-视图连接的,所以它需要一对指针。幸运的是,它还提供了与单元重用相对应的结束条件。 This gist demonstrates 如何为 table 视图单元格的子视图建立反应式连接。复制到这里...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:REUSABLE_CELL_ID];
UILabel *label = (UILabel *)[cell viewWithTag:VIEW_TAG];
Model *someModel = [self getModelFromIndexPath:indexPath];
// `takeUntil:` makes the RACObserve() signal complete (and thus breaks the subscription)
// when the cell is recycled.
RAC(label, text) = [RACObserve(someModel, someKey)
takeUntil:cell.rac_prepareForReuseSignal];
return cell;
}
我有一个 UICollectionView
,它加载我的自定义 UICollectionViewCell
,其中有一个 UITextField
和一个 UILabel
。
在我的 cellForItemAtIndexPath
中,我正在做这样的事情:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
BBCollectionViewTextFieldCell *textFieldCell = [collectionView dequeueReusableCellWithReuseIdentifier:[BBCollectionViewTextFieldCell reuseIdentifier] forIndexPath:indexPath];
NSString *label = @"";
switch (indexPath.item){
case 0:
label = @"Label One";
self.firstTextField = textFieldCell.textField;
textFieldCell.textField.text = self.viewModel.labelOneData;
break;
case 1:
label = @"Label Two";
self.secondTextField = textFieldCell.textField;
textFieldCell.textField.text = self.viewModel.labelTwoData;
break;
case 2:
label = @"Label Three";
self.thirdTextField = textFieldCell.textField;
textFieldCell.textField.text = self.viewModel.labelThreeData;
break;
}
textFieldCell.label.text = label;
textFieldCell.textField.delegate = self;
return textFieldCell;
}
然后我使用正常的 UITextFieldDelegate
方法来处理文本输入,就像这样:
-(void)textFieldDidEndEditing:(UITextField *)textField{
if (textField == self.firstTextField){
//Do something with it
}
//And so on for the rest...
}
到目前为止一切顺利...
这是什么问题?
问题是如果我重新加载 UICollectionView
会发生以下情况:
self.firstTextField
中将包含属于self.thirdTextField
的数据
或其任意组合。 UILabel
都是正确的 - 但是实际的 UItextField
似乎已经混淆了。第一个 UICollectionViewCell
的 UitextField
实际上会有来自另一个单元格的文本字段的数据。
起初我认为这是一个重用问题 - 然而,因为我的单元格永远不会滚动到屏幕外并且数据非常静态,(总是有 X 数量的单元格,不多也不少) - 所以它可以'这不是重用问题。
我修改了代码,因此我的 UIViewController
中没有 UitextField
Properties
代码所在的位置 - 并依赖 indexPath
获取文本字段。像这样 cellForItemAtIndexPath
switch (indexPath.item){
case 0:
label = @"Label One";
textFieldCell.textField.text = self.viewModel.labeloneData;
break;
和:
-(void)textFieldDidEndEditing:(UITextField *)textField{
NSIndexPath *indexPath = [self.collectionView indexPathForCellContaininView:textField];
if(indexPath.item == 0){
//Do something with it
}
//And so on for the rest...
}
这解决了问题,但这不是我想要做的。我的 UIViewController
UItextField
属性
我在实现中声明了 UitextField
Properties
:
@property (strong, nonatomic) UITextField *firsttextField;
我也发布了一个非常相似的问题,但使用 UITableView
代替,并得出结论它与单元格重用有关 - 但我不相信它了(同样,该问题代码中的设置几乎相同对于这个问题 - 虽然是同样的问题)
我觉得问题出在哪里
我认为这与 UITableView
或 UiCollectionView
重用细胞的方式无关。我认为问题出在 viewController's
代码和我的 UItextField
属性的实例中。不过我可能在这里偏离了基础。
我知道我列出了一个可能的解决方法 - 但是我想深入了解这个问题并找出它发生的原因。
保持指向 UITableView/UICollectionView 单元格子视图的指针很麻烦,因为单元格在滚动时被重复使用——并且可能在重新加载时被打乱。重用后,您认为在一个索引路径中的子视图现在在另一个索引路径中。
最常见的解决方案是自定义单元格中的插座。其他人会在每次配置单元时更新标签。其他人喜欢快速搜索视图层次结构(例如,点击按钮)以找出子视图对应的索引路径。
但是由于 ReactiveCocoa 完全是关于模型-视图连接的,所以它需要一对指针。幸运的是,它还提供了与单元重用相对应的结束条件。 This gist demonstrates 如何为 table 视图单元格的子视图建立反应式连接。复制到这里...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:REUSABLE_CELL_ID];
UILabel *label = (UILabel *)[cell viewWithTag:VIEW_TAG];
Model *someModel = [self getModelFromIndexPath:indexPath];
// `takeUntil:` makes the RACObserve() signal complete (and thus breaks the subscription)
// when the cell is recycled.
RAC(label, text) = [RACObserve(someModel, someKey)
takeUntil:cell.rac_prepareForReuseSignal];
return cell;
}