I have a UITableView that holds an FBProfilePictureView and a UILable,
my problem is when a user scrolls the picture rebuilds its self and it takes time to show the image it self, i want to know how can i create the FBProfilePictureView once and then when the user scrolls it won't build it self again.
Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
Messages *msg = [messages objectAtIndex:indexPath.row];
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
NSData *encodedDataObject = [def objectForKey:#"myUser"];
User *user = (User *)[NSKeyedUnarchiver unarchiveObjectWithData: encodedDataObject];
if(![msg.wrote_id isEqualToString:user.fid])
{
NSString *idToImage = [self getOtherUserId];
NSString *CellIdentifier = #"Cell";
ChatWindowCell *cell = nil;
cell = (ChatWindowCell *)[tableChat dequeueReusableCellWithIdentifier:CellIdentifier];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ChatWindowCell" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[ChatWindowCell class]])
{
cell = (ChatWindowCell *) currentObject;
cell.profile_image.profileID=nil;
if(cell.profile_image.profileID.length>0)
{
return cell;
}
break;
}
}
cell.profile_image.profileID = idToImage;
NSString *text = msg.msg;
cell.lblMessage.text=text;
return cell;
}
else
{
NSString *CellIdentifier = #"Cell";
ChatCellMe *cell = nil;
cell = (ChatCellMe *)[tableChat dequeueReusableCellWithIdentifier:CellIdentifier];
// if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ChatCellMe" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[ChatCellMe class]])
{
cell = (ChatCellMe *) currentObject;
NSLog(cell.prof_img.profileID);
cell.prof_img.profileID=nil;
if(cell.prof_img.profileID.length>0)
{
return cell;
}
break;
}
}
cell.prof_img.profileID = user.fid;
NSString *text = msg.msg;
cell.lblText.text=text;
isMessageFromMe=false;
return cell;
}
}
any help would be great guys...
thanks a lot.
I created an alternate view to solve this problem, see https://github.com/combinatorial/DBFBProfilePictureView
Related
I am using the following code to have a tab view. When you click one tab it expands downwards, this is currently working okay but if I open the first tab with the indexPath of 0 which should load a separate custom opened view it will load but then when I go to the other indexPath tabs it displays the same view but if I reload the app and go to the other tabs first they load the correct view. It's nearly like the app is making a cache?
Is there any way to solve this??
Thanks
- (void)viewDidLoad {
row = 1000;
NSLog(#"row is %d", row);
[super viewDidLoad];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
infoStory = [userDefaults objectForKey:#"storyname"];
// Do any additional setup after loading the view.
numbers = [NSArray arrayWithObjects:#"1", #"2", #"3", #"4", #"5", #"6", #"7", #"8", nil];
// Initialize thumbnails
text = [NSArray arrayWithObjects: #"Arriving by Bus or Train", #"Arriving by Car (Autobahn 5)", #"Arriving by Car (Autobahn 6)", #"Wifi", #"Registration", #"Refreshments", #"Evening Event", #"Contact Information", nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(row == indexPath.row){
if(indexPath.row == 0){
static NSString *simpleTableIdentifier2 = #"TableViewCellOPENEDbustaxi2";
TableViewCell1 *cell = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellOPENEDbustaxi2" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.text.text = [text objectAtIndex:indexPath.row];
return cell;
}
else{
static NSString *simpleTableIdentifier = #"TableViewCellOPENED";
TableViewCell1 *cell2 = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell2 == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellOPENED" owner:self options:nil];
cell2 = [nib objectAtIndex:0];
}
cell2.text.text = [text objectAtIndex:indexPath.row];
return cell2;
}
}
else{
static NSString *simpleTableIdentifier = #"TableViewCellINFO";
TableViewCell1 *cell = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellINFO" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.text.text = [text objectAtIndex:indexPath.row];
return cell;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [numbers count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(row == indexPath.row){
row = 1000;
NSLog(#"row is %d", row);
[self.tableViewObject reloadData];
}
else{
row = indexPath.row;
NSLog(#"row is %d", row);
[self.tableViewObject reloadData];
}
}
#end
I think the problem might be that you did not specify the correct reuse identifier in the attributes inspector of the cell in your XIB file(s). You should check if you use the wrong one somewhere, so dequeueing will return an unexpected cell.
You could also set the appropriate reuseIdentifier manually, with a little setValue:forKey: trick:
static NSString *simpleTableIdentifier2 = #"TableViewCellOPENEDbustaxi2";
TableViewCell1 *cell = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellOPENEDbustaxi2" owner:self options:nil];
cell = [nib objectAtIndex:0];
[cell setValue:simpleTableIdentifier2 forKey:#"reuseIdentifier"];
}
and so on for the other cells and identifiers.
Interesting predicament: Data for 'variant' is returned successfully, and for some reason it won't display in my cell's UILabel (the UILabel just appears empty, and yes, it's 'hooked up')? Is my currencyFormatter throwing this off somehow? Should I format this line differently? Help is appreciated.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PointsTableIdentifier = #"PointsCell";
PointsCell *cell = (PointsCell *)[tableView dequeueReusableCellWithIdentifier:PointsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"PointsCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
BUYProduct *productsbuy = self.products[indexPath.row];
cell.productLabel.text = productsbuy.title;
BUYProduct *productDescription = self.products[indexPath.row];
cell.productDescrip.text = productDescription.htmlDescription;
BUYProduct *pointValues = self.products[indexPath.row];
BUYProductVariant *variant = pointValues.variants.firstObject;
cell.priceLabel.text = [self.currencyFormatter stringFromNumber: variant.price];
NSLog(#"%#", variant.price);
}
return cell;
}
I have two tableviewcell in xib file and I use both of them.
When I use one of them the memory is still 7.3MB, but when I use both memory grow very fast.
Please help me. I don't now what is wrong.
My code is below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.events objectAtIndex:row];
static NSString *CellIdentifierL = #"LeftCell";
static NSString *CellIdentifierR = #"RightCell";
SampleTableCell *cellLeft = [tableView dequeueReusableCellWithIdentifier:CellIdentifierL];
SampleTableCell *cellRight = [tableView dequeueReusableCellWithIdentifier:CellIdentifierR];
if (cellLeft == nil) {
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"LeftTableCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SampleTableCell class]]) {
cellLeft = (SampleTableCell *)currentObject;
break;
}
}
}
if (cellRight == nil) {
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RightTableCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SampleTableCell class]]) {
cellRight = (SampleTableCell *)currentObject;
break;
}
}
}
return (row%2==0)?cellRight:cellLeft;
}
You need to create only the cell you need. Your code should be like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.events objectAtIndex:row];
static NSString *CellIdentifierL = #"LeftCell";
static NSString *CellIdentifierR = #"RightCell";
if (cellLeft == nil) {
SampleTableCell *cellLeft = [tableView dequeueReusableCellWithIdentifier:CellIdentifierL];
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"LeftTableCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SampleTableCell class]]) {
cellLeft = (SampleTableCell *)currentObject;
break;
}
}
return cellLeft;
}
if (cellRight == nil) {
SampleTableCell *cellRight = [tableView dequeueReusableCellWithIdentifier:CellIdentifierR];
NSArray* topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RightTableCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[SampleTableCell class]]) {
cellRight = (SampleTableCell *)currentObject;
break;
}
}
return cellRight;
}
return nil;
}
I change to this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.events objectAtIndex:row];
SampleTableCell *cell;
if(row%2==0){
cell = [[[NSBundle mainBundle] loadNibNamed:#"RightTableCell" owner:self options:nil]objectAtIndex:0];
}else{
cell = [[[NSBundle mainBundle] loadNibNamed:#"LeftTableCell" owner:self options:nil]objectAtIndex:0];
}
cell.labelName.text = [rowData objectForKey:#"name"];
return cell;
}
But I don't know that is good idea?
This is not a good way to do this. You are creating both cells for every row, but you only use one of them. You should also use the newer way to use a xib based cell -- that is, use registerNib:forCellWithReuseIdentifier: in viewDidLoad, to register both nibs. Do your check for odd/even rows first, and dequeue the correct cell (no need to check for nil when using the register method). You do it like this:
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:#"SampleCell1" bundle:nil] forCellReuseIdentifier:#"SampleCell1"];
[self.tableView registerNib:[UINib nibWithNibName:#"SampleCell2" bundle:nil] forCellReuseIdentifier:#"SampleCell2"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row % 2 == 0) {
SampleCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SampleCell1" forIndexPath:indexPath];
// populate cell with data
return cell;
}else{
SampleCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SampleCell2" forIndexPath:indexPath];
// populate cell with data
return cell;
}
}
This is all you need to do. There's no need to check for a nil cell, because dequeueReusableCellWithIdentifier:forIndexPath: is guaranteed to return a valid cell if you either register a nib, or make the cell in a storyboard (in which case you don't need to register anything).
How wrong could it be the code bellow:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
NSArray *array = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil];
for (id currentObject in array) {
if ([currentObject isKindOfClass:[self class]]) {
self = [currentObject retain];
}
}
return self;
}
I'm trying to bring up a custom UITableViewCell from nib file, the problem is that Leaks Instruments says there's a leak inside:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CPVideoGenTVCell *cell = (CPVideoGenTVCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CPVideoGenTVCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.delegate = self;
cell.titleLbl.textColor = [UIColor colorWithRed:0.992 green:0.933 blue:0.0 alpha:1.0];
}
CPTempVideo *aVideo = [self.videos objectAtIndex:indexPath.row];
cell.seasonLbl.text = [NSString stringWithFormat:#"Season %#", [self romanNumberFromArabic:aVideo.season]];
cell.titleLbl.text = [NSString stringWithFormat:#"%2i - \"%#\"",aVideo.idVideo, aVideo.chapterName];
cell.managedImg.url = aVideo.thumbnail;
[[CPDataManager sharedDataManager] manageImage:cell.managedImg];
return cell;
}
think the problem is with retain, but don't understand why are you doing this crazy stuff with initWithStyle..
if ([currentObject isKindOfClass:[self class]]) {
self = currentObject;
}
There's an alternative I've found:
+ (id)cellWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
NSArray *array = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil];
for (id currentObject in array) {
if ([currentObject isKindOfClass:[self class]]) {
return currentObject;
}
}
return nil;
}
just return an autoreleased object and take care of that inside cellForRowAtIndexPath:
CPTempHeadCell *headCell = (CPTempHeadCell *)[tableView dequeueReusableCellWithIdentifier:HeadCellIdentifier];
if (headCell == nil) {
headCell = [CPVideoGenTVCell cellWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
i need two kinds of UITableViewCell that has different height:
a) One with a small UIImageView holding user picture, 3 UILabel's and one UIImageView of 200 x 100.
b) The other has the same like a) without the UIImageView.
Well, in order to achieve this i have built two custom UITableViewCell's and set my UITableView to use them.
The problem is when i scroll the table because sometimes it isn't smooth.
My code is the following (i only post the cellForRowAtIndexPath)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (.....) return HEIGHT1
else return HEIGHT2
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CheckinCellIdentifier";
static NSString *TextCellIdentifier = #"CheckinTextCellIdentifier";
CheckIn *checkin = [self.checkinArray objectAtIndex:indexPath.row];
if (checkin.photoUrl) {
CheckinUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CheckinUITableViewCell" owner:nil options:nil];
for(id currentObject in topLevelObjects) {
if([currentObject isKindOfClass:[CheckinUITableViewCell class]]) {
cell = (CheckinUITableViewCell *)currentObject;
if (self.userImage)
cell.userImage.image = self.userImage;
break;
}
}
}
cell.checkin = checkin;
UIImage *imageCheckin = [self.checkinImages objectForKey:[NSNumber numberWithInt:checkin.checkInId]];
if (imageCheckin) {
cell.checkinImage.image = imageCheckin;
} else {
CompleteBlock block = ^(NSData* imageData) {
if (imageData) {
UIImage *image = [UIImage imageWithData:imageData];
[self.checkinImages setObject:image forKey:[NSNumber numberWithInt:checkin.checkInId]];
CheckinUITableViewCell *lookedUpCell = (CheckinUITableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
if (lookedUpCell){
cell.checkinImage.image = image;
//[lookedUpCell setNeedsLayout];
}
}
};
[Utility loadImageFromFile:checkin.photoPath url:checkin.photoUrl withCompletionBlock:block];
}
return cell;
} else {
CheckinTextUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TextCellIdentifier];
if (cell == nil){
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CheckinTextUITableViewCell" owner:nil options:nil];
for(id currentObject in topLevelObjects) {
if([currentObject isKindOfClass:[CheckinTextUITableViewCell class]]) {
cell = (CheckinTextUITableViewCell *)currentObject;
if (self.userImage)
cell.userImage.image = self.userImage;
break;
}
}
}
cell.checkin = checkin;
return cell;
}
}
Any idea? Thanks!
The possible problem of your code is that your Cells have never been reused. NSBundle loadNibNamed: create new Cell each time your table need it. So if dataSource contain 10000 records - you creates 10000 cells.
Please check if you set cell identifier within xib file. This will cause to dequeue your cells.