Overview
I'm creating a UITableView with custom UITableViewCell (in iOS 8.4,Objective-C). i've created IBoutlets of each and every items in Custom Cell. it seems working well, but randomly my UIButton gets disappeared from custom cell.
here my CellForRowAtIndexPath Code
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
linkCell*cell = (linkCell*)[tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if(!cell){
cell = [[linkCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
cell.contentView.backgroundColor = [UIColor clearColor];
NSDictionary *aDict = [numberOfSections objectAtIndex:indexPath.section];
NSDictionary* info = [[aDict objectForKey:#"Data"]objectAtIndex:indexPath.row];
static float span = 5;
static float dateviewsize = 83;
static float linesize = 1;
static float descriptionsize = 65;
//DAY_NAME
NSString* string = [self getDayNameFromDate:[info valueForKey:#"copied_url_date"]];
cell.lblDayName.text = string;
//DAY_NUMBER
string = [self getDayNumberFromDate:[info valueForKey:#"copied_url_date"]];
cell.lblDayNumber.text = string;
//DAY_TIME
string = [self getTimeFromDate:[info valueForKey:#"copied_url_date"]];
cell.lblDayTime.text = string;
//Link Label
if([[info objectForKey:#"copied_url_title"] isEqualToString:#"nil"]){
string = [NSString stringWithFormat:#"%#",[info valueForKey:#"copied_url"]];
cell.lblLink.font = [UIFont fontWithName:FONT_LIGHT size:14];
cell.lblLink.textColor = [UIColor colorWithRed:51.0/255.0 green:0/255.0 blue:135.0/255.0 alpha:1.0];
}else{
string = [NSString stringWithFormat:#"%#",[info objectForKey:#"copied_url_title"]];
cell.lblLink.font = [UIFont fontWithName:FONT_MEDIUM size:16];
cell.lblLink.textColor = [UIColor darkGrayColor];
}
cell.lblLink.text = string;
float w,h,y;
w = self.view.frame.size.width-(span*2);
CGRect dataviewframe,titleRect,buttonviewrect,imageRect;
CGSize newsize;
[cell.lblDescreption setFont:[UIFont fontWithName:FONT_LIGHT size:16]];
[cell.lblDescreption setNumberOfLines:3];
[cell.linkimage setHidden:NO];
if([AFNetworkReachabilityManager sharedManager].isReachable){
//Unspacified ImageView
if([[info objectForKey:#"copied_url_img"]isEqualToString:#"nil"]){
[cell.linkimage setHidden:YES];//hide image
//make call to get image & title of Copied URL
[self MakeCallAndSetImageToImageView:indexPath ToGetImageFromURL:[info valueForKey:#"copied_url"]];
//new size of link title
y = span+dateviewsize+span+linesize+1;
if([[info objectForKey:#"copied_url_description"] isEqualToString:#"nil"]){
[cell.lblDescreption setHidden:YES];//hide description
//set dataview's new height
h = span+dateviewsize+span;
}
else{
[cell.lblDescreption setHidden:NO];//show description
NSString* string = [NSString stringWithFormat:#"%#",[info objectForKey:#"copied_url_description"]];
[cell.lblDescreption setText:string];
newsize = [self getStringHeightWithMaxWidth:w-(span*2) AndText:cell.lblDescreption];
if(newsize.height > descriptionsize){
titleRect = CGRectMake(span,y,w-(span*2),descriptionsize);
//set dataview's new height
h = y+descriptionsize+span;
}else{
titleRect = CGRectMake(span,y,w-(span*2),newsize.height);
//set dataview's new height
h = y+newsize.height+span;
}
[cell.lblDescreption setFrame:titleRect];
}
dataviewframe = CGRectMake(span,span,w,h);
//set buttonview's new frame
buttonviewrect = CGRectMake(span,h+span+2,w,50);
}else{
[cell.linkimage setHidden:NO];//show image
//new size of link image
y = span+dateviewsize+span+linesize+1;
float imageH = [self SizeWithScaledToWidth:w-(span*2)].height;
imageRect = CGRectMake(span,y,w-(span*2),imageH);
NSString* imgurl=[NSString stringWithFormat:#"%#",[info objectForKey:#"copied_url_img"]];
[cell.linkimage setImageWithURL:[NSURL URLWithString:imgurl]];
[cell.linkimage setFrame:imageRect];
y = y+imageH+span;
//new size of link title
if([[info objectForKey:#"copied_url_description"] isEqualToString:#"nil"]){
[cell.lblDescreption setHidden:YES];
h = y+span;
}else{
[cell.lblDescreption setHidden:NO];//show description
NSString* string = [NSString stringWithFormat:#"%#",[info objectForKey:#"copied_url_description"]];
[cell.lblDescreption setText:string];
newsize = [self getStringHeightWithMaxWidth:w-(span*2) AndText:cell.lblDescreption];
if(newsize.height > descriptionsize){
titleRect = CGRectMake(span,y,w-(span*2),descriptionsize);
//set dataview's new height
h = y+descriptionsize+span;
}else{
titleRect = CGRectMake(span,y,w-(span*2),newsize.height);
//set dataview's new height
h = y+newsize.height+span;
}
[cell.lblDescreption setFrame:titleRect];
}
//set dataview's new frame
dataviewframe = CGRectMake(span,span,w,h);
//set buttonview's new frame
buttonviewrect = CGRectMake(span,h+span+2,w,50);
}
}else{
//NO INTERNET CONNECTION
//hide link image
[cell.linkimage setHidden:YES];
//hide link title
[cell.lblDescreption setHidden:YES];
//set dataview's new frame
h = span+dateviewsize;
dataviewframe = CGRectMake(span,span,w,h);
//set buttonview's new frame
buttonviewrect = CGRectMake(span,h+span+2,w,50);
}
cell.dataview.frame = dataviewframe;
cell.buttonview.frame = buttonviewrect;
if([selectedRow isEqual:indexPath]){
cell.buttonview.alpha=1;
}else{
cell.buttonview.alpha=0;
}
[cell.btnShare setHidden:NO];
[cell.buttonview bringSubviewToFront:cell.btnShare];
[cell.buttonview bringSubviewToFront:cell.btnOpen];
[cell.buttonview bringSubviewToFront:cell.btnCopy];
[cell.buttonview bringSubviewToFront:cell.btnDelete];
[cell.btnShare addTarget:self action:#selector(Action:) forControlEvents:UIControlEventTouchUpInside];
[cell.btnOpen addTarget:self action:#selector(Action:) forControlEvents:UIControlEventTouchUpInside];
[cell.btnCopy addTarget:self action:#selector(Action:) forControlEvents:UIControlEventTouchUpInside];
[cell.btnDelete addTarget:self action:#selector(Action:) forControlEvents:UIControlEventTouchUpInside];
[cell.btnShare setTag:indexPath.row];
[cell.btnOpen setTag:indexPath.row];
[cell.btnCopy setTag:indexPath.row];
[cell.btnDelete setTag:indexPath.row];
return cell;
}
here is my screen shots
Thanks in Advance tell me if you want more info.
You're doing way too much in the -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method. It's good practice to give a custom cell a configuration method, like -(void)configureCell, where the content and lay-out of the cell will be defined. In other words, let the cell be responsible (as much as possible) for its content and lay-out instead of the tableview.
I guess this part causes problems:
if([AFNetworkReachabilityManager sharedManager].isReachable) {
...
}
Especially:
[self MakeCallAndSetImageToImageView:indexPath ToGetImageFromURL:[info valueForKey:#"copied_url"]];
I don't know the implementation of this method, but I have the feeling you have to look over there, as it can be a threading issue at retrieving the image you requested.
One more tip: the way you name your classes and methods doesn't always follow the Objective-C conventions. Check linkCell (class) and MakeCallAndSetImageToImageView ... (method).
Possible layout broken. Try to capture view hierarchy. In Xcode: Debug > View Debugging > Capture View Hierarchy.
Also, method dequeueReusableCellWithIdentifier:forIndexPath: always returns a valid cell. if(!cell){ ... } will never be executed, you can remove it.
Try to use this block of GCD, i think it will work.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Do data fetching and calculation
dispatch_async(dispatch_get_main_queue(), ^(void) {
//Update UI on main thread
});
});
After a long time, i found the mistake in my code. i was setting buttonview tag indexPath.row and also gave same to button tag. and when DidSelectRowAtIndexPath get called, i was doing,
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
linkCell*cell = (linkCell*)[tableView cellForRowAtIndexPath:indexPath];
if([selectedRow isEqual:indexPath]){
selectedRow = nil;
//this is where i'm mistaking.
[[cell viewWithTag: indexPath.row]setAlpha:1];
}else{
selectedRow = indexPath;
//this is where i'm mistaking.
[[cell viewWithTag: indexPath.row]setAlpha:0];
}
[tableView reloadData];
}
so, i gave -1 tag to buttonview and the problem is solved.
if([selectedRow isEqual:indexPath]){
selectedRow = nil;
[[cell viewWithTag: -1]setAlpha:1];
}else{
selectedRow = indexPath;
[[cell viewWithTag: -1]setAlpha:0];
}
by the way thanks for your valuable Tips and Advises.
Related
created 4x4 metrics button in UITableView.
I want to select the button in sequentially order.
// button Creation in cell for row Index
for (int i = 0; i< [buttonArray count]; i++)
{
int buttonSpace = 10 * i + 10;
NSLog(#"ButtonPosition:%d",buttonSpace + (i * 50));
cell.Button = [[CustomButton alloc] initWithFrame:CGRectMake(buttonSpace + (i * 50),35, 50, 50)];
cell.Button.layer.cornerRadius = 25;
[cell.Button addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
cell.Button.buttonIndex = i;
[cell.ScrollView addSubview:cell.Button];
cell.ScrollView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.3];
}
rowIndexValue = indexPath.row;
// Button action in view controller.
-(void)buttonAction:(CustomButton *)sender
{
if (rowIndexValue) {
int counter = (int)[sender buttonIndex];
if (counter == incrementValue)
{
sender.backgroundColor = [UIColor redColor];
counter += 1;
incrementValue = counter;
}
else{
sender.selected = NO;
}
}
}
The order of button action in sequential order, for any random row's.
user select 3rd row but selection row in third row start from 1st button then 2nd button then 3rd button finally 4th button.
4x4 - > 4 row for UITableview 4 button in each row. Once button is click it will be in disable Mode
Set proper value so that you can recognise button column as well as row position. buttonIndex is just saving i value so you will only get column position.You may set button.tag=indexPath.row and use it in the buttonAction method to know the row position.
Declare NSInteger tagValue globally in your viewController.
-(NSUInteger)getRowByBtn:(UIButton *)btn :(UITableView *)tblView
{
CGPoint center= btn.center;
CGPoint rootViewPoint = [btn.superview convertPoint:center toView:tblView];
NSIndexPath *indexPath = [tblView indexPathForRowAtPoint:rootViewPoint];
NSLog(#"indexPath = %ld", (long)indexPath.row);
return indexPath.row;
}
With the help of above method you can get indexpath.row value from which you can determine the button for each row in the tableview.
[cell.Button addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
-(void)buttonAction:(UIButton*)sender
{
UIButton *btn=(UIButton *)sender;
tagValue = [self getRowByBtn:btn :yourTableview];
[[self.view viewWithTag:tagValue]setUserInteractionEnabled:YES];
//or any other action
}
Set UIButton tag in CellForRowAtIndexPath
Like this :
[cell.btn_name addTarget:self action:#selector(onclick_button:) forControlEvents:UIControlEventTouchUpInside];
self.btn_name.tag=indexpath.row;
And
-(IBAction)onclick_button:(id)sender
{
int btn_index= ((UIView*)sender).tag;
NSLog(#"Btn index:%d",btn_index);
}
It fix the problem with below code.
-(void)buttonAction:(UIButton*)sender{
CGPoint center = sender.center;
CGPoint rootViewPoint = [sender.superview convertPoint:centre toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rootViewPoint];
sender.userInteractionEnabled = NO;
sender.backgroundColor = [UIColor redColor];
CustomButton *enableNextButton = (CustomButton *) [[self.goalsTableView cellForRowAtIndexPath:indexPath] viewWithTag:sender.tag+1];
enableNextButton.userInteractionEnabled = YES;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am working with an IOS application. In my project have several UITableView with many rows, and each row has two images. When I scroll fast then It can't load cells smoothly. How can I scroll smoothly ???
N.B: I don't want to load all rows at a time.
Please Help
Edited:
Here is my code :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
float sca=appDelegate.deviceScaleFloat;
float XOffset=0*sca;
cell = [[UITableViewCell alloc] init];
cell.opaque = YES;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIImage *backImg;
backImg= [UIImage imageNamed:[NSString stringWithFormat:#"background-goal-collect%#.png",ipadExtention]];
backImg=[self scaleWithScaleFactor:backImg];
UIImageView *btnBuyImageView=[[UIImageView alloc]initWithImage:backImg];
btnBuyImageView.frame=CGRectMake(XOffset, 0, backImg.size.width, backImg.size.height);
[cell.contentView addSubview: btnBuyImageView];
for (int i=0; i<5 && indexPath.row*5+i<[catFishes count]; i++) {
int productIndex = (int)indexPath.row*5 + i;
DBProductAttributes *productAttributes = [allProductAttributes objectAtIndex:productIndex];
DBProductInfo *productInfo = [catFishes objectAtIndex:productIndex];
UIImage *frameImage = [UIImage imageNamed:[NSString stringWithFormat:#"background-element-%d%#.png",productAttributes.elementid,ipadExtention]];
frameImage=[self scaleWithScaleFactor:frameImage];UIImageView *frameView = [[UIImageView alloc] initWithImage:frameImage];
frameView.frame = CGRectMake((frameImage.size.width*i)+10*sca+5*i*sca, 5*sca , frameImage.size.width, frameImage.size.height);
frameView.userInteractionEnabled=YES;
[cell.contentView addSubview:frameView];
MyTapGestureRecognizer *tapGesture=[[MyTapGestureRecognizer alloc] init];
tapGesture.tag=productIndex;
[tapGesture addTarget:self action:#selector(buttonClicked:)];
[frameView addGestureRecognizer:tapGesture];
NSString *IconStr = [NSString stringWithFormat:#"i%db.png", productInfo.productid];
UIImage *btnImg = [UIImage imageNamed:IconStr];
if(![self isProductPurchesed:productInfo.productid])
{
if([ITIWAppDelegate blackimageforstore]>0)
{
btnImg = [self getBlackAndWhiteVersionOfImage:btnImg];
}
}
UIImageView *imageIconView;
imageIconView = [[UIImageView alloc] initWithImage:btnImg];
imageIconView.frame = CGRectMake(frameView.frame.origin.x+frameImage.size.width-64*sca, frameView.frame.origin.y/*+frameImage.size.height-64*sca*/ , 64*sca, 64*sca);
imageIconView.opaque = YES;
[cell.contentView addSubview:imageIconView];
UILabel *name;
name = [[UILabel alloc] initWithFrame:CGRectMake(frameView.frame.origin.x, frameView.frame.origin.y+62*sca, frameImage.size.width-0*sca, 18.0f*sca)];
name.text = productInfo.product_name;
name.font = [UIFont fontWithName:#"Georgia" size:12.0f*sca];
name.adjustsFontSizeToFitWidth = YES;
name.textAlignment = NSTextAlignmentCenter;
if(![self isProductPurchesed:productInfo.productid])
name.backgroundColor=[UIColor grayColor];
else
name.backgroundColor = [UIColor colorWithRed:colorCodeDragonBook[productAttributes.elementid-1][0]/255.0f green:colorCodeDragonBook[productAttributes.elementid-1][1]/255.0f blue:colorCodeDragonBook[productAttributes.elementid-1][2]/255.0f alpha:1.0f];
name.textColor = [UIColor colorWithWhite:1.0 alpha:1.0];
//name.shadowColor = [UIColor blackColor];
name.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
[cell.contentView addSubview:name];
NSArray *otherElements = [productAttributes.otherElementid componentsSeparatedByString:#","];
int k=0;
UIImage *habitatFlag = [UIImage imageNamed:[NSString stringWithFormat:#"flag-%d.png",productAttributes.elementid]]; UIImageView *habitatFlagView = [[UIImageView alloc] initWithImage:habitatFlag];
habitatFlagView.frame = CGRectMake(frameView.frame.origin.x-1*sca, frameView.frame.origin.y-1*sca , 15*sca, 22*sca);
[cell.contentView addSubview:habitatFlagView];
k+=15;
for (int i=0; i<[otherElements count]; i++) {
int otherElementid = [[otherElements objectAtIndex:i] intValue];
if(otherElementid==productAttributes.elementid) continue;
UIImage *habitatFlag = [UIImage imageNamed:[NSString stringWithFormat:#"flag-%d.png",otherElementid]]; UIImageView *habitatFlagView = [[UIImageView alloc] initWithImage:habitatFlag];
habitatFlagView.frame = CGRectMake(frameView.frame.origin.x+k*sca-1*sca, frameView.frame.origin.y-1*sca , 15*sca, 22*sca);
[cell.contentView addSubview:habitatFlagView];
k+=15;
}
}
return cell;
}
Problem is occurring when the cells are going to off screen, the tableview release all cells of off screen. And when after that I want to scroll the cells are reloading. I think it is not optimal to load cells. But I don't know how to optimize this.
the best you have to do is load the images asynchronously, and not in the main thread.
If you want, you can use my ImageLoader project : https://github.com/celian-m/ImageLoader/blob/master/ImageLoader.swift
All you have to do is using CMImageView instead of UIImageView.
Then you can do [myImageView assignImageFromUrl:YOUR_URL]
This will load your images in the background thread, in FIFO mode, and save it in memory and disk cache ( i.e. : you need to load each image only 1 time ).
You can make use of SDWebImageCache so that it'll cache the images in disk and the loading of images becomes much faster.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0ul);
dispatch_async(queue, ^{
//set image here
});
What about setting the image async in the tableview callback:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
May I ask whether the images are web images or local images?
I'm using the QuickBlox Framework to build a chatting application. Currently, when the chat view opens up, everything looks great.
However, when the users begins to scroll up and down the chat history, some of the cells begin to change (for example, they'll show an image which should be placed in a different row).
Below is my code for cellForRowAtIndexPath, if anyone can tell me what I'm doing wrong
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
QBChatMessage *message = [[ChatService shared] messagsForDialogId:self.dialog.ID][indexPath.row];
if (message.attachments.count > 0) {
ImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ImageCellIdentifier];
[cell configureCellWithImage:message];
cell.backgroundColor = [UIColor whiteColor];
return cell;
} else {
ChatMessageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ChatMessageCellIdentifier];
[cell configureCellWithMessage:message];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
}
EDIT Please see below my ImageTableViewCell configureCellWithImage method:
- (void) configureCellWithImage:(QBChatMessage*)message {
NSString *time = [message.dateSent timeAgoSinceNow];
if ([QBSession currentSession].currentUser.ID == message.senderID) {
// Message was sent by me
NSData *imageData = [FTWCache objectForKey:[NSString stringWithFormat:#"%#", [message.attachments[0] valueForKey:#"ID"]]];
if (imageData) {
// image is already downloaded
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
UIImageView *cellImage = [[UIImageView alloc] init];
[self.backgroundImageView setFrame:CGRectMake(320-155, 10, 140, 140)];
cellImage.frame = CGRectMake(7, 7, 120, 120);
[cellImage setContentMode:UIViewContentModeScaleAspectFill];
cellImage.clipsToBounds = YES;
cellImage.layer.cornerRadius = 5;
cellImage.image = image;
self.backgroundImageView.image = aquaBubble;
[self.backgroundImageView addSubview:cellImage];
[self.contentView addSubview:self.backgroundImageView];
});
} else {
// downloads the image and displays as above
}
} else {
// Message was sent by another user
NSData *imageData = [FTWCache objectForKey:[NSString stringWithFormat:#"%#", [message.attachments[0] valueForKey:#"ID"]]];
if (imageData) {
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
UIImageView *cellImage = [[UIImageView alloc] init];
[self.backgroundImageView setFrame:CGRectMake(padding/2, padding+5, 140, 140)];
cellImage.frame = CGRectMake(13, 7, 120, 120);
[cellImage setContentMode:UIViewContentModeScaleAspectFill];
cellImage.layer.cornerRadius = 5;
cellImage.clipsToBounds = YES;
cellImage.image = image;
self.timeLabel.frame = CGRectMake(20, self.backgroundImageView.frame.size.height + 20, 80, 20);
self.timeLabel.text = [NSString stringWithFormat:#"%#", time];
[self.timeLabel setFont:[UIFont systemFontOfSize:10.0]];
[self.timeLabel setTextColor:[UIColor blackColor]];
[self.contentView addSubview:self.timeLabel];
self.nameAndDateLabel.textAlignment = NSTextAlignmentLeft;
QBUUser *sender = [ChatService shared].usersAsDictionary[#(message.senderID)];
NSInteger loginForColor = [sender.login integerValue];
loginForColor = loginForColor % 255;
self.nameAndDateLabel.text = [NSString stringWithFormat:#"%#", sender.fullName];
self.backgroundImageView.image = orangeBubble;
[self.backgroundImageView addSubview:cellImage];
[self.contentView addSubview:self.backgroundImageView];
});
} else {
// downloads the image and displays as above
}
}
}
Cells get reused. Therefore you must always set/reset all properties of the cell each time.
For every if statement that sets a cell's property, there must be an else statement that resets the same property - even if it just clears the value.
Also you must avoid adding subviews over and over each time the cell is used. You have code that creates and adds an image view to the cell. But you keep adding new image views over and over. Just add it once if needed. If it's already there, update it with the new image instead of adding a new one.
The error should be on the functions configureCellWithImage and configureCellWithMessage.
I didn't see the code of those functions, but i bet that you didn't clean the image content on the configureCellWithMessage.
Im trying to refactor my code for better memory management and performance. I have an array of 12 images, but I want to load them as needed, not all at the same time. So maybe the current image -1, the current image and the current image +1. I viewed some of the answers on SO but found them unclear. I felt it would be clearer if I posted my code for reference.
//scroll view set up
- (void)scrollViewSetUp
{
self.scrollview.delegate = self;
for (int i = 0; i < _images.count; i++)
{
CGRect frame;
frame.origin.x = self.scrollview.frame.size.width * i;
frame.size = self.scrollview.frame.size;
self.scrollview.pagingEnabled = YES;
UIImageView *subview = [[UIImageView alloc] initWithFrame:frame];
subview.image = [UIImage imageNamed:[_images objectAtIndex:i]];
[self.scrollview addSubview:subview];
}
self.scrollview.contentSize = CGSizeMake(self.scrollview.frame.size.width * _images.count, self.scrollview.frame.size.height);
self.automaticallyAdjustsScrollViewInsets = NO;
//page control ie .... at bottom of
self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(100.0,0.0,100.0,40.0)];
[self.pageControl setNumberOfPages:_images.count];
[self.pageControl setCurrentPage:0];
self.pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
self.pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
[self.pageControl setBackgroundColor:[UIColor clearColor]];
[self.viewForPageControl addSubview:self.pageControl];
[self.viewForPageControl setBackgroundColor:[UIColor clearColor]];
}
#pragma mark - UIScrollView Delegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
int newOffset = scrollView.contentOffset.x;
int newPage = (int)(newOffset/(scrollView.frame.size.width));
[_pageControl setCurrentPage:newPage];
}
Any advice or direction is greatly appreciated.
As per Gman's request I reposted my comment.
This tutorial will help you:
http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content
You could try to reuse your UIImageView as they go offscreen... but you'll be just trying to redo what UITableview already does. UITableView with a custom UITableViewCell would take care of notifying you when new cells comes visible and dequeuing the ones that are offscreen.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"yourCustomImageCell";
//look if there are cells that could be reused
CustomImageCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) { //if not, create a new one
cell = [[CustomImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
//Set your image here
return cell;
}
Not sure if this is the best way of doing it, but it's an option.
You can set the tag property on your UIImageView to correspond to your index in your loop when setting the scrollView.
Then in your scrollViewDidEndDecelerating method:
for (int i = 0; i < _salonImages.count; i++)
{
if(i == (newPage-1))
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:newPage-1];
imgView.image = [_images objectAtIndex:newPage-1];
}
else if(i == newPage)
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:newPage];
imgView.image = [_images objectAtIndex:newPage];
}
else if(i == (newPage + 1 ))
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:newPage+1];
imgView.image = [_images objectAtIndex:newPage+1];
}
else
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:i];
imgView.image = nil;
}
}
I have on custom cell UIButton with UIImage content, with target action selector pushToImageDetailViewController: which push view to another detail view of image.
I create cell from UIPickerView in his delegate method and after that I upload image on server, next store to document path library. I need editing property on my custom cell, attachmentId and here is that problem.
- (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];
}
}
This code I have in block, therefore weakSelf on self property, important is refresh cell statements, indexPathForRow fired cellForRowAtIndexPath, in this message I have NSLog and right ID
get into this message.
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];
in cellForRowAtIndex assigning id from self.messages, Array of Dictionaries collection to cell property attachmentId, but in pushToImageDetail I have old ID before pregenerated.
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];
Problem is that id in imageDetailView.attachmentId = cell.attachmentId assigns old id (bad binding image detail with id of image) and in cellForRow is new actual cell.attachmentId = [attachmentInfo objectForKey:#"id"]. I don't know how it is possible.
Here is 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;
}
Solved by assign into tag property indexPath.row on UIButton, but still don't understand why my previous method didn't work.
- (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];
}