具有目标操作的单元格上的 iOS UIButton,单元格未在 (id)sender 中更新

标签 ios iphone objective-c uitableview uibutton

我有一个带有 UIImage 内容的自定义单元格 UIButton,带有目标操作选择器 pushToImageDetailViewController: 它将 View 推送到图像的另一个详细 View 。 我在他的委托(delegate)方法中从 UIPickerView 创建单元格,然后我在服务器上上传图像,然后存储到文档路径库。我需要在自定义单元格 attachmentId 上编辑属性,这就是问题所在。

- (void)pushToImageDetailViewController:(id)sender
{
    [MessageLoader invalidate];
    [self.messageInputFieldView resignFirstResponder];

    while (sender && ![sender isKindOfClass:[MessageTableViewCell class]]) {
        sender = [sender superview];
    }
    if (!sender) {
        NSLog(@"Error by getting cell from superview of button");
    } else {
        MessageTableViewCell *cell = (MessageTableViewCell *) sender;
        ImageDetailViewController *imageDetailView = [[ImageDetailViewController alloc] init];
        imageDetailView.sender = cell.sender;
        imageDetailView.attachmentId = cell.attachmentId;
        [[self navigationController] pushViewController:imageDetailView animated:YES];
   }
}

这段代码我在 block 中,因此自身属性上有 weakSelf,重要的是刷新单元格语句,indexPathForRow 触发了 cellForRowAtIndexPath,在这条消息中我有 NSLog 和正确的 ID 进入这个消息。

NSMutableDictionary *messagesFromCollection = [weakSelf.messageDetailViewController.messages objectAtIndex:weakSelf.index];
[[[messagesFromCollection objectForKey:@"attachments"] firstObject] setObject:[fileId copy] forKey:@"id"];
// refresh concret cell
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:weakSelf.index inSection:0];
[weakSelf.messageDetailViewController.messagesTableView reloadRowsAtIndexPaths:@[indexPath] 
                                                                withRowAnimation:UITableViewRowAnimationNone];

在 cellForRowAtIndex 中,将 self.messages 中的 ID、字典数组集合分配给单元格属性 attachmentId,但在 pushToImageDetail 中,我在预生成之前有旧 ID。

    cell.attachmentId = [attachmentInfo objectForKey:@"id"];
    [cell.attachmentView addTarget:self action:@selector(pushToImageDetailViewController:)     forControlEvents:UIControlEventTouchUpInside];
    [cell.attachmentView setImage:attachmentImage forState:UIControlStateNormal];
    [cell.bgImageView addSubview:cell.attachmentView];
    [cell.contentView addSubview:cell.attachmentView];

问题是 imageDetailView.attachmentId = cell.attachmentId 中的 id 分配了旧的 id(带有图像 id 的错误绑定(bind)图像细节),而在 cellForRow 中是新的实际 cell.attachmentId = [attachmentInfo objectForKey:@"id"]。我不知道这怎么可能。

这里是 cellForRow:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
NSDictionary *messagesFromDictionary = [self.messages objectAtIndex:indexPath.row];
NSString *message = [messagesFromDictionary objectForKey:@"message"];
UIImage *attachmentImage = [self.attachments objectAtIndex:indexPath.row];
NSString *time = [NSString formattedTime:[messagesFromDictionary objectForKey:@"posted_date"]];
NSString *beforeSender = [self beforeSender:indexPath];

static NSString *CellIdentifier;
if ([message isEqualToString:@""]) {
    CellIdentifier = @"AttachmentCellIdentifier";
} else {
    CellIdentifier = @"MessageCellIdentifier";
}

