iOS: шаблон проектирования для заполнения асинхронно извлекаемых данных

Я разрабатываю приложение, которое извлекает данные из Интернета и отображает их пользователю. Предположим, что данные представляют собой отзывы о ресторане и на одном просмотре отображается один отзыв. Пользователь может провести пальцем влево или вправо, чтобы перейти к предыдущему/следующему обзору. Данные извлекаются асинхронно (один поток для каждого обзора).

Вот постановка проблемы. Предположим, что было получено 5 отзывов, а пользователь в данный момент просматривает 3-й. Теперь 6-й обзор получен, и я хочу отобразить его как 4-й обзор для пользователя (поскольку дата публикации 6-го обзора более поздняя, ​​чем 5-й обзор). Как мой класс модели должен информировать контроллер представления?

Я рассмотрел несколько вариантов -

  1. Предоставьте массив контроллеру представления, а затем отправьте NSNotifications о новых элементах, которые будут вставлены между массивом по определенному индексу.
  2. Используйте NSFetchedResultsController (это немного сложно, потому что я не использую его с контроллером табличного представления)
  3. Контроллер представления всегда запрашивает отображение следующего обзора (из модели) и не имеет с собой массива обзоров.

Существуют ли какие-либо установленные шаблоны проектирования, которые используются в таком сценарии? Другие предложения, кроме 3 выше, приветствуются!


person Akshay    schedule 25.02.2014    source источник
comment
Это не очень хорошее описание проблемы для запроса шаблона проектирования. Вы можете применить известные варианты MVC и табличного представления с отложенной загрузкой, а также общепринятые практики асинхронного программирования. Заявленное вами требование также неясно: Теперь получен 6-й обзор, и я хочу отобразить его как 4-й обзор для пользователя. Как мой класс модели должен информировать контроллер представления? А? Кто я? Буквально, если вы хотите, чтобы 6-й обзор был размещен на позиции 4, просто вставьте его в массив в этой позиции, а затем обновите представление таблицы. Хотя, я не думаю, что вы имели это в виду, не так ли?   -  person CouchDeveloper    schedule 27.02.2014
comment
Я сам, разработчик. Я четко упомянул, что вместо отображения таблицы я показываю представление, в котором пользователи могут провести пальцем вправо или влево, чтобы увидеть следующий элемент (аналогично приложению для фотографий).   -  person Akshay    schedule 27.02.2014


Ответы (4)


Просто используйте NSFetchedResultsController. При использовании NSIndexPath просто игнорируйте section. По сути, это прославленный NSArray с бесплатными уведомлениями.

Вот как я думаю, что я бы сделал это:

  • Убедитесь, что NSFetchRequest для вашего NSFetchedResultsController отсортировано по дате публикации.
  • Обработка NSFetchedResultsControllerDelegate методов.
  • Когда NSFetchedResultsController обновится, сохраните текущий объект, перезагрузите представление коллекции, а затем прокрутите до сохраненного объекта без анимации. Это покажется пользователю, как будто с текущей страницей ничего не произошло.
person John Estropia    schedule 04.03.2014
comment
Я делаю это для своих нужд. Тем не менее, я знаком с базовыми данными с 2007 года. @Akshay, если вы хотите, это лучший путь, но у вас могут возникнуть некоторые проблемы роста, чтобы справиться с вашим первым выпуском и после следующего выпуска, когда вы найдете свой модели нужно что-то другое. - person Derek; 06.03.2014
comment
Спасибо! В итоге я выбрал вариант № 3 в своем вопросе. Контроллер представления тупой и всегда запрашивает отображение следующего обзора. Модель управляет всем заказом. Таким образом, только модель имеет хитрый код, а контроллер находится в блаженном неведении. - person Akshay; 06.03.2014

Хотя не существует идеального шаблона проектирования для каждой проблемы программирования, самое близкое, что я могу придумать, относится к вашей проблеме, это комбинация шаблонов Command и Observer.

https://en.wikipedia.org/wiki/Command_pattern

Шаблон наблюдателя используется в центре NSNotification.

Хотя неясно, почему вы хотите пропустить обзор, вы можете иметь два массива для их хранения при извлечении. Первый содержит все отзывы, которые вы получили. Второй содержит все отображаемые отзывы.

Затем вы можете получить последний обзор в выбранном массиве, как если бы это был стек. Таким образом, у вас всегда будет отображаться последний загруженный файл.

person TigerCoding    schedule 27.02.2014

Меня смущает, почему порядок отображения отличается от истинного порядка, т.е. почему 6-й обзор идет раньше 5-го, а вы просили помочь шаблоны.

Помимо MVC и наблюдателя, которые есть в других ответах и ​​комментариях, я бы предложил использовать ленивую загрузку с virtual proxy. Когда обзоры загружены, вы можете просто отобразить их прокси (например, с сообщением «загрузка...», пока они полностью не будут в памяти).

Подробнее см. здесь: http://en.wikipedia.org/wiki/Proxy_pattern

person Fuhrmanator    schedule 01.03.2014
comment
Как ни странно, он не хочет отображать загрузку, он хочет показать только то, что загружается первым. Вот почему я дал другую рекомендацию. Однако, если бы у него не было этого требования, я думаю, что ваше предложение было бы более подходящим. - person TigerCoding; 02.03.2014
comment
Спасибо за помощь. Причина, по которой истинный порядок отличается от порядка отображения, заключается в следующем: а) я не хочу, чтобы пользователь ждал, пока будут получены все отзывы; б) в этом сценарии новый отзыв имеет гораздо большее значение и должен отображаться сразу после достается - person Akshay; 02.03.2014
comment
Шаблон проектирования — это решение часто возникающей проблемы. То, как вы описываете свою проблему, довольно уникально, но, возможно, у других будут идеи. - person Fuhrmanator; 02.03.2014
comment
Вот почему я спросил: существуют ли какие-либо установленные шаблоны проектирования, которые используются в таком сценарии? Ответ может быть Нет. :-) - person Akshay; 03.03.2014

Я бы рекомендовал использовать шаблон наблюдения, чтобы информировать ваш контроллер о том, что новые данные были получены. При получении сигнала ваш контроллер представления может обновить свой массив «обзоров ресторанов» (либо добавив старый и переупорядочив его в соответствии с некоторыми дескрипторами сортировки вашего вкуса, либо напрямую запросив DAO). Допустим, вы извлекаете свои данные из Интернета и заполняете объект CoreData результатами. После того, как вы получили загруженные данные, вы можете заполнить сущность «Обзор» основных данных. Чтобы «прослушать» изменения, происходящие в основных данных, ваш контроллер должен в теле viewDidLoad зарегистрироваться в качестве наблюдателя для NSManagedObjectContextDidSaveNotification.

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(updateInfo:) name:NSManagedObjectContextDidSaveNotification object:nil];

Затем в вашем updateInfo вы можете получить изменения

- (void) updateInfo:(NSNotification *)notification { self.reviews = [self.managedObjectContext performRequest:myFetchRequest error:nil]; }

person Florian Burel    schedule 05.03.2014