iPhone: список друзей, как это удалось Facebook? - PullRequest
1 голос
/ 28 апреля 2011

Интересно, кто-нибудь может порассуждать или, что еще лучше, предоставить фрагмент кода для реализации длинного списка друзей в приложении Facebook для iPhone.

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

Когда я пробую его в своем собственном приложении, требуется много драгоценных секунд, чтобы заполнить представление таблицы теми же данными, поэтомуКак Facebook достиг такого быстрого времени отклика?

при просмотре таблицы в приложении facebook вы замечаете, что в таком просмотре таблицы обычно нет полосы прокрутки, может ли это быть одним из признаков аккуратного трюка, который использует Facebookдобиться этой быстрой вставки строк?Может быть, они реализовали своего рода виртуальное табличное представление, содержащее всего несколько десятков строк, но вращающее их?

есть мысли?

Ответы [ 2 ]

3 голосов
/ 28 апреля 2011

UITableView позволит вам сделать это.В Интернете есть несколько примеров использования UITableView и пользовательских ячеек

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

РЕДАКТИРОВАТЬ Добавлен пример кода для демонстрации того, как это выполняется.
ВАЖНОЕ ПРИМЕЧАНИЕ
Этот код не был протестирован и может или не может фактически работать как есть.
Он был вставлен с некоторымиредактирование для длины.Я сделал намного больше, чем это, в своем приложении, но в целях соблюдения запрошенного примера я много пропустил.

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"OfferCell";
    static NSString *CellNib = @"OfferItem";

    OfferCell* cell = (OfferCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
        cell = (OfferCell*)[nib objectAtIndex:0];
    }



    NSDictionary* couponPackage = [self.jsonOfferData valueForKey:@"result"];

    NSArray *couponList = [couponPackage valueForKey:@"offers"];

    if ([couponList count] >= indexPath.row )
    {
        NSDictionary* couponData = [couponList objectAtIndex:indexPath.row];
        Coupon *coupon = [[Coupon alloc] initWithDictionary:couponData];

        NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:cell,@"cell",coupon,@"coupon", nil];

        //Right here you would try to load any cached imaged from disk.

        //Then send a Thread to the background to load the image.
        [self performSelectorInBackground:@selector(loadTableViewCellData:) withObject:params];

        //Load up the rest of the custom info into the custom cell.
        [cell.captionLabel setText:coupon.name];
        [cell.subTextLabel setText:coupon.subText];
        [cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
        [cell setCommand:coupon.command];
        [cell setParameter:coupon.commandArgs];
        [cell setImageURL:coupon.imageURL];
        [cell setImageAltURL:coupon.imageAltURL];
        [cell setRegistrationCode:coupon.registrationCode];
        [coupon release];
    }    

    return cell;
}

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

- (void) loadTableViewCellData:(NSDictionary*) objectData
{
    OfferCell *cell = [objectData objectForKey:@"cell"];
    Coupon *coupon = [objectData objectForKey:@"coupon"];
    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[coupon iconURL]]]];
    [objectData setValue:image forKey:@"image"];
    self performSelectorOnMainThread:@selector(setImageOnMainThread:) withObject:objectData
}

после загрузки изображения я отправляю запрос главного потока для обновления изображения, находящегося в объекте ячейки.

- (void) setImageOnMainThread:(NSDictionary*) objectData
{
    OfferCell *cell = [objectData objectForKey:@"cell"];
    Coupon *coupon = [objectData objectForKey:@"coupon"];
    UIImage *image = [objectData objectForKey:@"image"];
    cell.icon.image = image;
}

## ОПЯТЬ Это может не работать на самом деле.##
Я не скопировал весь свой код для этого.это хит, чтобы вы могли понять.
поиграйте с кодом и протестируйте его.но основы есть.

  • Удалите из очереди ячейку, которая будет соответствовать вашим потребностям (Идентификатор повторного использования)
  • Используйте ячейку, если она может быть dequeue'd или создайте новую с идентификатором повторного использования (в моем примере используютсяxib-файл с именем OfferItem.xib)
  • Отправка потока в фоновый режим, который будет загружать данные изображения с диска или URL-адреса (рекомендуется сочетание обоих)
  • Отправка потока обратно вПользовательский интерфейс, когда вы готовы загрузить изображение в View (Обновление пользовательского интерфейса должно быть сделано в главном потоке)

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

Также, если вы используете технику кэширования, это будет быстрее для последующих загрузок, потому что в первом методе {tableView: cellForRowAtIndexPath:} вы загрузитеКэшированное изображение немедленно.

Кроме этого, это должно довольно быстро загрузить вашу клетку.

1 голос
/ 28 апреля 2011

Они, очевидно, загружают данные из локального ресурса (plist, ManagedObject, ...)

Взгляните на пример кода, чтобы нарисовать TableView:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *kCellIdentifier = @"MyCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kCellIdentifier] autorelease];
}
return cell;
}

dequeueReusableCellWithIdentifier: это одна из причин, по которой TableViews в iOS могут рисовать быстро. Это работает как-то так:

1) Вы предоставляете идентификатор для создаваемой ячейки.

2) Клетки, которые видны сначала, выделяются (с идентификатором)

3) Когда ячейка убирается с экрана, она складывается в кучу MyCellIdentifier

4) Всякий раз, когда системе нужно нарисовать ячейку идентификатора: MyCellIdentifier , сначала проверяется, есть ли какие-либо ячейки, в настоящее время неиспользуемые в куче MyCellIdentifier . Если это так, он выбирает один из кучи и, следовательно, не должен выделять новый. Таким образом, дорогостоящее выделение может быть сведено к минимуму.

Надеюсь, это ответит на ваш вопрос:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...