MessageTableViewCell *cell = (MessageTableViewCell *)
                            [self.messagesTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
    cell = [[MessageTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}

cell.sender = [messagesFromDictionary objectForKey:@"user_id"];
cell.backgroundColor = [UIColor clearColor];

UIImage *bgImage = nil;
UIImage *arrowImage = nil;
CGRect messageFrame = {};
CGRect bgImageFrame = {};
CGRect profilePictureFrame = {};

CGRect timeFrame = {};
CGRect arrowFrame = {};

// Log message level 3
//[NSString LogMessages:[NSString stringWithFormat:@"S:%f, %f M: %@", messageFrame.size.width, messageFrame.size.height, message] :3];

/*
 !!!! width and height for all cells !!!!
 */

cell.timeLabel.text = [NSString stringWithFormat:@"%@", time];
[cell.timeLabel sizeToFit];
timeFrame.size.height += cell.timeLabel.frame.size.height; // MUST BE DEFINED BEFORE Y COORDINATE
timeFrame.size.width += cell.timeLabel.frame.size.width;
profilePictureFrame.size.width += AVATAR;
profilePictureFrame.size.height += AVATAR;

if ([CellIdentifier isEqualToString:@"MessageCellIdentifier"]) {
    cell.messageContentView.text = message;
    CGSize  textSizeFrame = { 320.0 - 5*PADDING - AVATAR - cell.timeLabel.frame.size.width - RESERVE - 12, CGFLOAT_MAX};
    messageFrame.size = [message sizeForText:textSizeFrame withFontSize:MESSAGE_FONTSIZE];
    messageFrame.size.width += RESERVE;
    messageFrame.origin.x += PADDING;
    messageFrame.origin.y += PADDING;

    bgImageFrame.origin.y += PADDING;
    bgImageFrame.size.width = messageFrame.size.width + 3*PADDING  + cell.timeLabel.frame.size.width;
    bgImageFrame.size.height += messageFrame.size.height + 2*PADDING;

    arrowFrame.size.width += MESSAGE_ARROW_WIDTH;
    arrowFrame.size.height += MESSAGE_ARROW_HEIGHT;
    arrowFrame.origin.y += bgImageFrame.size.height/2;

    profilePictureFrame.origin.y += PADDING;

    // must be defined after bgImageFrame height, timeFrame height
    timeFrame.origin.y += bgImageFrame.size.height/2 - cell.timeLabel.frame.size.height/2;
    // must be defined after messageFrame width
    timeFrame.origin.x += messageFrame.size.width + PADDING;
} else if ([CellIdentifier isEqualToString:@"AttachmentCellIdentifier"]) {
    // prepare fields to download attachment from server
    NSArray *attachmentsFromDict = [messagesFromDictionary objectForKey:@"attachments"];
    NSDictionary *attachmentInfo = [attachmentsFromDict objectAtIndex:0];
    NSLog(@"id from cell %@", [attachmentInfo objectForKey:@"id"]);
    cell.attachmentId = [attachmentInfo objectForKey:@"id"];

    bgImageFrame.size.height = attachmentImage.size.height;
    bgImageFrame.size.width = attachmentImage.size.width;

    timeFrame.origin.y += PADDING;
    // must be defined after bgImageFrame width, timeFrame width
    timeFrame.origin.x += bgImageFrame.size.width/2 - timeFrame.size.width/2;

    [cell.attachmentView addTarget:self action:@selector(pushToImageDetailViewController:) forControlEvents:UIControlEventTouchUpInside];
    [cell.attachmentView setImage:attachmentImage forState:UIControlStateNormal];
    cell.attachmentView.tag = indexPath.row;
    [cell.bgImageView addSubview:cell.attachmentView];
    [cell.contentView addSubview:cell.attachmentView];
}

// X, Y positions
if ([cell.sender isEqualToString:[[user userInfo] objectForKey:@"id"]]) { // left aligned (Sender)
    bgImageFrame.origin.x = 320 - bgImageFrame.size.width - PADDING;
    bgImage = [UIImage imageNamed:@"msg_sender.png"];

    arrowFrame.origin.x += 320 - PADDING - 2;
    arrowImage = [UIImage imageNamed:@"sender_arrow.png"];

    cell.messageContentView.backgroundColor = [UIColor  whiteColor];
    cell.timeLabel.backgroundColor = [UIColor  whiteColor];
} else { // right aligned (Receiver)
    bgImageFrame.origin.x += AVATAR + 2*PADDING;
    bgImage = [UIImage imageNamed:@"msg_receiver.png"];

    arrowFrame.origin.x += AVATAR + 2*PADDING - MESSAGE_ARROW_WIDTH + 2;
    arrowImage = [UIImage imageNamed:@"receiver_arrow.png"];

    profilePictureFrame.origin.x += PADDING;

    cell.messageContentView.backgroundColor = [UIColor colorWithRed:255/255.0 green:242/255.0 blue:254/255.0 alpha:1];
    cell.timeLabel.backgroundColor = [UIColor colorWithRed:255/255.0 green:242/255.0 blue:254/255.0 alpha:1];
}

if ([CellIdentifier isEqualToString:@"AttachmentCellIdentifier"]) {
        cell.attachmentView.frame = CGRectMake(IMAGE_WIDTH_PADDING + bgImageFrame.origin.x,
                                               IMAGE_TOP_PADDING + timeFrame.size.height,
                                               bgImageFrame.size.width - 2*IMAGE_WIDTH_PADDING,
                                               bgImageFrame.size.height - IMAGE_BOTTOM_PADING - timeFrame.size.height);
}

if (
    (![cell.sender isEqualToString:beforeSender]) &&
    (![cell.sender isEqualToString:[[user userInfo] objectForKey:@"id"]])
   )
{
    [cell.profilePicture setFrame:profilePictureFrame];

    // ==== load user avatar
    cell.profilePicture.layer.masksToBounds = YES;
    float radius = AVATAR/2;
    CAShapeLayer *circle = [CAShapeLayer layer];
    circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(KAPPA, KAPPA, 2.0*radius, 2.0*radius)
                                             cornerRadius:radius].CGPath;
    [cell.profilePicture.layer setMask:circle];
    cell.profilePicture.image = [user getMyContactAvatar:cell.sender :existingContacts];
    [cell.contentView addSubview:cell.profilePicture];
} else {
    cell.profilePicture.frame = CGRectZero;
    cell.profilePicture.image = nil;
    [cell.profilePicture removeFromSuperview];
}

cell.messageContentView.frame = messageFrame;

[cell.bgImageView setFrame:bgImageFrame];
cell.bgImageView.image = bgImage;

cell.timeLabel.frame = timeFrame;
cell.textLabel.numberOfLines = 0;

cell.arrowView.frame = arrowFrame;
cell.arrowView.image = arrowImage;

cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}

