I have an UIViewController which contains a UICollectionView. But the UICollectionView does not fill all the UIViewController.
I find that there is space whose height equals the height of NavigationBar between the cell and the top edge of the UICollectionView. I don't know how I can set the cell position to (0,0) in the UICollectionView. (like this, the space is in the red rectangle)
I found this link How do I set the position of a UICollectionViewCell? And I subclass UICollectionViewFlowLayout (the following are my code)
MZMCollectionViewFlowLayout.h
#import <UIKit/UIKit.h>
#interface MZMCollectionViewFlowLayout : UICollectionViewFlowLayout
#end
MZMCollectionViewFlowLayout.m
#import "MZMCollectionViewFlowLayout.h"
#implementation MZMCollectionViewFlowLayout
- (CGSize)collectionViewContentSize
{
return [super collectionViewContentSize];
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
return [super layoutAttributesForElementsInRect:rect];
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"MZMCollectionViewFlowLayout layoutAttributesForItemAtIndexPath");
if (indexPath.section == 0 && indexPath.row == 1) // or whatever specific item you're trying to override
{
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
layoutAttributes.frame = CGRectMake(0,0,100,100); // or whatever...
return layoutAttributes;
}
else
{
return [super layoutAttributesForItemAtIndexPath:indexPath];
}
}
#end
and using it like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// hide the tool bar
[self.navigationController setToolbarHidden:YES animated:YES];
// set title
self.navigationItem.title = #"User Album";
[self.userAlbumView setCollectionViewLayout:[[MZMCollectionViewFlowLayout alloc] init]];
}
But it does not work. The log NSLog(#"MZMCollectionViewFlowLayout layoutAttributesForItemAtIndexPath"); doesn't show. And the blank is still there.
Thanks for any help!
FYI, this is answered more correctly here: UICollectionView adds top margin
The problem is the view controller is automatically adjusting scroll view insets. That can be turned off either in code or IB. In code just set:
self.automaticallyAdjustsScrollViewInsets = NO;
Answer myself question.
I printed every UICollectionViewLayoutAttribute information in layoutAttributesForElementsInRect: and found what I need is to change the frame.orgin.y
following is my code:
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:[attributes count]];
for (int i=0; i< [attributes count]; i++) {
UICollectionViewLayoutAttributes *attr = (UICollectionViewLayoutAttributes *)[attributes objectAtIndex:i];
// the key code "attr.frame.origin.y - 63"
[attr setFrame:CGRectMake(attr.frame.origin.x, attr.frame.origin.y - 63, attr.bounds.size.width, attr.bounds.size.height)];
//NSLog(#"attr h=%f w=%f x=%f y=%f", attr.bounds.size.height, attr.bounds.size.width, attr.frame.origin.x, attr.frame.origin.y);
[result addObject:attr];
}
return result;
}
then it works fine.
Related
If I modified any attribute property in layoutAttributesForItemAtIndexPath the collectionView cell does not get modified
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForItemAtIndexPath:indexPath];
//this properties does not get applied
attributes.zIndex = 1;
attributes.alpha = 0.5;
return attributes;
}
but when moving the properties modifications to layoutAttributesForElementsInRect it gets applied:
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributesArray = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes *attributes in attributesArray)
{
//this properties is getting applied here
attributes.zIndex = 1;
attributes.alpha = 0.5;
}
return attributesArray;
}
I'am applying a UIPanGestureRecognizer on the UICollectionView and I want to apply these
properties on the cell I'am currently dragging.
I'am able to call layoutAttributesForItemAtIndexPath method while I'am dragging through calling this method:
[customLayoutInstance indexOfItemSelected:indexPath.row];
layoutAttributesForItemAtIndexPath is called as long as I'am dragging but the properties does not get applied.
you should override one more method:
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
{
I am writing my own custom layout collection view layout (minor customizations to flow layout) and to simplify a few things I am trying to subclass UICollectionViewFlowLayoutAttributes too. Everything is working perfectly fine but when I try to apply my layout attributes in my custom cell every attribute is nil.
Cell (attributes are all nil here):
- (void)applyLayoutAttributes:(CustomLayoutAttributes *)layoutAttributes
{
[super applyLayoutAttributes:layoutAttributes];
NSLog(#"layoutAttributes %#", layoutAttributes.description);
}
Custom Flow Layout (Attributes being applied perfectly!!!):
+ (Class)layoutAttributesClass
{
return [CustomLayoutAttributes class];
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributesInRect = [super layoutAttributesForElementsInRect:rect];
[attributesInRect enumerateObjectsUsingBlock:^(CustomLayoutAttributes *layoutAttributes, NSUInteger idx, BOOL *stop) {
if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
[self configureLayoutAttributes:layoutAttributes];
}
}];
return attributesInRect;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomLayoutAttributes *layoutAttributes = (CustomLayoutAttributes *)[super layoutAttributesForItemAtIndexPath:indexPath];
if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
[self configureLayoutAttributes:layoutAttributes];
}
return layoutAttributes;
}
- (void)configureLayoutAttributes:(CustomLayoutAttributes *)layoutAttributes
{
CustomCollectionView *collectionView = (CustomCollectionView *)self.collectionView;
layoutAttributes.messageTopLabelHeight = 20.0;
layoutAttributes.messageBottomLabelHeight = 20.0;
layoutAttributes.messageBubbleFont = _messageBubbleFont;
}
Am I doing something wrong or missing something? :).
Note: I created all my cells in a storyboard, and set my custom layout in storyboard as well.
Thanks guys.
figured out the problem...apparently UICollectionViewLayoutAttributes must conform to NSCopying and implement copyWithZone:. After doing that everything worked perfectly.
I have a UICollectionView that when a cell is pressed, there will be a new set of data and will animate the flow layout.
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for(int i=0;i<200;i++)
{
[tempArray addObject:[NSNumber numberWithInt:i]];
}
items = [NSArray arrayWithArray:tempArray];
CollapseLayout *currentLayout = (CollapseLayout *)_collectionView.collectionViewLayout;
currentLayout.collapse = YES;
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.collectionView.numberOfSections)]];
} completion:nil];
}
It is using a Custom UICollectionViewFlowLayout that performs an animation when reloading the data.
My CustomFlowLayout Class is here
#import "CollapseLayout.h"
#implementation CollapseLayout
- (void)prepareLayout {
self.itemSize = CGSizeMake(200, 100);
self.minimumInteritemSpacing = 30;
self.scrollDirection = UICollectionViewScrollDirectionVertical;
}
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray* allAttributesInRect = [super layoutAttributesForElementsInRect:rect];
if(_collapse)
{
for(UICollectionViewLayoutAttributes *attribute in allAttributesInRect)
{
attribute.frame = CGRectMake(attribute.frame.origin.x - self.collectionView.frame.size.width, attribute.frame.origin.y, attribute.frame.size.width, attribute.frame.size.height);
}
}
return allAttributesInRect;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes* allAttributesInRect = [super layoutAttributesForItemAtIndexPath:indexPath];
if(_collapse)
{
allAttributesInRect.frame = CGRectMake(allAttributesInRect.frame.origin.x - self.collectionView.frame.size.width, allAttributesInRect.frame.origin.y, allAttributesInRect.frame.size.width, allAttributesInRect.frame.size.height);
}
return allAttributesInRect;
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
- (UICollectionViewLayoutAttributes*)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath*)itemIndexPath
{
UICollectionViewLayoutAttributes* layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:itemIndexPath];
return layoutAttributes;
}
- (void)invalidateLayout
{
}
The BOOL
_collapse
is set is called in my collection view to trigger the animation. I am hoping to have the old cells, move from left to right, outside the view, and the new cells animate in from the right side of the screen. Right now, the cells are just moving off screen.
My issue is that the code in layoutAttributesForItemAtIndexPath and layoutAttributesForElementsInRect are not animating correctly. Would adding the animation code in these methods be the best place to perform the animations, or im totally off?
Thanks
You shouldn't do anything to the result of
[super layoutAttributesForItemAtIndexPath:indexPath];
nor
[super layoutAttributesForElementsInRect:rect];
If you want your cells to animate from where they are to off the screen, then you need to modify only their "final" position by overriding finalAttributesForDisappearingElementAtIndexPath:, but not their "regular position".
If you want them to come back from the side of the screen then you need to modify their position through initialLayoutAttributesForAppearingItemAtIndexPath:
I am creating one application based on FMMoveTableView where I have to drag cell on long press and change its position with in same section and different section.The cell is dragging fine and setting in the same and different section.But the problem is when I start dragging the cell upwards the table also starts scrolling up.So some of its cells are invisible because of bounce where we want to keep the dragged cell.The same thing is happening when I drag the cell to the bottom.
Is it anything related to UITableView property or I have to do it programmatically?
The app FMMoveTableView which I followed for this functionality,it is working fine where it is using UITableView class type.I implemented it in UIViewController class where I made some other views.
UITableView Properties:
self.GroupedTableView=[[UITableView alloc]initWithFrame:CGRectMake(20, 25, 280, 480) style:UITableViewStylePlain];
self.GroupedTableView.showsHorizontalScrollIndicator=YES;
self.GroupedTableView.showsVerticalScrollIndicator=YES;
self.GroupedTableView.bounces=YES;
self.GroupedTableView.alwaysBounceHorizontal=NO;
self.GroupedTableView.alwaysBounceVertical=YES;
self.GroupedTableView.bouncesZoom=YES;
self.GroupedTableView.delaysContentTouches=YES;
self.GroupedTableView.canCancelContentTouches=YES;
self.GroupedTableView.userInteractionEnabled=YES;
self.GroupedTableView.dataSource=self;
self.GroupedTableView.delegate=self;
self.GroupedTableView.rowHeight=30;
self.GroupedTableView.backgroundColor=[UIColor clearColor];
self.GroupedTableView.tag=202;
[self.view addSubview:self.GroupedTableView];
Long Press Gesture:
UILongPressGestureRecognizer *movingGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
[movingGestureRecognizer setDelegate:self];
[self.GroupedTableView addGestureRecognizer:movingGestureRecognizer];
Auto Scroll Methods:
- (void)legalizeAutoscrollDistance
{
float minimumLegalDistance = [self.GroupedTableView contentOffset].y * -1;
float maximumLegalDistance = [self.GroupedTableView contentSize].height - ([self.GroupedTableView frame].size.height + [self.GroupedTableView contentOffset].y);
[self setAutoscrollDistance:MAX([self autoscrollDistance], minimumLegalDistance)];
[self setAutoscrollDistance:MIN([self autoscrollDistance], maximumLegalDistance)];
}
- (void)stopAutoscrolling
{
[self setAutoscrollDistance:0];
[[self autoscrollTimer] invalidate];
[self setAutoscrollTimer:nil];
}
- (void)maybeAutoscrollForSnapShotImageView:(FMSnapShotImageView *)snapShot
{
[self setAutoscrollDistance:0];
NSLog(#"Height====%f",[self.GroupedTableView frame].size.height);
NSLog(#"Height====%f",[self.GroupedTableView contentSize].height);
NSLog(#"Frame====%#",NSStringFromCGRect([snapShot frame]));
NSLog(#"Frame====%#",NSStringFromCGRect([self.GroupedTableView bounds]));
// Check for autoscrolling
// 1. The content size is bigger than the frame's
// 2. The snap shot is still inside the table view's bounds
if ([self.GroupedTableView frame].size.height < [self.GroupedTableView contentSize].height && CGRectIntersectsRect([snapShot frame], [self.GroupedTableView bounds]))
{
CGPoint touchLocation = [[self movingGestureRecognizer] locationInView:self.GroupedTableView];
touchLocation.y += [self touchOffset].y;
float distanceToTopEdge = touchLocation.y - CGRectGetMinY([self.GroupedTableView bounds]);
float distanceToBottomEdge = CGRectGetMaxY([self.GroupedTableView bounds]) - touchLocation.y;
if (distanceToTopEdge < [self autoscrollThreshold])
{
[self setAutoscrollDistance:[self autoscrollDistanceForProximityToEdge:distanceToTopEdge] * -1];
}
else if (distanceToBottomEdge < [self autoscrollThreshold])
{
[self setAutoscrollDistance:[self autoscrollDistanceForProximityToEdge:distanceToBottomEdge]];
}
}
if ([self autoscrollDistance] == 0)
{
[[self autoscrollTimer] invalidate];
[self setAutoscrollTimer:nil];
}
else if (![self autoscrollTimer])
{
NSTimer *autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60.0) target:self selector:#selector(autoscrollTimerFired:) userInfo:snapShot repeats:YES];
[self setAutoscrollTimer:autoscrollTimer];
}
}
- (void)autoscrollTimerFired:(NSTimer *)timer
{
[self legalizeAutoscrollDistance];
CGPoint contentOffset = [self.GroupedTableView contentOffset];
contentOffset.y += [self autoscrollDistance];
[self.GroupedTableView setContentOffset:contentOffset];
// Move the snap shot appropriately
FMSnapShotImageView *snapShot = (FMSnapShotImageView *)[timer userInfo];
[snapShot moveByOffset:CGPointMake(0, [self autoscrollDistance])];
// Even if we autoscroll we need to update the moved cell's index path
CGPoint touchLocation = [[self movingGestureRecognizer] locationInView:self.GroupedTableView];
[self moveRowToLocation:touchLocation];
}
- (float)autoscrollDistanceForProximityToEdge:(float)proximity
{
return ceilf(([self autoscrollThreshold] - proximity) / 5.0);
}
I am unable to stop tableview scroll when I drag a cell.What I need that table should not move till the dragged cell has not reached to the top or bottom and then it should scroll to show hidden Cells.
// // ViewController.h // testingApp
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UILongPressGestureRecognizer *reco; }
#property (nonatomic, weak) IBOutlet UITableView *table;
#end
//
// ViewController.m
// testingApp
#import "ViewController.h"
#implementation ViewController
#synthesize table;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
reco = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(recognize:)];
[self.table addGestureRecognizer:reco];
}
-(void)recognize:(id)sender
{
NSLog(#"recognize");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
return cell;
}
#end
I have got the solution.Actually I am using some gestures on my table view cell.So to enable this along with other gestures I was using:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
So this was actually activating the UITableView gestures too when it was not needed.And so When I dragged the cell Image my table also started scrolling along with the image.I misinterpreted it as my implementation for row sliding has got some issue.So code used in question works is fine if someone needs it in future.What I did is added some conditions in the above method and activated it when it was needed.
I have a UIScrollView within a UITableViewCell for being able to scroll through images within a cell. However, as a cell is reused the scroll position/content is reloaded and therefore the cell doesn't remember what scroll position (page) it was on when it comes into view again.
What's the best way to have a scroll view within a UITableView cell and have it maintain position as it comes back into view. The AirBnB app (https://itunes.apple.com/us/app/airbnb/id401626263?mt=8) seems to have accomplished this for example.
You need to keep track of your scroll views' content offset in a property. In the example below, I do this with a mutable dictionary. In cellForRowAtIndexPath:, I give the scroll view a tag and set the controller as the delegate. In the scroll view delegate method, scrollViewDidEndDecelerating:, the scroll view's content offset is set as the object for the key corresponding to the scroll view's tag. In cellForRowAtIndexPath:, I check for whether the indexPath.row (converted to an NSNumber) is one of the keys of the dictionary, and if so, restore the correct offset for that scroll view. The reason I add 1 to the tags is because the table view has its own scroll view which has a tag of 0, so I don't want to use 0 as a tag for one of the cell's scroll views.
So in cellForRowAtIndexPath, you need something like this:
cell.scrollView.tag = indexPath.row + 1;
cell.scrollView.delegate = self;
if ([self.paths.allKeys containsObject:#(indexPath.row + 1)]) {
cell.scrollView.contentOffset = CGPointMake([self.paths[#(indexPath.row + 1)] floatValue],0);
}else{
cell.scrollView.contentOffset = CGPointZero;
}
return cell;
And in the delegate method:
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
if (scrollView.tag != 0)
[self.paths setObject:#(scrollView.contentOffset.x) forKey:#(scrollView.tag)];
}
paths is a property (NSMutableDictionary) that I create in viewDidLoad.
Use my tableView customs cells
homeScrollCell.h
#import <UIKit/UIKit.h>
#import "MyManager.h"
#interface homeScrollCell : UITableViewCell<UIScrollViewDelegate>
{
MyManager *manager;
UIScrollView *__scrollView;
}
-(void)setPage:(int)page;
#property int currentPage;
#end
homeScrollCell.m
#import "homeScrollCell.h"
#implementation homeScrollCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
manager=[MyManager sharedManager];
__scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width,self.bounds.size.height)];
[__scrollView setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
NSInteger viewcount= 3;
for(int i = 0; i< viewcount; i++)
{
CGFloat x = i * self.bounds.size.width;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(x, 0,self.bounds.size.width,self.bounds.size.height)];
[view setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(50, 20, 200, 50)];
[label setBackgroundColor:[UIColor redColor]];
label.text=[NSString stringWithFormat:#"Hi, I am label %i",i];
[view addSubview:label];
view.backgroundColor = [UIColor greenColor];
[__scrollView addSubview:view];
}
[__scrollView setBackgroundColor:[UIColor redColor]];
__scrollView.contentSize = CGSizeMake(self.bounds.size.width *viewcount, 100);
__scrollView.pagingEnabled = YES;
__scrollView.bounces = NO;
__scrollView.delegate=self;
[self addSubview:__scrollView];
// Initialization code
}
return self;
}
-(void)setPage:(int)page
{
CGFloat pageWidth = __scrollView.frame.size.width;
float offset_X=pageWidth*page;
[__scrollView setContentOffset:CGPointMake(offset_X, __scrollView.contentOffset.y)];
_currentPage=page;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
static NSInteger previousPage = 0;
CGFloat pageWidth = scrollView.frame.size.width;
float fractionalPage = scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
if (previousPage != page) {
_currentPage=page;
[manager setpage:_currentPage ForKey:[NSString stringWithFormat:#"%i",self.tag]];
previousPage = page;
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
And use a Singleton file for keeping record or pages inside cell.
MyManager.h
#import <Foundation/Foundation.h>
#interface MyManager : NSObject
+ (id)sharedManager;
-(void)setpage:(int)page ForKey:(NSString*)key;
-(int)getpageForKey:(NSString*)key;
#end
MyManager.m
#import "MyManager.h"
static NSMutableDictionary *dictionary;
#implementation MyManager
#pragma mark Singleton Methods
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
-(void)setpage:(int)page ForKey:(NSString*)key
{
[dictionary setValue:[NSString stringWithFormat:#"%i",page] forKey:key];
}
-(int)getpageForKey:(NSString*)key
{
return [[dictionary valueForKey:key] intValue];
}
- (id)init {
if (self = [super init]) {
dictionary=[[NSMutableDictionary alloc] init];
}
return self;
}
- (void)dealloc {
// Should never be called, but just here for clarity really.
}
#end
And use this custom cell in cellForRow as
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Home Scroll Cell";
homeScrollCell *cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[homeScrollCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.tag=indexPath.row;
[cell setPage:[manager getpageForKey:[NSString stringWithFormat:#"%i",indexPath.row]]];
return cell;
}
Set your page inside CustomCell and scroll and after re scrolling get back to previous position will show you page set by you before scrolling.
It will persist your page moved as it is.
Download And Run
rdelmar's answer is missing something. scrollViewDidEndDecelerating will only be called if a users scroll triggers the deceleration behaviour.
A drag only scroll won't call this method so you will get inconsistent behaviour for the user who won't distinguish between the two types of scroll. You need to catch it with scrollViewDidEndDragging:willDecelerate
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
self.tableCellContentOffsets[#(scrollView.tag)] = #(scrollView.contentOffset.x);
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
self.tableCellContentOffsets[#(scrollView.tag)] = #(scrollView.contentOffset.x);
}