Как я могу пройти через ячейки UITableView?
У меня есть n разделов (известное количество) и X строк в каждом разделе (неизвестное количество. Каждая строка имеет UITextField. Когда пользователь нажимает кнопку "Готово", я хочу выполнить итерацию по каждой ячейке и выполнить некоторые условные тесты с UITextField. Если тесты передают данные из каждой ячейки, записываются в базу данных. Если нет, то показывается UIAlert. Каков наилучший способ циклически проходить по строкам, и если есть более элегантное решение, пожалуйста, сообщите об этом.
10 ответов
Если вы хотите перебирать только видимые ячейки, используйте
NSArray *cells = [tableView visibleCells];
Если вам нужны все ячейки табличного представления, используйте это:
NSMutableArray *cells = [[NSMutableArray alloc] init];
for (NSInteger j = 0; j < [tableView numberOfSections]; ++j)
{
for (NSInteger i = 0; i < [tableView numberOfRowsInSection:j]; ++i)
{
[cells addObject:[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:j]]];
}
}
Теперь вы можете перебирать все ячейки:
(CustomTableViewCell - это класс, который содержит свойство textField типа UITextField)
for (CustomTableViewCell *cell in cells)
{
UITextField *textField = [cell textField];
NSLog(@"%@"; [textField text]);
}
Вот хорошая быстрая реализация, которая работает для меня.
func animateCells() {
for cell in tableView.visibleCells() as! [UITableViewCell] {
//do someting with the cell here.
}
}
Принимается ответ в кратчайшие сроки для людей, которые не знают ObjC (как и я).
for section in 0 ..< sectionCount {
let rowCount = tableView.numberOfRowsInSection(section)
var list = [TableViewCell]()
for row in 0 ..< rowCount {
let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: row, inSection: section)) as! YourCell
list.append(cell)
}
}
Для xcode 9 используйте это - (похоже на @2ank3th, но код изменен для swift 4):
let totalSection = tableView.numberOfSections
for section in 0..<totalSection
{
print("section \(section)")
let totalRows = tableView.numberOfRows(inSection: section)
for row in 0..<totalRows
{
print("row \(row)")
let cell = tableView.cellForRow(at: IndexPath(row: row, section: section))
if let label = cell?.viewWithTag(2) as? UILabel
{
label.text = "Section = \(section), Row = \(row)"
}
}
}
for (UIView *view in TableView.subviews) {
for (tableviewCell *cell in view.subviews) {
//do
}
}
Поскольку iOS может перерабатывать ячейки tableView вне экрана, вы должны обрабатывать tableView по одной ячейке за раз:
NSIndexPath *indexPath;
CustomTableViewCell *cell;
NSInteger sectionCount = [tableView numberOfSections];
for (NSInteger section = 0; section < sectionCount; section++) {
NSInteger rowCount = [tableView numberOfRowsInSection:section];
for (NSInteger row = 0; row < rowCount; row++) {
indexPath = [NSIndexPath indexPathForRow:row inSection:section];
cell = [tableView cellForRowAtIndexPath:indexPath];
NSLog(@"Section %@ row %@: %@", @(section), @(row), cell.textField.text);
}
}
Вы можете собирать NSArray всех ячеек ТОЛЬКО до того, как весь список будет виден. В таком случае используйте [tableView visibleCells] для безопасности.
Быстро и грязно:
for (UIView *view in self.tableView.subviews){
for (id subview in view.subviews){
if ([subview isKindOfClass:[UITableViewCell class]]){
UITableViewCell *cell = subview;
// do something with your cell
}
}
}
Вот совершенно другой способ думать о циклическом перемещении по строкам UITableView... вот пример изменения текста, который может заполнить ваш UITextView, путем циклического перемещения по вашему массиву, по сути, означая данные вашей ячейки tableView.
Все ячейки заполнены данными из какой-то модели. Очень распространенной моделью было бы использование NSObject и NSMutableArray этих объектов. Если бы вы были в didSelectRowAtIndexPath, вы бы хотели сделать что-то вроде этого, чтобы повлиять на строку, которую вы выбираете после изменения вышеуказанного массива:
for(YourObject *cellRow in yourArray)
{
if(![cellRow.someString isEqualToString:@""])
{
cellRow.someString = @"";
}
//...tons of options for conditions related to your data
}
YourObject *obj = [yourArray objectAtIndex:indexPath.row];
obj.someString = @"selected";
[yourArray insertObject:views atIndex:indexPath.row];
[yourArray removeObjectAtIndex:indexPath.row];
[yourTable reloadData];
Этот код удаляет весь текст UITextField в каждой строке, кроме той, которую вы выбрали, оставляя текст "выделенным" в UITextField повернутой ячейки, пока вы используете obj.someString для заполнения текста поля в cellForRowAtIndexPath или willDisplayRowAtIndexPath с использованием YourObject и yourArray.
Этот тип "зацикливания" не требует никаких условий видимых ячеек против невидимых ячеек. Если у вас есть несколько разделов, заполненных массивом словарей, вы можете использовать одну и ту же логику, используя условие для значения ключа. Может быть, вы хотите переключить изображение ячейки, вы можете изменить строку, представляющую имя изображения. Тонны опций для циклического прохождения данных в вашем tableView без использования каких-либо делегированных свойств UITableView.
Свифт 5:
guard let cells = self.creditCardTableView.visibleCells as? [CreditCardLoanCell] else {
return
}
cells.forEach { cell in
cell.delegate = self
}
Я хотел бы добавить свои два цента к этому вопросу, хотя этот пост старый. Я создал массив типа UITableViewCell и добавлял к нему каждую новую ячейку, прежде чем возвращать ее вcellForRowAt
. См. код ниже:
var cellArray = [UITableViewCell]()
//UITableView code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! Cell
//set up cell information
cellArray.append(cell)
return cell
}
Затем, если вам нужна какая-либо информация из каждой ячейки (например, UITextFields) в вашемDone
кнопку, вы можете перебирать массив таким образом в нужном контексте:
for cell in cellArray {
let myCell = cell as! Cell
//do stuff
}
Надеюсь, это поможет кому-нибудь в будущем