Как перезагрузить данные в UITableView в MonoTouch?

В моем приложении я отображаю данные из онлайн-веб-службы в несколько UITableViews. Я добавил несколько способов обновления данных пользователем, но метод TableView.ReloadData() не работает. Когда пользователь вызывает обновление, я получаю новый набор данных с сервера, передаю его экземпляру UITableViewSource, прикрепленному к UITableViewController, а затем вызываю метод ReloadData(), который, к сожалению, фактически не перезагружает данные. Только после того, как я вернусь на главный экран, а затем вернусь к табличному представлению (поскольку оно уже создано, я просто показываю экземпляр, который уже существует), новые данные отображаются в табличном представлении. Что я делаю неправильно? Я попытался создать новый экземпляр UITableViewSource при обновлении данных, но это тоже не помогает.

Вот код для загрузки данных в табличное представление (я повторно использую его для любого события, требующего загрузки в него данных):

 dataControl.GetList(Tables.UPDATES)); //gets data from the server and passes it to the SQL database
 Source source = GetSource(theType.Name, theType, groups); //creates a new source loaded with the data
 Updates.TableView.Source = source;
 Updates.TableView.AllowsSelection = false;     
 Updates.TableView.ReloadData();

Этот код, конечно же, выполняется в отдельном потоке, который вызывается в основном потоке. В основном тот же код вызывается, когда пользователь запрашивает обновление (анимация воспроизводится, пока работает фоновый поток).


person Kiril    schedule 28.02.2011    source источник


Ответы (5)


Павел прав - попробуйте следующее, чтобы посмотрите, работает ли это:

InvokeOnMainThread(delegate{
    Updates.TableView.Source = source;
    Updates.TableView.AllowsSelection = false;
    Updates.TableView.ReloadData();
});

В будущем всякий раз, когда вы будете иметь дело с чем-то, что изменит отображаемый в данный момент пользовательский интерфейс, вам нужно будет убедиться, что это происходит в основном потоке (также известном как поток графического интерфейса пользователя). Этот InvokeOnMainThread является методом из NSObject, поэтому его можно вызывать, как указано выше, во всех UIViews/UIViewControllers и т. д. Вы также можете вызывать его из полностью класса C#, используя:

MonoTouch.UIKit.UIApplication.SharedApplication.InvokeOnMainThread(delegate{ /*code here*/ });
person Luke    schedule 01.03.2011
comment
Спасибо за ответ. Я проверил это, но это не имеет значения. Я попытался поместить весь код в поток графического интерфейса, но это тоже не сработало. Я проверил, выполняется ли ReloadData() без блокировки, и он работает правильно. Возможно ли, что мне нужно использовать какой-то другой метод для обновления представления таблицы? Может быть, сделать его недействительным и заставить его перерисовываться на экране? - person Kiril; 01.03.2011
comment
как странно. Это похоже на проблему с обновлением. Это сложно, но вы пробовали и TableView.SetNeedsDisplay();? - person Luke; 01.03.2011
comment
Да, пробовал, к сожалению, ничего не вышло. Я просматривал документацию MonoTouch, но многие вещи не задокументированы. Я мог бы попытаться перейти к корневому контроллеру представления, а затем нажать на перезагруженный контроллер представления, но, во-первых, это ужасный хак, и я действительно хотел бы использовать лучшее решение, а во-вторых, это может сбить пользователя с толку (так как это требует некоторое время, чтобы вытолкнуть, а затем нажать контроллер представления). Спасибо за помощь! - person Kiril; 01.03.2011
comment
Это может быть связано с тем, как вы настраиваете источник TableView. Когда вы выходите из этого представления, а затем снова включаете его, это приведет к срабатыванию ViewWillAppear — есть ли что-то в этом методе, что вы делаете иначе, чем здесь? p.s. не беспокойтесь, я довольно заинтригован этим! - person Luke; 01.03.2011
comment
Привет, спасибо за ответ. Я ничего не делаю в ViewWillAppear. Источник, который я устанавливаю следующим образом: «Updates.TableView.Source = новый USource (некоторые параметры);» Я попытался избавиться от источника/контроллера/TableView самого TableView, прежде чем давать ему новый, но это не имело значения. Я попытаюсь как-то вызвать ViewWillAppear вручную, чтобы посмотреть, работает ли это. - person Kiril; 02.03.2011
comment
Что мне иногда помогает, так это создать новый проект и вырезать все, что не связано с проблемой, и попытаться воспроизвести это. Если это сработает, я буду медленно добавлять к нему биты, пока он не перестанет работать (тогда у вас будет зацепка о том, что вызывает хаос) или вы останетесь с идентичным проектом, который, кажется, работает (что было бы больше всего в ярости). !) - person Luke; 02.03.2011
comment
Нет, вызов ViewWillAppear вручную не работает. Я действительно сбит с толку в этот момент. Я проверил несколько примеров Objective-C о том, как это сделать, и предполагается, что он работает только с ReloadData(). - person Kiril; 02.03.2011
comment
Можно ли опубликовать пример проекта (даже если это просто урезанный проект, в котором все еще есть проблема), трудно отлаживать такие глубокие проблемы удаленно! - person Luke; 02.03.2011
comment
Да, я сделаю это в течение 3-4 часов, извините за задержку. - person Kiril; 03.03.2011

Вы говорите, что это делается в другом потоке, может быть, рабочий поток не может вызвать поток пользовательского интерфейса? т.е. вы должны вызвать ReloadData через делегата, чтобы убедиться, что он вызывается в потоке пользовательского интерфейса, а не «только» в рабочем потоке, поскольку он может блокироваться и никогда не вызываться на самом деле (со мной это произошло в другом сценарии).

person Pavel Sich    schedule 01.03.2011

Я также столкнулся с этой проблемой и нашел этот вопрос. Используя некоторые подсказки здесь, я, наконец, заработал, сбросив DataSource и вызвав ReloadView().

tableView.DataSource = new MyDataSource(...);
tableView.RelaodData();

Судя по моему тестированию, это не имеет значения, если я оберну ReloadView() в InvokeOnMainThread или нет. Ну, это может быть потому, что я не использую рабочий поток.

Странно, что в другом случае я мог обновить табличное представление, просто вызвав ReloadData() в ViewDidAppear(). Единственное отличие состоит в том, что приведенный выше случай — это обновление в том же представлении.

person newman    schedule 21.11.2011

Вы можете перезагрузить данные в viewwillappear() или установить код загрузки данных в viewwillappear().

person 能蟹仔    schedule 11.08.2012

Для гуглеров:

У меня были те же проблемы. Это то, что исправило это для меня

InvokeOnMainThread(delegate {
    myTableView.Source = new TableViewSource();
    myTableView.ReloadData();
    this.View.SetNeedsDisplay();
});
person fukijama    schedule 22.05.2015