Преимущество заключается в том, что вам не нужно проверять код ошибки после каждого потенциально неудачного вызова. Чтобы это работало, вам нужно объединить его с классами RAII, чтобы все автоматически очищалось при разматывании стека.
С сообщениями об ошибках:
int DoSomeThings()
{
int error = 0;
HandleA hA;
error = CreateAObject(&ha);
if (error)
goto cleanUpFailedA;
HandleB hB;
error = CreateBObjectWithA(hA, &hB);
if (error)
goto cleanUpFailedB;
HandleC hC;
error = CreateCObjectWithA(hB, &hC);
if (error)
goto cleanUpFailedC;
...
cleanUpFailedC:
DeleteCObject(hC);
cleanUpFailedB:
DeleteBObject(hB);
cleanUpFailedA:
DeleteAObject(hA);
return error;
}
С исключениями и RAII
void DoSomeThings()
{
RAIIHandleA hA = CreateAObject();
RAIIHandleB hB = CreateBObjectWithA(hA);
RAIIHandleC hC = CreateCObjectWithB(hB);
...
}
struct RAIIHandleA
{
HandleA Handle;
RAIIHandleA(HandleA handle) : Handle(handle) {}
~RAIIHandleA() { DeleteAObject(Handle); }
}
...
На первый взгляд версия RAII / Исключения выглядит длиннее, пока вы не поймете, что код очистки должен быть написано только один раз (и есть способы упростить это). Но вторая версия DoSomeThings намного понятнее и удобнее в обслуживании.
НЕ пытайтесь использовать исключения в C ++ без языка RAII, так как это приведет к утечке ресурсов и памяти. Вся ваша очистка должна быть сделана в деструкторах объектов, выделенных стеком.
Я понимаю, что есть и другие способы обработки кода ошибки, но все они выглядят примерно одинаково. Если вы бросите gotos, вы в конечном итоге будете повторять код очистки.
Одним из пунктов кодов ошибок является то, что они делают очевидным, где что-то может выйти из строя и как оно может выйти из строя. В приведенном выше коде вы пишете его с предположением, что что-то не выйдет из строя (но если они это сделают, вы будете защищены оболочками RAII). Но вы в конечном итоге уделяете меньше внимания тому, где что-то может пойти не так.
Ну, на случай, если вы так и не нашли решение, или для тех, кто задаст этот вопрос дальше, я дам вам ответ, который вы искали. UITableView предоставит вам indexPaths, которые вы ищете, а затем UITableView с радостью предоставит вам ячейки, соответствующие этим индексным путям:
UITableView *tableView = self.tableView; // Or however you get your table view
NSArray *paths = [tableView indexPathsForVisibleRows];
// For getting the cells themselves
NSMutableSet *visibleCells = [[NSMutableSet alloc] init];
for (NSIndexPath *path in paths) {
[visibleCells addObject:[tableView cellForRowAtIndexPath:path]];
}
// Now visibleCells contains all of the cells you care about.
Вместо того, чтобы сосредотачиваться на том, когда UITableView запрашивает ячейку, вам следует сосредоточиться на том, когда он отображает ячейку, что указано методом делегата tableView: willDisplayCell: forRowAtIndexPath
.