Разобрать запрос в ViewDidLoad для UICollectionViewController

Я пытаюсь адаптировать использование UICollectionViewController, который я заполняю массивом локальных изображений, чтобы получить изображения из Parse.

Пока это довольно просто. Мой NSArray много раз заполняется одним и тем же локальным образом:

testImages = [NSArray arrayWithObjects: @"thumbnail.jpg", @"thumbnail.jpg", @"thumbnail.jpg", @"thumbnail.jpg", @"thumbnail.jpg", @"thumbnail.jpg", @" thumbnail.jpg", @"thumbnail.jpg", @"thumbnail.jpg", @"thumbnail.jpg", @"thumbnail.jpg", @"thumbnail.jpg", @"thumbnail.jpg", @"thumbnail .jpg", @"thumbnail.jpg", @"thumbnail.jpg", nil];

В collectionView:cellForItemAtIndexPath: я настраиваю свою ячейку (из раскадровки):

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    // Set up cell identifier that matches the Storyboard cell name
    static NSString *identifier = @"Cell";    
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];

    // Configure the cell to show photo thumbnail
    UIImageView *testImageView = (UIImageView *)[cell viewWithTag:100];

    testImageView.image = [UIImage imageNamed:[testImages objectAtIndex:indexPath.row]];

    return cell;
}

Это работает и выглядит так:

UICollectionViewController с массивом локальных изображений

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

Я пытаюсь сделать это с помощью метода viewDidLoad:

PFQuery *query = [PFQuery queryWithClassName:@"Photo"];

PFUser *user = [PFUser currentUser];
[query whereKey:@"user" equalTo:user];
[query orderByAscending:@"createdAt"];
[query setCachePolicy:kPFCachePolicyNetworkOnly];


[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    if (!error) {
        // The find succeeded.
        NSLog(@"Successfully retrieved %d photos.", objects.count);
        testImages = [NSMutableArray arrayWithArray:objects];
        NSLog(@"# Images: %d", [testImages count]);

        // Do something with the found objects
        for (PFObject *object in objects) {                
            NSLog(@"Object Name: %@", object.objectId);
        }


    } else {
        // Log details of the failure
        NSLog(@"Error: %@ %@", error, [error userInfo]);
    }
}];

Дело в том, что я каждый раз получаю пустой массив. Я предполагаю, что, поскольку это выполняется в блоке в фоновом режиме, как только collectionView:numberOfItemsInSection: запрашивает количество элементов в массиве «testImages», я всегда получаю 0 элементов.

Когда UICollectionViewController хочет использовать информацию из массива для заполнения ячеек, там ничего нет.

Я не знаю, размещаю ли я свой код в неправильном месте или использую неправильный запрос.

Вы можете получить мою ошибку здесь?

Любая обратная связь будет принята с благодарностью.


person Juan González    schedule 04.07.2013    source источник
comment
В блоке завершения вызов метода reloadData для вашего collectionView заполнит ячейки. Я не уверен, что это тот ответ, который вы ищете, но он сработает   -  person gg13    schedule 05.07.2013
comment
Привет, @gg13, спасибо, все получилось, но это кажется немного странным. Я печатаю количество извлеченных объектов (с помощью NSLog) и сначала получаю 0, а затем после reloadData получаю нужное количество. Это обычный способ работы с UICollectionViewController? Это кажется странным, хотя, должен признаться, я еще не эксперт.   -  person Juan González    schedule 05.07.2013
comment
Происходит то, что когда вы впервые печатаете количество извлеченных объектов, Parse не завершил запрос для объектов, поэтому возвращает 0. В том же духе представление коллекции пытается настроить себя с помощью пустого массива, вот почему вы ничего не получаете. Затем, поскольку вы вызываете reloadData в блоке завершения, запрос завершен, поэтому у вас есть объекты, и представление коллекции может заполниться само. На самом деле это ничем не отличается от UITableView, поскольку они также не смогут заполнить себя без каких-либо объектов.   -  person gg13    schedule 06.07.2013


Ответы (1)


наконец-то у меня что-то работает. Отзывы @gg13 сыграли ключевую роль в решении проблемы с пустым массивом.

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

Я поставил свой запрос на новый метод:

- (void)queryForTable
{
    PFQuery *query = [PFQuery queryWithClassName:@"Photo"];
    PFUser *user = [PFUser currentUser];
    [query whereKey:@"user" equalTo:user];
    [query orderByAscending:@"createdAt"];
    [query setCachePolicy:kPFCachePolicyNetworkOnly];

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            // The find succeeded.
            NSLog(@"Successfully retrieved %d photos.", objects.count);

            [self.collectionView reloadData];

            gridImages = [[NSMutableArray alloc] initWithCapacity:objects.count];

            // Do something with the found objects
            for (PFObject *object in objects) {

                PFFile *thumbnail = [object objectForKey:@"thumbnail"];
                [thumbnail getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
                    if (!error) {
                        // Now that the data is fetched, update the cell's image property with thumbnail

                        NSLog(@"Fetching image..");

                        [gridImages addObject:[UIImage imageWithData:data]];

                        NSLog(@"Size of the gridImages array: %d", [gridImages count]);

                    } else {
                        // Log details of the failure
                        NSLog(@"Error: %@ %@", error, [error userInfo]);
                    }
                }];
            }
        } else {
            // Log details of the failure
            NSLog(@"Error: %@ %@", error, [error userInfo]);
        }
    }];
}

Что я вызываю на viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [self queryForTable];
}

Затем я изменил свой метод collectionView:cellForItemAtIndexPath: на это:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    // Set up cell identifier that matches the Storyboard cell name
    static NSString *identifier = @"Cell";    
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];

    // Configure the cell to show photo thumbnail
    UIImageView *imageView = (UIImageView *)[cell viewWithTag:100];

    //NSLog(@"testImages: %@", [testImages objectAtIndex:indexPath.row]);
    imageView.image = [UIImage imageNamed:@"placeholder.jpg"];

    imageView.image = [gridImages objectAtIndex:indexPath.row];

    return cell;
}

И пока это работает. Приложение получает изображения из Parse, и это выглядит так:

UICollectionViewController с анализом изображений

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

Я уверен, что Parse рано или поздно создаст свой собственный UICollectionViewController, как они сделали с UITableViewController, и все станет еще лучше.

Как было сказано ранее, спасибо за отзыв, я оставлю это здесь на случай, если кто-то еще столкнется с той же проблемой и, конечно же, открыт для отзывов и предложений.

Ваше здоровье,

person Juan González    schedule 06.07.2013