Reputation: 1859
I have a CollectionView
and inside each cell of this collectionView
there is one textField
.
If all content of the textfield
is nil
, when I change content of one textfield
(for example cell_1) all other textfield
s will auto update content with value like the content of textfield
in cell_1.
I have tried with collectionView.visibleCells
but it does not work properly for my scene.
Is there any way that I can change one cell then update for all cells in CollectionView
?
Please help. Thanks in advance!
Upvotes: 0
Views: 4265
Reputation: 10329
Clear new cells:
Since I am not understanding your question to a 100%, I assume that your problem is that new cells get the value of cell_1, which is not something you want.
If that is the case, then there is a function called prepareForReuse
in UICollectionViewCell
.
In your subclass of the UICollectionViewCell
, implement the following:
override func prepareForReuse() {
super.prepareForReuse()
textfield.text = ""
}
That should do the trick, given that your textfield
is called textfield
.
Performs any clean up necessary to prepare the view for use again. https://developer.apple.com/reference/uikit/uicollectionreusableview/1620141-prepareforreuse
Update all cells:
If your question is how to update other cells to get the same content as cell_1, then this means that the Collection View subclass needs to know about an update in cell_1 and then transform that update to the other cells.
One way of doing that is having your textfield
s delegate set in the Collection View. When the value is changed (textField(_:shouldChangeCharactersIn:replacementString:)
), get all the visible cells and update those textfields
accordingly. Maybe also save either a reference to the textfield
in cell_1, or a string variable in your Collection View stating the latest entered value so you can update cells as they get rendered.
You don't want to use reloadData()
though, since that will remove the focus from the textField
, since the textField
is reloaded.
Solution:
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
fileprivate var customString: String?
}
extension ViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.textField.delegate = self
cell.textField.text = customString
return cell
}
}
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
customString = string
for cell in collectionView.visibleCells {
if let cell = cell as? CustomCell,
let text = textField.text,
cell.textField != textField {
cell.textField.text = text+string
}
}
return true
}
}
The only con in the code above is that it loops through cells that currently are visible. Usually I'd recommend to stay out of looping unless absolutely necessary, but the alternative to the solution above would be to post a notification and having the cells listen to that notification and update its content accordingly. Doing that would not only be overkill, but also something notifications aren't really meant for. Third option would be to hold a weak reference in an array to every textfield, which might not be optimal as well since it creates unnecessary overhead. After all visibleCells
already is an array of the cells currently visible which each hold a reference to an UITextField
.
Upvotes: 2
Reputation: 856
try this -
Step 1 -
Create a variable like and IBOutlet of your collection view -
var xyzString: String?
@IBOutlet weak var collectionView: UICollectionView! // IBOutlet of your collection view
Step 2 -
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TagViewCell", for: indexPath) as? TagViewCell // instead of TagViewCell give your custom cell class name
if self.xyzString != nil {
cell?.txtField.text = self.xyzString // if you want same value for all cell
}
return cell!
}
Step 3 -
func textFieldDidEndEditing(_ textField: UITextField) {
self.xyzString = textField.text
self.collectionView.reloadData()
}
Upvotes: 1