Как установить представление аксессуара ячейки табличного представления для сохранения ранее инициализированного UIImageView?

Скажем, у меня есть свойство, по моему мнению, контроллер, определенный следующим образом:

@property (nonatomic, retain) UIImageView *checkmarkOffAccessoryView;

Я @synthesize это в реализации, release это в -dealloc и инициализируйте его в -viewDidLoad следующим образом:

self.checkmarkOffAccessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];

Пока все хорошо.

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

  1. Представление аксессуара только одной ячейки показывает изображение
  2. Приложение замораживания UI.

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

Вот то, как я использую инициализированное свойство со своей ячейкой:

- (UITableViewCell *) tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // initialize or dequeue cell...

    if (condition)
        cell.accessoryView = self.checkmarkOffAccessoryView;
    else
        cell.accessoryView = nil;
}

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

Если я инициализирую UIImageView инстанцируйте непосредственно в методе делегата, я получаю все удовлетворяющие условие ячейки, показывающие вспомогательное представление, и я не испытываю замораживание UI:

- (UITableViewCell *) tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    // initialize or dequeue cell...

    if (condition)
        cell.accessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];
    else
        cell.accessoryView = nil;
}

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

Это походит на ячейку accessoryView свойство должно просто увеличить retain количество self.checkmarkOffAccessoryView но кажется, что я пропускаю некоторую деталь.

Что я пропустил? Спасибо за Ваш совет.

Править

Я думаю что:

self.checkmarkOffAccessoryView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]] autorelease];

совпадает с:

UIImageView *uncheckedView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"checkmarkOff.png"]];
self.checkmarkOffAccessoryView = uncheckedView;
[uncheckedView release];

Так или иначе я испытываю тот же признак замораживания.

7
задан Alex Reynolds 6 July 2010 в 23:57
поделиться

4 ответа

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

Кстати, ваша консоль, вероятно, при зависании показывает ошибку BAD_ACCESS. Если вы включите NSZombieEnabled, я думаю, вы увидите, что он обращается к освобожденному UIImage.

0
ответ дан 7 December 2019 в 03:10
поделиться

может это поможет

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    static NSString *CellIdentifier = @"ShoppingListCell";

    HSShoppingListCell *cell = (HSShoppingListCell *)[aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"ShoppingListCell" 
                                                                            owner:self 
                                                                        options:nil];
        cell = shoppingListCell;
    }

    ShoppingListItem *theItem = nil;
    theItem = [self.fetchedResultsController objectAtIndexPath:indexPath];

    UIImage *selected         = [UIImage imageNamed:@"listBullet_checked.png"];
    UIImage *notSelected    = [UIImage imageNamed:@"listBullet.png"];

    cell.imageView.image = ([theItem.checkedOff boolValue] ? selected : notSelected); 

    cell.shoppingListLabel.text = theItem.productName;
    [cell.shoppingListLabel setFont:[UIFont fontWithName:@"Marker Felt" size:26.0]];
    return cell;
}

- (void)toggleCellImage:(NSIndexPath *)indexPath
{
    ShoppingListItem *item  = [self.fetchedResultsController objectAtIndexPath:indexPath];

    item.checkedOff = ([item.checkedOff boolValue] ? [NSNumber numberWithBool:NO] : [NSNumber numberWithBool:YES]);

    [HSCoreDataUtilities saveContext:item.managedObjectContext];
    [self.tableView reloadData];
}

#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    [self toggleCellImage:indexPath];
    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
0
ответ дан 7 December 2019 в 03:10
поделиться

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

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

Используя ваш текущий метод (без сохраненного UIImage), вы можете сделать:

-(UIImageView *) makeCheckmarkOffAccessoryView
{
    return [[[UIImageView alloc] initWithImage:
        [UIImage imageNamed:@"checkmarkOff.png"]] autorelease];
}

А затем сделать

cell.accessoryView = [self makeCheckmarkOffAccessoryView];

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

Чтобы расширить сделку только для одного места, представьте, что вы добавляете UIView в два места одновременно.

Что [ob removeFromSuperview] сделает для этого объекта? Удалит ли вид из обоих мест? Только от одного из них? Какое значение будет возвращено, когда вы запросите [ob superview]? Очевидно, что пользовательский интерфейс не предназначен для обработки того, о чем вы просите.

9
ответ дан 7 December 2019 в 03:10
поделиться

Сокращение вашего случая до самого необходимого (я собирался предложить поместить два «тонких» объекта UIView вокруг UIImageView ...) , Я обнаружил, что это, скорее всего, невозможно.

Создайте 2 пустых объекта UIView в IB, подключите их к bareView1 и bareView2 . Тогда

UIImageView *imageView = [[UIImageView alloc]
                      initWithImage:[UIImage imageNamed:@"test.png"]];
[bareView1 addSubview:imageView]; // it shows either here ...
[bareView2 addSubview:imageView]; // ... or here

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

При переносе второго addSubview только UIImageView перескакивает с bareView1 на bareView2 .

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

0
ответ дан 7 December 2019 в 03:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: