【发布时间】:2014-08-15 15:30:38
【问题描述】:
我在这里绝对需要帮助...
我正在创建一个自定义 UITableViewCell 以编程方式将子视图添加到单元格的内容视图。
首先,它创建可重用单元格或获取内容视图(如果已存在)。 然后它设置图片。
#import "NSString+MD5.h"
#import "UIImageView+Network.h"
(....)
#define PHOTO_TAG 1
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"CustomCell";
PELOTFriendTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
UIImageView *photo;
if (cell == nil) {
NSLog(@"Creating cell");
cell = [[PELOTFriendTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
photo = [[UIImageView alloc] initWithFrame:CGRectMake(42, 17, 55, 55)];
photo.tag = PHOTO_TAG;
photo.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:photo];
} else {
NSLog(@"Reusing cell");
photo = (UIImageView *)[cell.contentView viewWithTag:PHOTO_TAG];
NSLog(@"%@",photo);
}
(....)
if (friend.pictureUrl==nil) {
NSLog(@"Setting default photo");
[photo setImage:[UIImage imageNamed:@"user-picture.png"]];
} else {
NSLog(@"Setting photo from URL");
[photo loadImageFromURL:[[NSURL alloc]initWithString:friend.pictureUrl] placeholderImage:[UIImage imageNamed:@"user-picture.png"] cachingKey: [friend.pictureUrl MD5Hash]];
}
NSLog 告诉我
photo = (UIImageView *)[cell.contentView viewWithTag:PHOTO_TAG];
有时返回 UITableViewCellContentView* 而不是 UIImageView* 并且我收到“无法识别的选择器”错误。
2014-08-15 11:41:27.747 MyApp[79972:60b] <UIImageView: 0xc722840; frame = (60 17; 55 90); opaque = NO; autoresize = LM+H; userInteractionEnabled = NO; tag = 1; layer = <CALayer: 0xc7228c0>>
2014-08-15 11:41:27.750 MyApp[79972:60b] <UITableViewCellContentView: 0xc840c90; frame = (0 0; 338 79.5); tag = 1; gestureRecognizers = <NSArray: 0xc8409d0>; layer = <CALayer: 0xc840b60>>
第一个是用 [photo setImage] 初始化的图像,第二个是用 [photo loadImageFromURL] 初始化的图像。
这让我发疯。 有什么想法吗?
Tks,
编辑 1
第一次渲染表格时,它可以工作。当我调用 [tableview reloadData] 并调用 [cell.contentView viewWithTag:PHOTO_TAG] 时会出现问题
编辑 2
可重现的代码是:
PELOTReproduceBugViewController.h
#import <UIKit/UIKit.h>
@interface PELOTReproduceBugViewController : UIViewController <UITableViewDelegate>
@property (nonatomic,retain) IBOutlet UITableView *friendsTableView;
@property (nonatomic,retain) IBOutlet UIButton *reloadButton;
-(IBAction)reload:(id)sender;
@end
PELOTReproduceBugViewController.m
#import "PELOTReproduceBugViewController.h"
@implementation PELOTReproduceBugViewController
@synthesize friendsTableView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(IBAction)reload:(id)sender {
NSLog(@"reload!");
[friendsTableView reloadData];
}
- (void)viewDidLoad
{
NSLog(@"viewDidLoad!");
[super viewDidLoad];
friendsTableView.delegate = self;
friendsTableView.backgroundColor = [UIColor clearColor];
friendsTableView.opaque = NO;
friendsTableView.backgroundView = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)popViewToGetBack:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
NSLog(@"** numberOfSectionsInTableView");
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(@"** numberOfRowsInSection");
return 3;
}
#define PHOTO_TAG 1
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int row = (int) [indexPath row];
static NSString *cellIdentifier = @"CustomCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSLog(@"** 1[%d]",row);
UIImageView *photo=nil;
if (cell == nil) {
NSLog(@"Creating cell");
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentView.tag = indexPath.row;
photo = [[UIImageView alloc] initWithFrame:CGRectMake(42, 17, 55, 55)];
photo.tag = PHOTO_TAG;
photo.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[cell.contentView addSubview:photo];
NSLog(@"** 2a[%d]: %@",row,photo);
} else {
photo = (UIImageView *)[cell.contentView viewWithTag:PHOTO_TAG];
NSLog(@"** 2b[%d]: %@",row,photo);
}
// Configure the cell...
NSLog(@"** 3 %d",row);
[photo setImage:[UIImage imageNamed:@"user-picture.png"]];
NSLog(@"** 4");
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
输出是:
2014-08-16 17:46:43.432 BugApp[83096:60b] viewDidLoad!
2014-08-16 17:46:43.447 BugApp[83096:60b] ** numberOfSectionsInTableView
2014-08-16 17:46:43.450 BugApp[83096:60b] ** numberOfRowsInSection
2014-08-16 17:46:43.452 BugApp[83096:60b] ** 1[0]
2014-08-16 17:46:43.453 BugApp[83096:60b] Creating cell
2014-08-16 17:46:43.455 BugApp[83096:60b] ** 2a[0]: <UIImageView: 0xc8b23f0; frame = (42 17; 55 55); autoresize = LM+H; userInteractionEnabled = NO; tag = 1; layer = <CALayer: 0xc8b2470>>
2014-08-16 17:46:43.456 BugApp[83096:60b] ** 3 0
2014-08-16 17:46:43.459 BugApp[83096:60b] ** 4
2014-08-16 17:46:43.460 BugApp[83096:60b] ** 1[1]
2014-08-16 17:46:43.461 BugApp[83096:60b] Creating cell
2014-08-16 17:46:43.463 BugApp[83096:60b] ** 2a[1]: <UIImageView: 0xc8b5150; frame = (42 17; 55 55); autoresize = LM+H; userInteractionEnabled = NO; tag = 1; layer = <CALayer: 0xc8b51d0>>
2014-08-16 17:46:43.464 BugApp[83096:60b] ** 3 1
2014-08-16 17:46:43.465 BugApp[83096:60b] ** 4
2014-08-16 17:46:43.467 BugApp[83096:60b] ** 1[2]
2014-08-16 17:46:43.468 BugApp[83096:60b] Creating cell
2014-08-16 17:46:43.470 BugApp[83096:60b] ** 2a[2]: <UIImageView: 0xc7ef9a0; frame = (42 17; 55 55); autoresize = LM+H; userInteractionEnabled = NO; tag = 1; layer = <CALayer: 0xc7eb7a0>>
2014-08-16 17:46:43.471 BugApp[83096:60b] ** 3 2
2014-08-16 17:46:43.472 BugApp[83096:60b] ** 4
2014-08-16 17:46:48.658 BugApp[83096:60b] reload!
2014-08-16 17:46:48.658 BugApp[83096:60b] ** numberOfSectionsInTableView
2014-08-16 17:46:48.659 BugApp[83096:60b] ** numberOfRowsInSection
2014-08-16 17:46:48.660 BugApp[83096:60b] ** 1[0]
2014-08-16 17:46:48.661 BugApp[83096:60b] ** 2b[0]: <UIImageView: 0xc8b23f0; frame = (60 17; 55 90); opaque = NO; autoresize = LM+H; userInteractionEnabled = NO; tag = 1; layer = <CALayer: 0xc8b2470>>
2014-08-16 17:46:48.661 BugApp[83096:60b] ** 3 0
2014-08-16 17:46:48.661 BugApp[83096:60b] ** 4
2014-08-16 17:46:48.662 BugApp[83096:60b] ** 1[1]
2014-08-16 17:46:48.662 BugApp[83096:60b] ** 2b[1]: <UITableViewCellContentView: 0xc8b4df0; frame = (0 0; 338 79.5); tag = 1; gestureRecognizers = <NSArray: 0xc8b5100>; layer = <CALayer: 0xc8b4f60>>
2014-08-16 17:46:48.663 BugApp[83096:60b] ** 3 1
2014-08-16 17:46:48.663 BugApp[83096:60b] -[UITableViewCellContentView setImage:]: unrecognized selector sent to instance 0xc8b4df0
2014-08-16 17:46:48.678 BugApp[83096:60b] WARNING: GoogleAnalytics 3.07 void GAIUncaughtExceptionHandler(NSException *) (GAIUncaughtExceptionHandler.m:49): Uncaught exception: -[UITableViewCellContentView setImage:]: unrecognized selector sent to instance 0xc8b4df0
2014-08-16 17:46:53.684 BugApp[83096:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCellContentView setImage:]: unrecognized selector sent to instance 0xc8b4df0'
*** First throw call stack:
(
0 CoreFoundation 0x021a11e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x01f208e5 objc_exception_throw + 44
2 CoreFoundation 0x0223e243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x0219150b ___forwarding___ + 1019
4 CoreFoundation 0x021910ee _CF_forwarding_prep_0 + 14
5 BugApp 0x0003387b -[PELOTReproduceBugViewController tableView:cellForRowAtIndexPath:] + 1083
6 UIKit 0x0057e11f -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 412
7 UIKit 0x0057e1f3 -[UITableView _createPreparedCellForGlobalRow:] + 69
注意第一次
photo = (UIImageView *)[cell.contentView viewWithTag:PHOTO_TAG];
被调用,它工作。第二个,没有。
要重现,您必须调用 [table reloadData]。
【问题讨论】:
-
如果将 UIImageView *photo 初始化为 nil,问题会消失吗? UIImageView *photo = nil;
-
不管这里有什么问题,但这是一种糟糕的技术。使用当前提倡的实现,您将始终返回一个单元格,因此初始化永远不会触发。我强烈建议创建一个子类(然后将图像视图设为属性)。
-
@Eiko,鉴于 OP 的实现,初始化将触发,尽管我同意这不是创建自定义单元格的最佳方式,尽管 Apple 的示例代码。
-
我无法重现您的问题。我复制了你的代码,并且总是在日志中获得图像视图。我同意 Eico 的观点,现在这不是最好的方法。最好在其 init 方法中创建单元格的子视图,并创建任何子视图属性,这样您就可以通过名称引用它们,而不是使用 viewWithTag:。如果你这样做,你应该在viewDidLoad中注册类(registerClass:forCellReuseIdentifier:),然后就不需要检查nil单元格了。
-
@Chocksmith 我想知道您是否在检查视图标签时不小心在某处使用了赋值而不是比较,您显示的代码没有这个问题,但其他代码可能有,请检查您的相关文件中的
if和while条件。
标签: ios objective-c uitableview