Comments 25
Часто люди любят сразу называть багами то, что они не понимают и с чем неправильно работают. Я не говорю конкретно о Вас и всех тех вещах, которые Вы описали, но часть из них все же надуманные.
— reloadData действительно работает асинхронно. Я не нашел подтверждения этому в документации, но проверить это не сложно, достаточно посмотреть в какой последовательности выполняются методы DataSource для этой UICollectionView.
— «Попытка выполнить две операции анимации одновременно без performBatchUpdates блока приведет к падению приложения. „
на мой взгляд, ве логично и обоснованно. Вы начинаете изменение данных, оно анимируется, все это происходит асинхронно, не дождавшись завершения, Вы начинаете вторую операцию, которая тоже изменяет данные, что же должно произойти?!
и так далее.
— reloadData действительно работает асинхронно. Я не нашел подтверждения этому в документации, но проверить это не сложно, достаточно посмотреть в какой последовательности выполняются методы DataSource для этой UICollectionView.
— «Попытка выполнить две операции анимации одновременно без performBatchUpdates блока приведет к падению приложения. „
на мой взгляд, ве логично и обоснованно. Вы начинаете изменение данных, оно анимируется, все это происходит асинхронно, не дождавшись завершения, Вы начинаете вторую операцию, которая тоже изменяет данные, что же должно произойти?!
и так далее.
0
Статья и не претендует на обучалку, как правильно работать с UICollectionView. Документация же, к сожалению, не содержит ответов на те проблемы, с которыми я неоднократно сталкивался. Я тоже считаю, что костыль — это просто признак того, что разработчик в каком-то смысле сдался, и не нашел корректного и стабильного решения проблемы. Но UICollectionView не оставляет другого выбора. Над некоторыми из проблем, перечисленных в статье, я убил по неделе времени, и не нашел решения лучше, чем описал сейчас.
А самый печальный факт — то, что стабильно работает с UITableView, при абсолютно идентичном использовании — не работает с UICollectionView. Моя библиотека для работы с UITableView — не содержит ни одного костыля в принципе, там все работает стабильно и безошибочно. Хотя архитектура абсолютно идентична тому, что я использую для UICollectionView.
А самый печальный факт — то, что стабильно работает с UITableView, при абсолютно идентичном использовании — не работает с UICollectionView. Моя библиотека для работы с UITableView — не содержит ни одного костыля в принципе, там все работает стабильно и безошибочно. Хотя архитектура абсолютно идентична тому, что я использую для UICollectionView.
+1
Не понимаю вашего комментария. То, что reloadData работает асинхронно, я тоже узнал из личного опыта, и это, поверьте, было совсем не хорошей новостью — легко это проверить или сложно. А вдруг вам надо сначала перезагрузить данные, а потом сразу же вызвать какую-либо анимацию layout-а?
+1
Учите матчасть.
Для справки: данные «перезагружает» collectionView.datasource, а никак не [collectionView reloadData]. Последний отвечает за обновление интерфейса в ответ на измененные данные.
Для справки: данные «перезагружает» collectionView.datasource, а никак не [collectionView reloadData]. Последний отвечает за обновление интерфейса в ответ на измененные данные.
-2
Речь идет именно об обновлении интерфейса. UITableView обновляет его синхронно, UICollectionView, несмотря на отсутствие каких-либо анимаций — асинхронно.
0
Это я понимаю, я отвечал не на Ваш комментарий, а на «сумбурный крик» другого комментирующего.
Что касается асинхронной работы reloadData в UICollectionView, да, это и у меня порой вызывает сложные для решения проблемы, но приходится с этим жить.
Что касается асинхронной работы reloadData в UICollectionView, да, это и у меня порой вызывает сложные для решения проблемы, но приходится с этим жить.
-3
Опечатался ночью, очевидно я писал о перерисовке интерфейса. В самой collection view вообще нет данных, т.к. это юайный класс.
Смените, пожалуйста, тон. Я подозреваю, что у вас не зря карма в минусе и вы со всеми так разговариваете.
Смените, пожалуйста, тон. Я подозреваю, что у вас не зря карма в минусе и вы со всеми так разговариваете.
0
Ох, и больную же вы тему подняли! Давно хотел написать подобную статью, все руки не доходили. Сколько ж я с ней намучался за последние полтора года, а как красиво все начиналось… поначалу я был в восторге и от API, и от возможностей. Глубоко уверен, что Apple стоит больше покрывать код юнит-тестами. Из того, что первым вспомнилось без мака под рукой:
1) UICollectionView плохо обрабатывает очень высокие ячейки. Если высота ячейки — около 5-10 экранов (в зависимости от устройства), она при скроле начинает сначала «снежить», а потом просто пропадает. При этом в Open Source-реализации PSTCollectionView такого бага не было обнаружено.
2) Знает тот, кто пробовал имитировать стандартное для UITableView «залипание» хэдеров секции. После очередного, довольно рандомного Y в contentOffset UICollectionView она перестает махом спрашивать NSLayoutAttributes для, в моем случае, первых пяти секций, и хоть ты убейся. Пиксель назад спрашивает, пиксель вперед — начинает с шестой.
Ну и все или почти все ваши случаи, конечно, встречал. Особенно асинхронность, которой не должно быть, или которая должна быть хотя бы управляемой, и проблемы с синхронизацией анимаций — сущий ад. Добавлю один пункт:
3) Попробуйте запустить какую-либо анимацию в ячейке, и одновременно после этого вызвать reloadData. Крэш обеспечен.
Эпплу по рукам за нефикс багов функционала, который вышел полтора года назад, и юнит-тесты и еще раз юнит-тесты. И функциональные тесты. Библиотеку пишете, а не RSS reader! Зато живые иконки часов сделать — это пожалуйста, это всем очень нужно…
1) UICollectionView плохо обрабатывает очень высокие ячейки. Если высота ячейки — около 5-10 экранов (в зависимости от устройства), она при скроле начинает сначала «снежить», а потом просто пропадает. При этом в Open Source-реализации PSTCollectionView такого бага не было обнаружено.
2) Знает тот, кто пробовал имитировать стандартное для UITableView «залипание» хэдеров секции. После очередного, довольно рандомного Y в contentOffset UICollectionView она перестает махом спрашивать NSLayoutAttributes для, в моем случае, первых пяти секций, и хоть ты убейся. Пиксель назад спрашивает, пиксель вперед — начинает с шестой.
Ну и все или почти все ваши случаи, конечно, встречал. Особенно асинхронность, которой не должно быть, или которая должна быть хотя бы управляемой, и проблемы с синхронизацией анимаций — сущий ад. Добавлю один пункт:
3) Попробуйте запустить какую-либо анимацию в ячейке, и одновременно после этого вызвать reloadData. Крэш обеспечен.
Эпплу по рукам за нефикс багов функционала, который вышел полтора года назад, и юнит-тесты и еще раз юнит-тесты. И функциональные тесты. Библиотеку пишете, а не RSS reader! Зато живые иконки часов сделать — это пожалуйста, это всем очень нужно…
+1
Я плюнул на залипание с помощью хэдеров и делал нормальный лэйаут поверх всего этого безобразия который следит за положением скролла таблицы. Работает безотказно. Там еще все это завязано на положение нав бара, что доставляет отдельного невероятного геморроя.
+1
Т.е. вы подписываетесь на изменение contentInset-a и рисуете хэдер сами? Был бы очень признателен, если бы вы рассказали про свой способ поподробнее, т.к. очень уж много времени убил на эти хэдэры…
0
Да. Мне будет тяжело с примерами кода, они на Xamarin. Но смысл с нативным кодом тот же самый, разве что событие скролла может будет где-то в другом месте.
1. Инициализирую новый View поверх таблицы и связываю его с ней логически. Это наш кастом хэдер (наследован от UIView).
2. Ловлю событие Scrolled в datasource коллекции. Проверяю наличие кастом хэдера и если он есть, то вызываю его метод определения нового положения.
3. Обновляю положение вот таким вот методом внутри кастом хэдера:
1. Инициализирую новый View поверх таблицы и связываю его с ней логически. Это наш кастом хэдер (наследован от UIView).
2. Ловлю событие Scrolled в datasource коллекции. Проверяю наличие кастом хэдера и если он есть, то вызываю его метод определения нового положения.
3. Обновляю положение вот таким вот методом внутри кастом хэдера:
//Метод заставляет хэдер плавно прятаться когда таблица скроллится вниз дальше определенного положения и показываться когда таблица скроллится вверх.
public void Scrolled (MonoTouch.UIKit.UIScrollView scrollView)
{
var topInset = scrollView.ContentOffset.Y + scrollView.ContentInset.Top;
float downInset = 200;
//fix when scroll down and scroll up
if (this.Frame.Y > topInset || this.Frame.Y< downInset ){//<scrollView.ContentInset.Top)
this.Frame = new RectangleF (
x: this.Frame.X,
y: topInset,
width: this.Frame.Width,
height: this.Frame.Height
);
this.SetNeedsDisplay ();
}
}
+1
2) Знает тот, кто пробовал имитировать стандартное для UITableView «залипание» хэдеров секции.
А в вашем случае можно было использовать такой подход: обернуть коллекцию в таблицу, то есть каждая секция в вашей коллекции — ячейка в таблице, у которой на contentView лежит коллекция? В таблице же количество секций = количеству ячеек.
0
Также спасибо за ссылку на DTCollectionViewManager, не сомневаюсь что очень полезная вещь. Но есть один существенный недостаток — любой ваш контроллер должен наследоваться от DTCollectionViewController. А т.к. в objective-c нет множественного наследования, наследоваться от чего-то другого невозможно.
А так конечно да, если данное требование не критично — модель шикарна. Так уже надоело менять Data Source, потом искать index path нужной ячейки и т.п!
А так конечно да, если данное требование не критично — модель шикарна. Так уже надоело менять Data Source, потом искать index path нужной ячейки и т.п!
0
Я тоже думал изначально датасорс делать отдельным обьектом, но в итоге отказался от данной затеи, все-таки слишком сложная получается архитектура. Для себя я решил данную проблему таким способом — везде, где используется UICollectionView или UITableView, и контроллер достаточно сложный, я просто добавляю DTCollectionViewController как childViewController. А события при необходимости прокидываю через протокол. Таким образом родительский контроллер можно унаследовать от чего угодно.
+1
Я натыкался ещё на один баг UICollectionView, когда Flow Layout считал начальную координату по оси X ячейки неправильно если у коллекции был установлен contentInset, воспроизводилось стабильно, но только на некоторых инстансах, то есть в одном приложении из двух казалось бы одинаковых UICollectionView на одном стабильно воспроизводится, на другом стабильно всё прекрасно. Ни причины ни тем более решения так и не нашёл.
Если говорить о UITableView в нём тоже далеко не всё так радужно, прямо сейчас уже больше дня бьюсь головой об стенку. Есть ячейка в xib с включенным auto layout и приложение без него на storyboard (понадобилась динамическая высота ячейки, а приложение полностью переделывать долго), так вот лезет постоянная ошибка с конфликтующими ограничениями среди которых подлый NSAutoresizingMaskLayoutConstraint на contentView, который мало того, что абсолютно непонятно откуда берётся, так ещё и оказывается меньше чем минимальная ширина ячейки, что и влечёт конфликт.
Вообще для меня лично основной источник проблем это невозможность залезть в базовые библиотеки отладчиком (тут я может и просто не туда смотрю, но не вижу как это сделать), и даже там, куда я могу дотянуться, отладчик частенько не может показать значения полей (Даже frame у контрола какого-нибудь). Да я избалован явой, в которой почти всегда можно докопаться что и почему происходит, тут же я прыгаю вокруг чёрного ящика.
Если говорить о UITableView в нём тоже далеко не всё так радужно, прямо сейчас уже больше дня бьюсь головой об стенку. Есть ячейка в xib с включенным auto layout и приложение без него на storyboard (понадобилась динамическая высота ячейки, а приложение полностью переделывать долго), так вот лезет постоянная ошибка с конфликтующими ограничениями среди которых подлый NSAutoresizingMaskLayoutConstraint на contentView, который мало того, что абсолютно непонятно откуда берётся, так ещё и оказывается меньше чем минимальная ширина ячейки, что и влечёт конфликт.
Вообще для меня лично основной источник проблем это невозможность залезть в базовые библиотеки отладчиком (тут я может и просто не туда смотрю, но не вижу как это сделать), и даже там, куда я могу дотянуться, отладчик частенько не может показать значения полей (Даже frame у контрола какого-нибудь). Да я избалован явой, в которой почти всегда можно докопаться что и почему происходит, тут же я прыгаю вокруг чёрного ящика.
0
frame можно вывести в консоль через po [NSValue valueWithCGRect:view.frame].
С констрэйнтами есть такая беда — они очень плохо работают в иерархии вьюх, в которых то используется, то не используется автолэйаут. Мой совет — все же переделать ячейку без autolayout.
С констрэйнтами есть такая беда — они очень плохо работают в иерархии вьюх, в которых то используется, то не используется автолэйаут. Мой совет — все же переделать ячейку без autolayout.
+1
вы проверяли какие-то из этих «багов» на бете 7.1?
может быть что-то из этого уже пофиксено?
может быть что-то из этого уже пофиксено?
0
Как мне кажется, 90 % причин всех багов в UICollectionView можно разделить на две категории:
1) множественные анимированные действия без performBatchUpdates блока;
2) наличие нескольких секций, хедеров (supplementary view) и футеров (decoration view).
Первое вроде как не тревожит, если все множественные вставки/удаления делать корректно и по науке (читай в performBatchUpdates) блоке.
По поводу второго, мне кажется, есть неплохой вариант, который даже вроде бы и не костыль вовсе. Суть в том, чтобы использовать только односекционные коллекции без футеров и хедеров. А уже эти коллекции использовать как ячейки UITableView, который и будет ответственным за возню со всеми этими хедерами и футерами (а он с этим неплохо справляется).
При секциях, предполагающих большое количество ячеек, конечно, таким грешить не стоит.
1) множественные анимированные действия без performBatchUpdates блока;
2) наличие нескольких секций, хедеров (supplementary view) и футеров (decoration view).
Первое вроде как не тревожит, если все множественные вставки/удаления делать корректно и по науке (читай в performBatchUpdates) блоке.
По поводу второго, мне кажется, есть неплохой вариант, который даже вроде бы и не костыль вовсе. Суть в том, чтобы использовать только односекционные коллекции без футеров и хедеров. А уже эти коллекции использовать как ячейки UITableView, который и будет ответственным за возню со всеми этими хедерами и футерами (а он с этим неплохо справляется).
При секциях, предполагающих большое количество ячеек, конечно, таким грешить не стоит.
0
Sign up to leave a comment.
UICollectionView или танцы с волками