PFImageView не работает на подклассе PFCollectionViewCell

У меня проблемы с получением моего подкласса PFCollectionViewCell хорошо играть с PFImageView, Я использую раскадровки для установки моего PA_ProfileCollectionViewCell.

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

Мой желаемый результат: иметь собственную ячейку (подкласс PFCollectionViewCell) для использования -collectionView:cellForItemAtIndexPath:object:

Проблема: мое пользовательское свойство PFImageView *imageThumb (на моем подклассе PFCollectionViewCell) не отвечает на loadInBackground: или же setFile: которые являются двумя методами на PFImageView учебный класс.


Вот мой код для ясности:

- Мой пользовательский PFCollectionViewCell: ProfileCollectionViewCell

@interface PA_ProfileCollectionViewCell : PFCollectionViewCell
@property (weak, nonatomic) IBOutlet PFImageView *imageThumb;
@end

- Зарегистрируйте пользовательский класс в viewDidLoad

- (void)loadView {
    [super loadView];
    [self.collectionView registerClass:[PA_ProfileCollectionViewCell class]
            forCellWithReuseIdentifier:_cellIdentifier];
}

- Настройте ячейку в collectionView:cellForItemAtIndexPath:object
Вот где возникает основная проблема. Мое значение для ячейки успешно окрашивается в DarkGray, в соответствии с cell.backgroundColor: вызов, но все попытки присвоить изображение моему imageThumb терпят неудачу. Обратите внимание в исходном коде ниже, что мой imageThumb не отвечает на селекторы loadInBackground или же setFile, который поставляется с PFImageView,

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath
                                  object:(PFObject *)object {


    PA_ProfileCollectionViewCell *cell = (PA_ProfileCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:_cellIdentifier
                                                                                                                   forIndexPath:indexPath];
    cell.backgroundColor = [UIColor grayColor];

    // Load the photo
    PFFile *pingThumb = [object objectForKey:@"imageMediumFile"];
    if (pingThumb){

        BOOL canLoadInBackground = [cell.imageThumb respondsToSelector:@selector(loadInBackground:)];
        BOOL canSetFile = [cell.imageThumb respondsToSelector:@selector(setFile:)];

        NSLog(@"can cell.imageThumb loadInBackground? : %hhd", canLoadInBackground);
        NSLog(@"can cell.imageThumb setFile? : %hhd", canSetFile);

        [cell.imageThumb setFile:pingThumb];
        [cell.imageThumb loadInBackground:^(UIImage *image, NSError *error) {
            if(!error){
                NSLog(@"CODE WON'T REACH THIS POINT.");
                NSLog(@"loadInBackground doesn't exist on cell.imageThumb)");
                [UIView animateWithDuration:0.2f animations:^{
                    cell.imageThumb.alpha = 1.0f;
                }];
            }
        }];

    }

    return cell;
}

Выход всех NSLog() утверждения в фрагменте кода выше:

can cell.imageThumb loadInBackground? : 0 (NO)
can cell.imageThumb setFile? : 0 (NO)

Другие вещи, которые я пробовал:

Я выбрал исходный код ParseUIDemo, но все их реализации используют запас PFCollectionViewCell без каких-либо настроек или подклассов, поэтому я попытался адаптировать свой проект, чтобы использовать их подход, но я так и не смог добиться успеха.

Я прочитал этот ответ на SO, что заставило меня попробовать пролистать мой cell.contentViews.subviews а также cell.subviews Ищу PFImageView Ни одна попытка не была успешной:

// [DIDN'T WORK]
for (UIView *subview in cell.contentView.subviews) {
    if ([subview isKindOfClass:[PFImageView class]]) {
        NSLog(@"Yay! I found a PFImageView"); // Never gets called
        break;
    }
}

Затем я попробовал этот ответ на SO, и это заставило меня попробовать захватить экземпляр PFImageView из моей раскадровки с помощью тега, который был одинаково неудачным.

PFImageView *photoView = (PFImageView *)[cell.contentView viewWithTag:242];
if(!photoView) NSLog(@"Can't find PFImageView with tag in Storyboards");
// -> Can't find PFImageView with tag in Storyboards

Наконец, я передал каждую возможную комбинацию classNames всем методам, которые требуют classNames в PFQueryCollectionViewController, Например: я попробовал приведенные ниже строки кода, где я поменял местами все экземпляры CLASSNAMEHERE PA_ProfileCollectionViewCell, UICollectionViewCell а также PFCollectionViewCell, все с равным количеством FAIL:

// the cell (with casting)
CLASSNAMEHERE *cell = (CLASSNAMEHERE *)[cv dequeueReusableCellWithReuseIdentifier:...];

// the cell (without casting)
CLASSNAMEHERE *cell = [cv dequeueReusableCellWithReuseIdentifier:...];

// registering the class
[self.collectionView registerClass:[CLASSNAMEHERE class]
        forCellWithReuseIdentifier:_cellIdentifier];

Обновление № 01:

По предложению пользователя @soulshined я попытался пропустить setFile: вызов, так как он не появляется в API через документы Parse (но я никогда не получал ошибку или unrecognized selector error при использовании), поэтому я попробовал приведенный ниже фрагмент кода, но не повезло (обратите внимание, как setFile: был заменен на .file:

cell.imageThumb.file = pingThumb;
//[cell.imageThumb setFile:pingThumb];
[cell.imageThumb loadInBackground:^(UIImage *image, NSError *error) {

    if(!error){
        NSLog(@"CODE WON'T REACH THIS POINT.");
        NSLog(@"loadInBackground doesn't exist on cell.imageThumb)");
        [UIView animateWithDuration:0.2f animations:^{
            cell.imageThumb.alpha = 1.0f;
        }];
    }
}];

Обновление № 02

Опять же, по предложению @soulshined, я воспользовался советом, приведенным здесь, и изменил свой PFImageView *imageThumb к UIImageView *imageThumb и попытался присвоить NSdata, возвращенный из getDataInBackground:withBlock: вместо этого вот мой фрагмент кода (обратите внимание, что я получаю вывод "Got Data!" на консоль, но изображения все еще не отображаются):

// pingThumb is a PFFile
[pingThumb getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
        if (!error) {
            NSLog(@"Got data");
            UIImage *image = [UIImage imageWithData:data];
            [cell.imageThumb setImage:image];
        }
    }];

Так может кто-нибудь придумать шаг, который мне не хватает? Почему так сложно получить PFImageView загрузить с подклассом PFCollectionViewCell?

Заранее спасибо всем, кто нашел время, чтобы помочь мне!

2 ответа

Решение

Проблема, с которой вы сталкиваетесь, заключается в том, что вы регистрируете класс в своем -viewDidLoad метод, но вы настраиваете свою ячейку через ячейку Prototype в раскадровке.

Если вы обратитесь к разделу "Повторное использование ячеек и представлений" здесь, вы прочтете (выделение мое):

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

Вот почему ваш PFImageViews не вела себя, потому что вы разрывали соединения Prototype, которые вы установили в раскадровке после -registerClass:forCellWithReuseIdentifier: был вызван, и ваши PFImageViews были потеряны в режиме ожидания.

Итак, чтобы решить вашу проблему, просто УДАЛИТЕ -registerClass:forCellWithReuseIdentifier с вашей точки зрения контроллера.

Эт вуаля, проблема решена...

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

// Not needed when using Prototype cells in Storyboards!
[self.collectionView registerClass:[PA_ProfileCollectionViewCell class]
            forCellWithReuseIdentifier:_cellIdentifier];

После того как вы удалите код registerClass, код, который вы работаете с вашим PFImageView в приведенных выше примерах кода вопрос должен работать просто отлично.

Надеюсь это поможет!


На заметку о том, что при создании экземпляра в -collectionView:cellForItemAtIndexPath:object

// this is all you need
SomeCustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:_cellId]; 

// the casting example below is redundant and unnecessary, stick with the top example 
SomeCustomCell *cell = (SomeCustomCell *)[collectionView dequeueReusableCellWithReuseIdentifier:_cellId];  

PA_ProfileCollectionViewCell имеет файл NIB? Если ДА, вам нужно зарегистрировать файл NIB, а не Class. Попробуйте что-то вроде этого:

// LOAD UP THE NIB FILE FOR THE CELL
UINib *nib = [UINib nibWithNibName:@"PA_ProfileCollectionViewCell" bundle:nil];

// REGISTER THE NIB FOR THE CELL WITH THE TABLE
[self.collectionView registerNib:nib forCellWithReuseIdentifier:@"CustomNibCellId"];
Другие вопросы по тегам