最佳答案

通过分配到 UIButton 上的标记属性 indexPath.row 来解决,但仍然不明白为什么我以前的方法不起作用。

- (void)pushToImageDetailViewController:(id)sender
{
[MessageLoader invalidate];
[self.messageInputFieldView resignFirstResponder];

UIButton *imageButton = (UIButton *)sender;
MessageTableViewCell *cell = (MessageTableViewCell *) [self tableView:self.messagesTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:imageButton.tag inSection:0]];        
ImageDetailViewController *imageDetailView = [[ImageDetailViewController alloc] init];
imageDetailView.sender = cell.sender;
imageDetailView.attachmentId = cell.attachmentId;
[[self navigationController] pushViewController:imageDetailView animated:YES];
}

关于具有目标操作的单元格上的 iOS UIButton,单元格未在 (id)sender 中更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19926966/

相关文章:

ios - 着色器中的多个纹理单元与多个半透明纹理网格 - 性能

iphone - 将 native iphone 相机缩放 slider 和 youtube 播放器 Controller 添加到我的应用程序

iphone - 适用于 iOS 的可视化嵌套树状控件

iphone - UIImage 在下载时损坏

iphone - Cocoa touch - 内存管理

ios - 缓存模型(DTO)类供以后使用

ios - 无法添加字体为 Avenir Next Condensed 的属性字符串 [Swift 3]

iphone - 使用NSFastEnumeration时检测到最后一个元素?

ios - 使用 GoogleService-Info.plist 配置适用于 iOS 应用程序的 Google 分析时出错

ios - 添加 NSDictionary 作为 NSDictionary 键的值