According to some answers I found in Stackoverflow, I should use this piece of code:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self.collectionView scrollToItemAtIndexPath:selectedRow atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}
but the scrolling freezes, so I have to set it up this way:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.title = [NSString stringWithString:barTitle];
self.automaticallyAdjustsScrollViewInsets = NO;
//Download JSON
NSError *error=nil;
NSURL *url = [NSURL URLWithString:urlToFollow];
data = [NSMutableData dataWithContentsOfURL: url options:NSDataReadingMappedIfSafe error:&error];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSArray *response = [dictionary objectForKey:#"items"];
articlesArray = [[NSArray alloc] initWithArray:response];
//sizes
CGFloat window_height = ([self window_height]-70.0);
CGFloat window_width = [self window_width];
CGRect frame = CGRectMake((window_width/2)-15.0f , window_height, 30.0f , 15.0f);
self.pageControl = [[UIPageControl alloc]initWithFrame:frame];
UICollectionViewFlowLayout *layout = (id) self.collectionView.collectionViewLayout;
layout.itemSize = self.collectionView.frame.size;
// Add a target that will be invoked when the page control is changed by tapping on it
[self.pageControl
addTarget:self
action:#selector(pageControlChanged:)
forControlEvents:UIControlEventValueChanged
];
// Set the number of pages to the number of pages in the paged interface
// and let the height flex so that it sits nicely in its frame
if (articlesArray.count >8) {
self.pageControl.numberOfPages = 10;
}else if (articlesArray.count <8){
self.pageControl.numberOfPages =[articlesArray count];
}
self.pageControl.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[self.view addSubview:self.pageControl];
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.collectionView scrollToItemAtIndexPath:selectedRow atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}
#pragma mark uicollectionview
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [articlesArray count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
LOArcticlesCustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
[cell.imageView setImageWithURL:[NSURL URLWithString:[[articlesArray objectAtIndex:indexPath.row]objectForKey:#"photoUrl"]]placeholderImage:[UIImage imageNamed:#"simboloLakari29.png"]];
index= indexPath.row;
cell.lblMake.text = [NSString stringWithString:[[articlesArray objectAtIndex:indexPath.row]objectForKey:#"marca"]];
cell.lblMake.lineBreakMode = NSLineBreakByWordWrapping;
cell.lblModel.text = [NSString stringWithString:[[articlesArray objectAtIndex:indexPath.row]objectForKey:#"modelo"]];
cell.lblModel.lineBreakMode = NSLineBreakByWordWrapping;
cell.lblPrice.text = [NSString stringWithString:[[articlesArray objectAtIndex:indexPath.row]objectForKey:#"precio"]];
cell.lblOrder.text = [NSString stringWithFormat:#"%ld de %ld", (unsigned long)indexPath.row+1, (unsigned long)articlesArray.count];
return cell;
}
#pragma mark page control
- (void)pageControlChanged:(id)sender
{
UIPageControl *pageControl = sender;
CGFloat pageWidth = self.collectionView.frame.size.width;
CGPoint scrollTo = CGPointMake(pageWidth * pageControl.currentPage, 0);
[self.collectionView setContentOffset:scrollTo animated:YES];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.collectionView.frame.size.width;
self.pageControl.currentPage = self.collectionView.contentOffset.x / pageWidth;
}
- (CGFloat) window_height {
return [UIScreen mainScreen].applicationFrame.size.height;
}
- (CGFloat) window_width {
return [UIScreen mainScreen].applicationFrame.size.width;
}
But the CollectionView goes from index=0 to the desired index and it's very annoying.
Any suggestion?
Related
I updated the code
hi I'm using a tableview populated from a web service in my iOS app
implementing the endless scroll the page number jumps by 4 every time and is not incremented every page has 10 items that are put in an array from the tableview to display.
my code
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize articlesArray;
#synthesize currentpage;
#synthesize articles;
#synthesize page;
#synthesize rowww;
- (void)viewDidLoad {
[super viewDidLoad];
self.articlesArray = [[NSMutableArray alloc] init];
self.articles = [[NSMutableArray alloc]init];
currentpage = 1;
page = 2;
[self fetchData:(int)currentpage];
[self.tableView registerNib:[UINib nibWithNibName:#"ArticleCell" bundle:nil] forCellReuseIdentifier:#"ArticleCell"];
}
-(void)makeRequest:(int)page1{
if ([DGUtilFunctions isInternetAvailable])
{
NSString *urlString = [NSString
stringWithFormat:#"http://url/wp-json/wp/v2/posts?page=%d",(int) page1];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
NSData *theData = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil
error:nil];
self.articles = [NSJSONSerialization JSONObjectWithData:theData
options:NSJSONReadingMutableContainers
error:nil];
NSLog(#"self.articles %#",self.articles);
}
else
{
UIAlertController* _alertView = [ UIAlertController alertControllerWithTitle:nil
message:#"Veuillez vous connecter à internet. " preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action){} ];
[_alertView addAction:defaultAction ];
[self presentViewController:_alertView animated:YES completion:nil];
}
}
-(void) fetchData:(int)page2 {
if ([DGUtilFunctions isInternetAvailable])
{
NSString *urlString = [NSString
stringWithFormat:#"http://url/wp-json/wp/v2/posts?&page=%d", (int)page2];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
NSData *theData = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil
error:nil];
self.articlesArray = [NSJSONSerialization JSONObjectWithData:theData
options:NSJSONReadingMutableContainers
error:nil];
NSLog(#"articlesarray %#",self.articlesArray);
}
else
{
UIAlertController* _alertView = [ UIAlertController alertControllerWithTitle:nil
message:#"Veuillez vous connecter à internet. " preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action){} ];
[_alertView addAction:defaultAction ];
[self presentViewController:_alertView animated:YES completion:nil];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
CGPoint offset = aScrollView.contentOffset;
CGRect bounds = aScrollView.bounds;
CGSize size = aScrollView.contentSize;
UIEdgeInsets inset = aScrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
float reload_distance = 40;
if(y > h + reload_distance) {
NSLog(#"load more rows");
[self makeRequest:(int)page];
page++;
NSLog(#"currentpage %d",(int)page);
[self.articlesArray addObjectsFromArray:self.articles];
[self.tableView reloadData];
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section==0)
{
return 0;
}
else{
return [self.articlesArray count] + [self.articlesArray count] / 4;
}
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(self.sidebarMenuOpen == YES){
return nil;
} else {
return indexPath;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger row = [indexPath row];
if (3 == (row % 4)) { // or 0 == if you want the first cell to be an ad!
static NSString *MyIdentifier = #"AdCell";
AdViewCell *cell = (AdViewCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if ((cell == nil) || (![cell isKindOfClass: AdViewCell.class]))
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"AdCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell = [[AdViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] ;
}
GADBannerView *bannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeMediumRectangle];
double width = (cell.contentView.frame.size.width/2)-(bannerView.frame.size.width/2);
double heigth = (cell.contentView.frame.size.height/2)-(bannerView.frame.size.height/2);
bannerView =[[GADBannerView alloc] initWithFrame:CGRectMake(width,heigth,300,250)];
bannerView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin);
bannerView.adUnitID = #""; //admob
bannerView.rootViewController =self;
GADRequest *request = [GADRequest request];
[bannerView loadRequest:request];
[cell.contentView addSubview:bannerView];
return cell;
}
else {
static NSString *simpleTableIdentifier = #"ArticleCell";
ArticleViewCell *cell = (ArticleViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier ];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if ((cell == nil) || (![cell isKindOfClass: ArticleViewCell.class]))
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ArticleCell" owner:self options:nil];
cell = [nib objectAtIndex:1];
cell = [[ArticleViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier] ;
}
NSInteger offset = indexPath.row / 4;
NSInteger roww = indexPath.row - offset;
rowww = roww;
NSDictionary * tempDictionary = [self.articlesArray objectAtIndex:roww];
NSString *imageUrl = [[self.articlesArray objectAtIndex:roww]objectForKey:#"featured_image"];
imageUrl = [imageUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[cell.thumbnailImageView sd_setImageWithURL:[NSURL URLWithString:imageUrl ] placeholderImage:nil options:SDWebImageRetryFailed completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (image){
// Set your image over here
}else{
//something went wrong
NSLog(#"Error occured : %#", [error description]);
}
}];
});
NSString * title=[tempDictionary valueForKeyPath:#"title"];
cell.titleLabel.text = title;
return cell;
}
}
- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
[self performSegueWithIdentifier:#"showarticle" sender:self];
}
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the item to be re-orderable.
return NO;
}
#end
thanks
Imagine a UITableView with 10 UITableViewCells.
Once the UITableView loads, it will call tableView:willDisplayCell:forRowAtIndexPath for each cell. Your implementation increments the page number each time this method is called which causes the page number to jump from 1 to page 10. You should get rid of this method.
Instead, you should rely only on the - (void)scrollViewDidScroll:(UIScrollView *)scrollView callback. Try this:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView_
{
CGFloat actualPosition = scrollView_.contentOffset.y;
CGFloat contentHeight = scrollView_.contentSize.height - (self.tableview.frame.size.height);
if (actualPosition >= contentHeight) {
[self makeRequet:++currentPage];
[self.articlesArray addObjectsFromArray:self.articlesArray];
[self.tableView reloadData];
}
You just need to use this
[tableView insertRowsAtIndexPaths:#[indexPathArray]]
in your request completion handler block
and don't forget to increase your count of rows in
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
I am new to iOS development and this is my first project that i am doing alone. i am trying to show the feed of my college's unofficial fb page using uicollectionview. I have been trying a lot of different things but nothing seems to work. The uilabel for the name is not being added to the collection view. However before i added the sizeForLabelAtIndexPath method which is to determine the size of the 2 ui labels and the height of the image to be displayed, the name label was working fine
UICollectionViewController.m file
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"DCE Speaks Up";
self.collectionView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1];
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = NO;
NSError *error= nil;
NSURL *feedURL = [NSURL URLWithString:#"https://graph.facebook.com/382057938566656/feed?fields=id,full_picture,message,story,created_time,link&access_token=1750413825187852%7CkUl9nlZFPvdGxGZX4WYabKKG2G4"];
NSData *jsonData = [NSData dataWithContentsOfURL:feedURL];
NSDictionary *dataDictionary= [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
self.feedArray = [NSMutableArray array];
NSArray *feedTempArray = [dataDictionary objectForKey:#"data"]; //feedTempArray just used for parsing
for (NSDictionary *feedDictionary in feedTempArray) {
FacebookFeed *fbFeed =[FacebookFeed facebookFeedWithMessage:[feedDictionary objectForKey:#"message"]];
fbFeed.story = [feedDictionary objectForKey:#"story"];
fbFeed.imageURL = [NSURL URLWithString:[feedDictionary objectForKey:#"full_picture"]];
fbFeed.date = [feedDictionary objectForKey:#"created_time"];
fbFeed.sharedLink = [NSURL URLWithString:[feedDictionary objectForKey:#"link"]];
[self.feedArray addObject:fbFeed];
}
// Register cell classes
[self.collectionView registerClass:[FacebookCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
// Do any additional setup after loading the view.
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FacebookCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
cell.feed = self.feedArray[indexPath.row];
cell.sizeDictionary = [self sizeForLabelAtIndexPath:indexPath.row collectionView:collectionView];
// Configure the cell
for (UIView *view in cell.contentView.subviews) {
if ([view isKindOfClass:[UILabel class]]) {
[view removeFromSuperview];
}else if ([view isKindOfClass:[UIImageView class]]){
[view removeFromSuperview];
}
}
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
return cell;
}
#pragma mark <UICollectionViewDelegateFlowLayout>
-(CGSize) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *sizeDictionary = [[NSDictionary alloc] init];
sizeDictionary = [self sizeForLabelAtIndexPath:indexPath.row collectionView:collectionView];
return CGSizeMake(self.view.frame.size.width - 20, [sizeDictionary[#"imageHeight"] floatValue] + [sizeDictionary[#"messageHeight"] floatValue] + [sizeDictionary[#"nameHeight"] floatValue]);
}
#pragma mark <UICollectionViewDelegate>
- (NSDictionary *) sizeForLabelAtIndexPath:(NSUInteger)indexPath collectionView:(UICollectionView *)collectionView{
FacebookFeed *feed = self.feedArray[indexPath];
CGSize nameSize = CGSizeFromString(#"DCE Speaks Up");
CGSize imageSize = CGSizeMake(0, 0);
if (feed.imageURL) {
imageSize = CGSizeMake(470, 394);
}
float height = 80;
NSString *string = #"";
if (feed.message) {
string = [feed.message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}else if (feed.story){
string = [feed.story stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
if (string) {
NSDictionary *attributes = #{
NSFontAttributeName : [UIFont preferredFontForTextStyle:UIFontTextStyleBody]
};
CGRect bodyFrame =
[string boundingRectWithSize:CGSizeMake(CGRectGetWidth(collectionView.bounds),
CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin)
attributes:attributes
context:nil];
height += ceilf(CGRectGetHeight(bodyFrame));
}
return #{ #"imageHeight" : #(imageSize.height) , #"messageHeight" : #(height) , #"nameHeight" : #(nameSize.height)};
}
Custom cell file
#implementation FacebookCollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self)
{
self.contentView.backgroundColor = [UIColor whiteColor];
// change to our custom selected background view
self.imageView = [[UIImageView alloc] init];
self.messageLabel = [[UILabel alloc] init];
self.nameLabel = [[UILabel alloc] init];
}
return self;
}
-(void) setFeed:(FacebookFeed *)feed{
_feed = feed;
self.messageLabel.numberOfLines = 0;
self.messageLabel.lineBreakMode = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data= [NSData dataWithContentsOfURL:feed.imageURL];
UIImage *theImage=[UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image= theImage ;
});
});
if (feed.message) {
self.messageLabel.text = [[NSString alloc] initWithString:[feed.message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}else{
self.messageLabel.text = [[NSString alloc] initWithString:[feed.story stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
self.messageLabel.font = [UIFont fontWithName:#"ArialMT" size:11];
[self.messageLabel sizeToFit];
self.nameLabel.text = #"DCE Speaks Up";
[self.nameLabel setFont:[UIFont fontWithName:#"ArialMT" size:12]];
[self.nameLabel sizeToFit];
}
-(void) layoutSubviews{
NSLog(#"%#",self.feed);
self.nameLabel.frame = CGRectMake(10, 10, self.contentView.bounds.size.width, [self.sizeDictionary[#"nameHeight"] floatValue]);
float height = 200;
if (self.contentView.bounds.size.height - [self.sizeDictionary[#"messageHeight"] floatValue] -[self.sizeDictionary[#"nameHeight"] floatValue] >100) {
height = self.contentView.bounds.size.height - [self.sizeDictionary[#"messageHeight"] floatValue] -[self.sizeDictionary[#"nameHeight"] floatValue];
}
if (self.feed.imageURL) {
self.imageView.frame = CGRectMake(10, [self.sizeDictionary[#"messageHeight"] floatValue] +[self.sizeDictionary[#"nameHeight"] floatValue], self.contentView.bounds.size.width - 20,height);
self.messageLabel.frame = CGRectMake(10, [self.sizeDictionary[#"nameHeight"] floatValue] +10, self.contentView.bounds.size.width - 10, [self.sizeDictionary[#"messageHeight"] floatValue]);
[self.contentView addSubview:self.messageLabel];
[self.contentView addSubview:self.imageView];
}else{
self.messageLabel.frame = CGRectMake(10, [self.sizeDictionary[#"nameHeight"] floatValue], self.contentView.bounds.size.width - 10, [self.sizeDictionary[#"messageHeight"] floatValue]);
[self.contentView addSubview:self.messageLabel];
}
[self.contentView addSubview:self.nameLabel];
}
#end
I am new to iOS development and this is my first project that i am doing alone. i am trying to show the feed of my college's unofficial fb page using uicollectionview. I have been trying a lot of different things but nothing seems to work.
UICollectionViewController.m file
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"DCE Speaks Up";
self.collectionView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1];
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = NO;
NSError *error= nil;
NSURL *feedURL = [NSURL URLWithString:#"https://graph.facebook.com/382057938566656/feed?fields=id,full_picture,message,story,created_time,link&access_token=1750413825187852%7CkUl9nlZFPvdGxGZX4WYabKKG2G4"];
NSData *jsonData = [NSData dataWithContentsOfURL:feedURL];
NSDictionary *dataDictionary= [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
self.feedArray = [NSMutableArray array];
NSArray *feedTempArray = [dataDictionary objectForKey:#"data"]; //feedTempArray just used for parsing
for (NSDictionary *feedDictionary in feedTempArray) {
FacebookFeed *fbFeed =[FacebookFeed facebookFeedWithMessage:[feedDictionary objectForKey:#"message"]];
fbFeed.story = [feedDictionary objectForKey:#"story"];
fbFeed.imageURL = [NSURL URLWithString:[feedDictionary objectForKey:#"full_picture"]];
fbFeed.date = [feedDictionary objectForKey:#"created_time"];
fbFeed.sharedLink = [NSURL URLWithString:[feedDictionary objectForKey:#"link"]];
[self.feedArray addObject:fbFeed];
}
// Register cell classes
[self.collectionView registerClass:[FacebookCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
// Do any additional setup after loading the view.
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FacebookCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
cell.feed = self.feedArray[indexPath.row];
cell.sizeDictionary = [self sizeForLabelAtIndexPath:indexPath.row collectionView:collectionView];
// Configure the cell
for (UIView *view in cell.contentView.subviews) {
if ([view isKindOfClass:[UILabel class]]) {
[view removeFromSuperview];
}else if ([view isKindOfClass:[UIImageView class]]){
[view removeFromSuperview];
}
}
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
return cell;
}
#pragma mark <UICollectionViewDelegateFlowLayout>
-(CGSize) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *sizeDictionary = [[NSDictionary alloc] init];
sizeDictionary = [self sizeForLabelAtIndexPath:indexPath.row collectionView:collectionView];
return CGSizeMake(self.view.frame.size.width - 20, [sizeDictionary[#"imageHeight"] floatValue] + [sizeDictionary[#"messageHeight"] floatValue] + [sizeDictionary[#"nameHeight"] floatValue]);
}
#pragma mark <UICollectionViewDelegate>
- (NSDictionary *) sizeForLabelAtIndexPath:(NSUInteger)indexPath collectionView:(UICollectionView *)collectionView{
FacebookFeed *feed = self.feedArray[indexPath];
CGSize nameSize = CGSizeFromString(#"DCE Speaks Up");
CGSize imageSize = CGSizeMake(0, 0);
if (feed.imageURL) {
imageSize = CGSizeMake(470, 394);
}
float height = 80;
NSString *string = #"";
if (feed.message) {
string = [feed.message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}else if (feed.story){
string = [feed.story stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
if (string) {
NSDictionary *attributes = #{
NSFontAttributeName : [UIFont preferredFontForTextStyle:UIFontTextStyleBody]
};
CGRect bodyFrame =
[string boundingRectWithSize:CGSizeMake(CGRectGetWidth(collectionView.bounds),
CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin)
attributes:attributes
context:nil];
height += ceilf(CGRectGetHeight(bodyFrame));
}
return #{ #"imageHeight" : #(imageSize.height) , #"messageHeight" : #(height) , #"nameHeight" : #(nameSize.height)};
}
Custom cell file
#implementation FacebookCollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self)
{
self.contentView.backgroundColor = [UIColor whiteColor];
// change to our custom selected background view
self.imageView = [[UIImageView alloc] init];
self.messageLabel = [[UILabel alloc] init];
self.nameLabel = [[UILabel alloc] init];
}
return self;
}
-(void) setFeed:(FacebookFeed *)feed{
_feed = feed;
self.messageLabel.numberOfLines = 0;
self.messageLabel.lineBreakMode = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data= [NSData dataWithContentsOfURL:feed.imageURL];
UIImage *theImage=[UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image= theImage ;
});
});
if (feed.message) {
self.messageLabel.text = [[NSString alloc] initWithString:[feed.message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}else{
self.messageLabel.text = [[NSString alloc] initWithString:[feed.story stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
self.messageLabel.font = [UIFont fontWithName:#"ArialMT" size:11];
[self.messageLabel sizeToFit];
self.nameLabel.text = #"DCE Speaks Up";
[self.nameLabel setFont:[UIFont fontWithName:#"ArialMT" size:12]];
[self.nameLabel sizeToFit];
}
-(void) layoutSubviews{
NSLog(#"%#",self.feed);
self.nameLabel.frame = CGRectMake(10, 10, self.contentView.bounds.size.width, [self.sizeDictionary[#"nameHeight"] floatValue]);
float height = 200;
if (self.contentView.bounds.size.height - [self.sizeDictionary[#"messageHeight"] floatValue] -[self.sizeDictionary[#"nameHeight"] floatValue] >100) {
height = self.contentView.bounds.size.height - [self.sizeDictionary[#"messageHeight"] floatValue] -[self.sizeDictionary[#"nameHeight"] floatValue];
}
if (self.feed.imageURL) {
self.imageView.frame = CGRectMake(10, [self.sizeDictionary[#"messageHeight"] floatValue] +[self.sizeDictionary[#"nameHeight"] floatValue], self.contentView.bounds.size.width - 20,height);
self.messageLabel.frame = CGRectMake(10, [self.sizeDictionary[#"nameHeight"] floatValue] +10, self.contentView.bounds.size.width - 10, [self.sizeDictionary[#"messageHeight"] floatValue]);
[self.contentView addSubview:self.messageLabel];
[self.contentView addSubview:self.imageView];
}else{
self.messageLabel.frame = CGRectMake(10, [self.sizeDictionary[#"nameHeight"] floatValue], self.contentView.bounds.size.width - 10, [self.sizeDictionary[#"messageHeight"] floatValue]);
[self.contentView addSubview:self.messageLabel];
}
[self.contentView addSubview:self.nameLabel];
}
#end
Use NSLayoutConstraints, it's the standard and best practice. Also you shouldn't be adding subviews in layoutSubviews(), as this method may get called multiple times. I'd also suggest moving your cell size calculation code into your UICollectionViewCell subclass.
There is a lot of odd stuff going on in your code, so it's hard to tell what's causing your problems. It's probably a combination of all of the subview adding/removing and manual size calculations. You could also use the visual debugger to give you some clues as to what might be happening:
https://www.raywenderlich.com/98356/view-debugging-in-xcode-6
I believe your problem is here:
-(CGSize) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *sizeDictionary = [[NSDictionary alloc] init];
sizeDictionary = [self sizeForLabelAtIndexPath:indexPath.row collectionView:collectionView];
return CGSizeMake(self.view.frame.size.width - 20, [sizeDictionary[#"imageHeight"] floatValue] + [sizeDictionary[#"messageHeight"] floatValue] + [sizeDictionary[#"nameHeight"] floatValue]);
}
You set in CGSizeMake width:
self.view.frame.size.width - 20
And height:
[sizeDictionary[#"imageHeight"] floatValue] + [sizeDictionary[#"messageHeight"] floatValue] + [sizeDictionary[#"nameHeight"] floatValue]
Check it out if the size of your height it's correct. It looks like is too big. That method return the size of the each cell. I believe you have been setting a bigger height than you want to.
I'm working with UICollectionView and I have a main class and another one which is a subclass of UICollectionViewFlowLayout. The thing it's that the cell's width and height in main class it's 0. In subclass the cell have the right size.
Here's some code:
The FlowLayoutSubClass
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes* currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
if (!currentItemAttributes) {
currentItemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
}
CGFloat containerWidth = self.collectionView.frame.size.width;
CGFloat cellWidth = containerWidth / 2.0f - 1.0f;
CGFloat baseHeight = containerWidth / 4.0f;
CGRect frame = [self frameForIndexPath:indexPath];
if (CGRectEqualToRect(frame, CGRectZero)) {
ArtworkModel *currentObject = [self.artworksArray objectAtIndex:indexPath.row];
CGFloat height = currentObject.height;
frame.origin = [self getNextFreePosition];
frame.size.width = cellWidth;
frame.size.height = 120 + arc4random() % (200 - 120);
[self saveFrame:frame forIndexPath:indexPath];
[self saveFrame:frame];
}
currentItemAttributes.frame = frame;
currentItemAttributes.size = frame.size;
return currentItemAttributes;
}
- (CGRect)frameForIndexPath:(NSIndexPath *)indexPath {
CGRect frame = CGRectZero;
NSString *key = [NSString stringWithFormat:#"%ld-%ld", (long)indexPath.section, (long)indexPath.row];
NSString *frameString = [self.framesByIndexPath objectForKey:key];
if (frameString) {
frame = CGRectFromString(frameString);
}
return frame;
}
- (void)saveFrame:(CGRect)frame forIndexPath:(NSIndexPath *)indexPath {
if (!self.framesByIndexPath) {
self.framesByIndexPath = [[NSMutableDictionary alloc] init];
}
NSString *key = [NSString stringWithFormat:#"%d-%d", indexPath.section, indexPath.row];
[self.framesByIndexPath setObject:NSStringFromCGRect(frame) forKey:key];
}
- (CGPoint)getNextFreePosition {
CGFloat containerWidth = self.collectionView.frame.size.width;
CGFloat cellWidth = containerWidth / 2.0f;
CGPoint point = CGPointZero;
NSArray *leftFrames = [self.framesDictionary valueForKey:#"left"];
NSArray *rightFrames = [self.framesDictionary valueForKey:#"right"];
NSString *lastLeftFrameString = [leftFrames lastObject];
NSString *lastRightFrameString = [rightFrames lastObject];
if (lastLeftFrameString == nil) {
// There is no frame saved yet, so this will be the first
point.x = 0.0f;
point.y = 0.0f;
} else {
if (lastRightFrameString == nil) {
// There is no item on the right side
point.x = cellWidth;
point.y = 0.0f;
} else {
// There are items on both left and right sides...
// Check which one has the smallest Y component
CGRect leftFrame = CGRectFromString(lastLeftFrameString);
CGRect rightFrame = CGRectFromString(lastRightFrameString);
if (CGRectGetMaxY(leftFrame) <= CGRectGetMaxY(rightFrame)) {
// We put this one on the left
point.x = 0.0f;
point.y = CGRectGetMaxY(leftFrame);
} else {
point.x = cellWidth;
point.y = CGRectGetMaxY(rightFrame);
}
}
}
return point;
}
- (void)saveFrame:(CGRect)frame {
if (!self.framesDictionary) {
self.framesDictionary = [[NSMutableDictionary alloc] init];
}
NSString *sideKey = nil;
if (CGRectGetMinX(frame) == 0.0f) {
// left
sideKey = #"left";
} else {
sideKey = #"right";
}
NSMutableArray *frames = [self.framesDictionary objectForKey:sideKey];
if (!frames) {
frames = [[NSMutableArray alloc] init];
[self.framesDictionary setObject:frames forKey:sideKey];
}
[frames addObject:NSStringFromCGRect(frame)];
}
#end
and the main class:
- (void)takeAllArtworks {
[WaitingView showWaitingView:shadowView WithIndicator:indicatorActivity];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSMutableString *requestURL = [[NSMutableString alloc] init];
[requestURL appendFormat:#"%#%#", BASE_URL_ARTWORK, GET_ARTWORKS];
// NSInteger screenWidth = self.view.frame.size.width / 2.0f;
[manager GET:requestURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([[responseObject objectForKey: #"status"] integerValue] == 0) {
NSArray *artworks = [responseObject objectForKey:#"Data"];
if ([artworks count] > 0) {
for (NSDictionary *dict in artworks) {
ArtworkModel *artwork = [[ArtworkModel alloc] init];
if ([dict objectForKey:#"Title"] != [NSNull null]) {
artwork.title = [dict objectForKey:#"Title"];
}
if ([dict objectForKey:#"Description"] != [NSNull null]) {
artwork.descriptionAlbum = [dict objectForKey:#"Description"];
}
if ([dict objectForKey:#"ArtistName"] != [NSNull null]) {
artwork.artistName = [dict objectForKey:#"ArtistName"];
}
NSString *dateAdded = [[dict objectForKey:#"DateAdded"] substringWithRange:NSMakeRange(0, 19)];
NSString *dateUpdated = [[dict objectForKey:#"DateUpdated"] substringWithRange:NSMakeRange(0, 19)];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss"];
NSDate *dateAd = [formatter dateFromString:dateAdded];
NSDate *dateUp = [formatter dateFromString:dateUpdated];
NSString *result;
if ([dateAd compare:dateUp] == NSOrderedAscending) {
result = [NSString stringWithFormat:#"edited %#", [self relativeDateStringForDate:dateUp]];
} else {
result = [self relativeDateStringForDate:dateAd];
}
artwork.dateAdded = result;
if ([dict objectForKey:#"MediaItems"] != [NSNull null]) {
NSArray *mediaArray = [dict objectForKey:#"MediaItems"];
if ([mediaArray count] > 0) {
for (NSDictionary *mediaDict in mediaArray) {
// NSString *endpoint = [NSString stringWithFormat:#"%#.ashx?w=%ld&h=%d&mode=crop", [mediaDict objectForKey:#"Url"], (long)screenWidth, 170];
NSString *endpoint = [mediaDict objectForKey:#"Url"];
NSString *imageURL = [NSString stringWithFormat:#"%#%#", IMAGE_BASE_URL, endpoint];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]];
[artwork.imageUrls addObject:[UIImage imageWithData:data]];
}
}
}
[listOfArtworks addObject:artwork];
}
FBFlowLayout *layout = [[FBFlowLayout alloc] initWithArtworks:listOfArtworks];
[layout setMinimumInteritemSpacing:0.5f];
[layout setMinimumLineSpacing:0.5f];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
[artworkCollectionView reloadData];
artworkCollectionView.collectionViewLayout = layout;
[WaitingView hideWaitingView:shadowView WithIndicator:indicatorActivity];
} else {
[WaitingView hideWaitingView:shadowView WithIndicator:indicatorActivity];
}
}
else
[WaitingView hideWaitingView:shadowView WithIndicator:indicatorActivity];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Faild");
[WaitingView hideWaitingView:shadowView WithIndicator:indicatorActivity];
}];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [listOfArtworks count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
FBWorkartCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"WorkartCollection" forIndexPath: indexPath];
ArtworkModel *artworkModel = (ArtworkModel *)[listOfArtworks objectAtIndex:indexPath.row];
cell.nameAlbumLabel.text = artworkModel.title;
cell.nameArtistLabel.text = artworkModel.artistName;
if ([artworkModel.imageUrls count] > 0) {
cell.coverAlbumPhoto.image = [artworkModel.imageUrls objectAtIndex:0];
}
cell.shadowView.alpha = 0.9;
cell.dateLabel.text = artworkModel.dateAdded;
CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0
CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white
CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black
UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1];
cell.backgroundColor = color;
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
ArtworkModel *artworkModel = (ArtworkModel *)[listOfArtworks objectAtIndex:indexPath.row];
FBWorkDetailsViewController *dvc = [[FBWorkDetailsViewController alloc] initWithArtwork:artworkModel];
FBLeftMenuViewController *left = [[FBLeftMenuViewController alloc] init];
MFSideMenuContainerViewController *container = [MFSideMenuContainerViewController
containerWithCenterViewController: dvc
leftMenuViewController: left
rightMenuViewController:nil
withHeader: YES];
[container.titleLabel setText:#"WORK DETAILS"];
[self.navigationController pushViewController: container animated: YES];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return [collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath].size;
}
First of all if you have a subclass of UIcollectionViewLayout, why not set in in the Storyboard
Second, your
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return [collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath].size;
}
is redundant, have you tried to make an NSLog before return on [collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath].size; does it return a valid size?
Im trying to make dynamic uitableviewcell height for my custome cell.
the cell is subclassed for adding some background.
this is my uitableview controller class :
#define PADDING 23.0f
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSUInteger count = [self.entries count];
return count + _rowcount;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *reuseIdentifier = #"PlaceholderCell2";
SubcategoryTableViewCell * sctvCell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (sctvCell == nil) {
sctvCell= [[SubcategoryTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
}
NSUInteger nodeCount = [self.entries count];
sctvCell.contentView.translatesAutoresizingMaskIntoConstraints = NO;
UILabel *label = (UILabel *)[sctvCell.contentView viewWithTag:1];
if (nodeCount > 0)
{
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
[label setText:appRecord.title];
NSDictionary *attributes = #{NSFontAttributeName: [UIFont fontWithName:#"B MyFont" size:14.0f]};
CGRect rect = [appRecord.title boundingRectWithSize:CGSizeMake(label.frame.size.height - PADDING * 5, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
CGRect newFrame = label.frame;
newFrame.size.height = rect.size.height;
label.frame = newFrame;
[label sizeToFit];
UIView *whiteRoundedCornerView = (UIView *)[sctvCell.contentView viewWithTag:1000];
CGRect newFrame2 = whiteRoundedCornerView.frame;
newFrame2.size.width = 300;
newFrame2.size.height = rect.size.height + 160;
[ whiteRoundedCornerView setFrame:newFrame2];
}
if ((unsigned long)indexPath.row == [self.entries count] - 1){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
NewsFetchParseOperation *p = [[NewsFetchParseOperation alloc]init];
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
p.cat = appRecord.Category;
self.intindex = self.intindex + 1;
p.index = [NSString stringWithFormat:#"%d", (int)self.intindex];
p.lastid = appRecord.ids;
[p main];
dispatch_async(dispatch_get_main_queue(), ^(void)
{
[self.tableView beginUpdates];
NSMutableArray *indexPaths = [NSMutableArray array];
NSInteger currentCount = self.entries.count;
for (NSUInteger i = 0; i < p.appRecordList.count; i++) {
[indexPaths addObject:[NSIndexPath indexPathForRow:currentCount+i inSection:0]];
}
NSArray *temp_1 =[self.entries arrayByAddingObjectsFromArray:p.appRecordList];
self.entries = temp_1;
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView endUpdates];
});
});
}
return sctvCell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *reuseIdentifier = #"PlaceholderCell2";
SubcategoryTableViewCell * sctvCell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (sctvCell == nil) {
sctvCell= [[SubcategoryTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
}
NewsFetchAppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
UILabel *label = (UILabel *)[sctvCell.contentView viewWithTag:1];
NSDictionary *attributes = #{NSFontAttributeName: [UIFont fontWithName:#"B MyFont" size:14.0f]};
CGRect rect = [appRecord.title boundingRectWithSize:CGSizeMake(label.frame.size.height - PADDING * 5, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
return rect.size.height + PADDING * 6;
}
and my cell subclass :
- (void)awakeFromNib {
self.news_img.layer.cornerRadius = 4;
self.news_img.clipsToBounds = YES;
self.resource_icon_img.layer.cornerRadius = 4;
self.resource_icon_img.clipsToBounds = YES;
self.contentView.backgroundColor = [UIColor clearColor];
self.whiteroundcorner = [[UIView alloc] initWithFrame:CGRectMake(10,10,300,250)];
self.whiteroundcorner.backgroundColor = [UIColor whiteColor];
self.whiteroundcorner.layer.masksToBounds = NO;
self.whiteroundcorner.layer.cornerRadius = 3.0;
[self.whiteroundcorner.layer setShadowColor:[UIColor grayColor].CGColor];
self.whiteroundcorner.layer.shadowOffset = CGSizeMake(-1, 1);
self.whiteroundcorner.layer.shadowOpacity = 0.2;
self.whiteroundcorner.tag = 1000;
[self.contentView addSubview:self.whiteroundcorner];
[self.contentView sendSubviewToBack:self.whiteroundcorner];
}
im using story board for my table like this :
now problem is most of time the height calculated incorrectly.
also some time the height goes way beyond on cell and in the end of 10 cell
when i try to fetch new row the last cell apears incorrectly.
You will need to calculate the height for the cell after setting its content.
So something like this:
- (CGFloat)heightForCellAtIndexPath:(NSIndexPath *)indexPath {
static UITableViewCell *sizingCell = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sizingCell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
});
/* Method where you set the content of the cell */
[self configureCell: atIndexPath:indexPath];
return [self calculateHeightForConfiguredSizingCell:sizingCell];
}
- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
[sizingCell setNeedsDisplay];
[sizingCell layoutIfNeeded];
CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height;
}