how to know indexpath of UITableView.visibleCells? - ios

NSArray * arrayOfVisibleTVC=[BNUtilitiesQuick ListController].tableViewA.visibleCells;
NSLog(#"array : %#", arrayOfVisibleTVC);
will display
"<UITableViewCell: 0x76c22a0; frame = (0 0; 320 75); autoresize = W; layer = <CALayer: 0x76bf770>>",
"<UITableViewCell: 0x76cfec0; frame = (0 75; 320 75); autoresize = W; layer = <CALayer: 0x769d260>>",
"<UITableViewCell: 0xe245f70; frame = (0 150; 320 75); autoresize = W; layer = <CALayer: 0xe245ed0>>",
"<UITableViewCell: 0xe248980; frame = (0 225; 320 75); autoresize = W; layer = <CALayer: 0xe2488c0>>",
"<UITableViewCell: 0xe24afa0; frame = (0 300; 320 75); autoresize = W; layer = <CALayer: 0xe24aee0>>"
and with this
UITableViewCell * lastObjectOfArray=arrayOfVisibleTVC.lastObject;
int indexpathLastObject= (lastObjectOfArray.frame.origin.y/new.frame.size.height);
I know the last of arrayOfVisibleTVC.lastObject that I use to get indexpath. but I think there is an another way to get indexpath of TableViewcell that showed.. any one can help me?
so I can get indexpath of cell as integer

Here is method in UITableView class:
objective-c
- (NSArray *)indexPathsForVisibleRows
Swift
public var indexPathsForVisibleRows: [NSIndexPath]? { get }

UITableView has a method to find the indexPath of a cell:
- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell
Just iterate over your visible cells array and pass each cell to get the index path.
for (UITableViewCell *cell in arrayOfVisibleTVC) {
NSIndexPath *path = [[BNUtilitiesQuick ListController].tableViewA indexPathForCell:cell];
NSLog(#"%#", path);
}

Related

tableHeaderView - layoutSubviews and initWithFrame

I have a custom UITableViewHeaderFooterView class and an xib for it. There is a label in this xib which is connected to the custom class using an outlet. This custom class is being used as the tableHeaderView for a table view in a view controller.
I am able to show the header view with required dimensions but the label in the header is not showing any value.
In view controller's viewDidLoad.
- (void)viewDidLoad {
..
DashboardHeaderView* headerView = [[DashboardHeaderView alloc] initWithFrame:CGRectMake(0, 0, 320, 180) headerText:#"XYX"];
self.alertsTableView.tableHeaderView = headerView;
}
In DashboardHeaderView which is a subclass of UITableViewHeaderFooterView.
- (id)initWithFrame:(CGRect)frame headerText:(NSString *)headerText {
if (self = [super initWithFrame:frame]) {
self.headerText = headerText;
NSArray* objects = [[NSBundle mainBundle] loadNibNamed:#"DashboardHeaderView"
owner:self
options:nil];
UIView *nibView = [objects firstObject];
UIView *contentView = self.contentView;
contentView.backgroundColor = [UIColor clearColor];
CGSize contentViewSize = contentView.frame.size;
nibView.frame = CGRectMake(0, 0, contentViewSize.width, contentViewSize.height);
[contentView addSubview:nibView];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.headerLabel.text = self.headerText;
}
If I put some log messages in initWithFrame:headerText: and layoutSubviews, I can see that the self of both is pointing to different addresses and hence in layoutSubviews, self.headerText is always nil.
layoutSubviews
<DashboardHeaderView: 0x7ff862cf1a90; baseClass = UITableViewHeaderFooterView; frame = (0 0; 320 180); text = ''; opaque = NO; autoresize = W+H; layer = <CALayer: 0x7ff861634e30>>
initWithFrame
<DashboardHeaderView: 0x7ff862cf05e0; baseClass = UITableViewHeaderFooterView; frame = (0 0; 320 180); text = ''; layer = <CALayer: 0x7ff8616d13f0>>
layoutSubviews
<DashboardHeaderView: 0x7ff862cf1a90; baseClass = UITableViewHeaderFooterView; frame = (0 0; 290 180); text = ''; opaque = NO; autoresize = W+H; layer = <CALayer: 0x7ff861634e30>>
layoutSubviews
<DashboardHeaderView: 0x7ff862cf05e0; baseClass = UITableViewHeaderFooterView; frame = (0 0; 290 180); text = ''; layer = <CALayer: 0x7ff8616d13f0>>
layoutSubviews
<DashboardHeaderView: 0x7ff862cf05e0; baseClass = UITableViewHeaderFooterView; frame = (0 0; 290 180); text = ''; layer = <CALayer: 0x7ff8616d13f0>>
layoutSubviews
<DashboardHeaderView: 0x7ff862cf1a90; baseClass = UITableViewHeaderFooterView; frame = (0 0; 345 180); text = ''; opaque = NO; autoresize = W+H; layer = <CALayer: 0x7ff861634e30>>
layoutSubviews
<DashboardHeaderView: 0x7ff862cf05e0; baseClass = UITableViewHeaderFooterView; frame = (0 0; 345 180); text = ''; layer = <CALayer: 0x7ff8616d13f0>>
layoutSubviews
<DashboardHeaderView: 0x7ff862cf1a90; baseClass = UITableViewHeaderFooterView; frame = (0 0; 345 180); text = ''; opaque = NO; autoresize = W+H; layer = <CALayer: 0x7ff861634e30>>
layoutSubviews
<DashboardHeaderView: 0x7ff862cf05e0; baseClass = UITableViewHeaderFooterView; frame = (0 0; 345 180); text = ''; layer = <CALayer: 0x7ff8616d13f0>>
If you look at above logs, why do we have two different addresses - 0x7ff862cf1a90 and 0x7ff862cf05e0.
UIView Class Reference says:
layoutSubviews - Implement this method if you need more precise
control over the layout of your subviews than either the constraint or
autoresizing behaviors provide.
You are setting a value of an UILabel inside the layoutSubviews method, that is intended only for resizing operations.
I suggest you to move the self.headerLabel.text = self.headerText instruction into the initWithFrame:headerText: method and perform other operations like resizing or changing constraints into the layoutSubviews method.
In this way it works fine!

kvc get subview lastobject

I have a problem.
first,I have a NSArray like this:
(NSMutableArray *)currentCanMoveAndDeleteCellArray {
NSInteger count = [self.contentCollectionView numberOfItemsInSection:0];
NSMutableArray *currentCells = [NSMutableArray arrayWithCapacity:count];
for (int index = 0 ; index < count; ++index) {
UICollectionViewCell *cell = [self.contentCollectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
if(cell) {
[currentCells addObject:[self.contentCollectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]];
}
}
return currentCells;
}
then I want to get their last subviews, I use kvc get subviews like this.
[self.currentCanMoveAndDeleteCellArray valueForKeyPath:#"subviews"]
and I got:
<__NSArrayI 0x1710793c0>(
<__NSArrayM 0x17405a670>(
<UIView: 0x155de9020; frame = (0 0; 80 30); gestureRecognizers = <NSArray: 0x170248f40>; layer = <CALayer: 0x1702363a0>>,
<UILabel: 0x155e524d0; frame = (70 -10; 20 20); clipsToBounds = YES; tag = 123; gestureRecognizers = <NSArray: 0x17405a520>; layer = <_UILabelLayer: 0x17409f540>>
)
,
<__NSArrayM 0x17405cf80>(
<UIView: 0x155e7cbf0; frame = (0 0; 80 30); gestureRecognizers = <NSArray: 0x17405d3a0>; layer = <CALayer: 0x174431a40>>,
<UILabel: 0x155e7ceb0; frame = (70 -10; 20 20); clipsToBounds = YES; tag = 123; gestureRecognizers = <NSArray: 0x17405d400>; layer = <_UILabelLayer: 0x17409f9a0>>
)
,
<__NSArrayM 0x17405f6b0>(
<UIView: 0x155e7da80; frame = (0 0; 80 30); gestureRecognizers = <NSArray: 0x17405faa0>; layer = <CALayer: 0x174433440>>,
<UILabel: 0x155e7dd40; frame = (70 -10; 20 20); clipsToBounds = YES; tag = 123; gestureRecognizers = <NSArray: 0x17405fb00>; layer = <_UILabelLayer: 0x174282f30>>
)
<__NSArrayM 0x174240990>(
<UIView: 0x155e7e150; frame = (0 0; 80 30); gestureRecognizers = <NSArray: 0x174240d80>; layer = <CALayer: 0x174433e60>>,
<UILabel: 0x155e7e410; frame = (70 -10; 20 20); clipsToBounds = YES; tag = 123; gestureRecognizers = <NSArray: 0x174240de0>; layer = <_UILabelLayer: 0x174283610>>
)
,
<__NSArrayM 0x174241c50>(
<UIView: 0x155e7ec30; frame = (0 0; 80 30); gestureRecognizers = <NSArray: 0x174242040>; layer = <CALayer: 0x174434880>>,
<UILabel: 0x155e7eef0; frame = (70 -10; 20 20); clipsToBounds = YES; tag = 123; gestureRecognizers = <NSArray: 0x1742420a0>; layer = <_UILabelLayer: 0x174283cf0>>
)
,
<__NSArrayM 0x174242f10>(
<UIView: 0x155e7f710; frame = (0 0; 80 30); gestureRecognizers = <NSArray: 0x174243300>; layer = <CALayer: 0x1744352a0>>,
<UILabel: 0x155e7f9d0; frame = (70 -10; 20 20); clipsToBounds = YES; tag = 123; gestureRecognizers = <NSArray: 0x174243360>; layer = <_UILabelLayer: 0x1742843d0>>
)
)
who can tell me how to got last subview.
I tried to write:
[self.currentCanMoveAndDeleteCellArray valueForKeyPath:#"subviews.#lastObject"]
but, you know that it isn't result that i want.
You should use UICollectionViewCell class in array.
After, you can get subview.
- (NSMutableArray *)currentCanMoveAndDeleteCellArray {
NSInteger count = [self.contentCollectionView numberOfItemsInSection:0];
self.currentCells = [NSMutableArray arrayWithCapacity:count];
for (int index = 0 ; index < count; ++index) {
UICollectionViewCell *cell = [self.contentCollectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
if(cell) {
[ self.currentCells addObject:cell]; }
} return self.currentCells;
}
-(void)getCell{
UICollectionViewCell *cell = [ self.currentCells objectAtIndex:_index];
for (UIView * view in [cell subviews]) {
NSLog(#"%#",view);
}
}

Bug in iOS with UITableViewCells?

I have a UITableViewController in a Storyboard in my iOS project. I have a special TableViewCell MessageCell with a UIView inside of a specific class.
When I call tableView.dequeueReusableCellWithIdentifier: I get a UITableViewCell with only this subview tree:
<UITableViewCell: 0x16da5e90; frame = (0 0; 0 0); layer = <CALayer: 0x16da5120>>
<UITableViewCellContentView: 0x16da6210; frame = (0 0; 0 0); clipsToBounds = YES; opaque = NO; gestureRecognizers = <NSArray: 0x16da5510>; layer = <CALayer: 0x16da6280>>
<_UITableViewCellSeparatorView: 0x16da62b0; frame = (0 -1; 15 1); layer = <CALayer: 0x16da52d0>>
But when I call tableView.dequeueReusableCellWithIdentifier:forIndexPath, I get this subview tree:
<UITableViewCell: 0x146f3a90; frame = (0 148.93; 320 54.93); autoresize = W; layer = <CALayer: 0x146f2ff0>>
<UITableViewCellContentView: 0x146f3020; frame = (0 0; 320 54.43); opaque = NO; gestureRecognizers = <NSArray: 0x146f3e90>; layer = <CALayer: 0x146f3180>>
<Heaven_Help.MessageView: 0x146f3f70; frame = (0 0; 320 568); autoresize = W+H; tag = 99; layer = <CALayer: 0x146f4af0>>
<UIImageView: 0x146f4010; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x146f4090>>
<UILabel: 0x146f40c0; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x146f4180>>
<UILabel: 0x146f42d0; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x146f4390>>
<_UITableViewCellSeparatorView: 0x146f31b0; frame = (0 -1; 15 1); layer = <CALayer: 0x146f3c20>>
<_UITableViewCellSeparatorView: 0x146f5170; frame = (0 -0.5; 16 0.5); layer = <CALayer: 0x146c1f40>>
The UIImageview and 2 UILabels get added in my MessageView initializer.
Who can tell me what I am not getting?
As requested: my code from tableView:cellForRowAtIndexPath::
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MessageCell", forIndexPath: indexPath) as UITableViewCell
(cell.viewWithTag(99) as MessageView).setMessage(conversation[indexPath.row])
return cell
}
In short, don't use dequeueReusableCellWithIdentifier:.
dequeueReusableCellWithIdentifier: returns:
A UITableViewCell object with the associated identifier or nil if no such object exists in the reusable-cell queue.
This method is typically used in a pattern like this without a storyboard:
MessageCell *cell = [tableView dequeueReusableCellWithIdentifier:#"messageCell"];
if (!cell) {
cell = [[MessageCell alloc] initWithStyle:…reuseIdentifier:#"messageCell"];
// set properties that are true for EVERY cell
}
// set properties from your data model for THIS cell (usually strings and images)
return cell;
(With a storyboard, the method will always return a cell.)
The newer methods (like dequeueReusableCellWithIdentifier:forIndexPath:) are guaranteed to return a cell, so you don't need to use this pattern any more.
The reason you're getting a UITableViewCell back from dequeueReusableCellWithIdentifier: is because you inserted one into the reusable-cell queue with that identifier.

indexPathForCell unrecognized selector sent to instance on iOS 8 with ObjC

I have a UITextField in UITableViewCell. When user tries to enter some text into this textfield, app scrolls that cell to the top of UITableView.Here is the code:
#pragma mark - UITextField Delegates
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
UITableViewCell *QCELL = (UITableViewCell *)[[[[textField superview]superview]superview]superview];
UITableView *QTable = (UITableView *)[[QCELL superview] superview];
NSIndexPath*path = = [QTable indexPathForCell:QCELL];
return true;
}
and exception
2014-09-11 11:12:50.604 InspectTHIS[9401:348011] -[UIView indexPathForCell:]: unrecognized selector sent to instance 0x7c2e8b30
2014-09-11 11:12:50.608 InspectTHIS[9401:348011] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView indexPathForCell:]: unrecognized selector sent to instance 0x7c2e8b30'
Updated - Answered
After I search in Views Layer I found this
////////// iOS 8 //////////
<UIView: 0x792aabd0; frame = (0 0; 768 1023); opaque = NO; autoresize = W+H; layer = <CALayer: 0x792aac40>>
<UITableViewCellContentView: 0x79758340; frame = (0 0; 768 699); opaque = NO; gestureRecognizers = <NSArray: 0x79758530>; layer = <CALayer: 0x797583b0>>
<QuestionCell: 0x79757ed0; baseClass = UITableViewCell; frame = (0 0; 768 699); autoresize = W; layer = <CALayer: 0x79758190>>
<UITableViewWrapperView: 0x7967bc50; frame = (0 0; 768 750); gestureRecognizers = <NSArray: 0x7967bef0>; layer = <CALayer: 0x7967be30>; contentOffset: {0, 0}; contentSize: {768, 750}>
<UITableView: 0x78c99600; frame = (0 244; 768 750); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7967b9c0>; layer = <CALayer: 0x7967ae00>; contentOffset: {0, 0}; contentSize: {768, 699}>
<UIView: 0x7967abd0; frame = (0 0; 768 1024); autoresize = RM+BM; layer = <CALayer: 0x7967ac40>>
//////// iOS 7 ////
<UIView: 0x11fbbbf0; frame = (0 0; 768 1023); opaque = NO; autoresize = W+H; layer = <CALayer: 0x11fbbc50>>
<UITableViewCellContentView: 0x11f832a0; frame = (0 0; 768 699); opaque = NO; gestureRecognizers = <NSArray: 0x11f8dd40>; layer = <CALayer: 0x11faa6f0>>
<UITableViewCellScrollView: 0x11fc4090; frame = (0 0; 768 699); autoresize = W+H; gestureRecognizers = <NSArray: 0x11f9c830>; layer = <CALayer: 0x11f978f0>; contentOffset: {0, 0}>
<QuestionCell: 0x11fa2090; baseClass = UITableViewCell; frame = (0 0; 768 699); autoresize = W; layer = <CALayer: 0x11fa1c90>>
<UITableViewWrapperView: 0xced1860; frame = (0 0; 768 750); autoresize = W+H; layer = <CALayer: 0xced18d0>>
<UITableView: 0xd958800; frame = (0 244; 768 750); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0xced1560>; layer = <CALayer: 0xced0eb0>; contentOffset: {0, 0}>
<UIView: 0xced0c30; frame = (0 0; 768 1024); autoresize = RM+BM; layer = <CALayer: 0xced0c90>>
as you can see in iOS 8, UITableViewCellScrollView is missing and and I can't go up like I did in iOS 7. so i change the code like this.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
NSIndexPath*path;
UITableView *QTable;
CGFloat version =[[[UIDevice currentDevice] systemVersion] floatValue];
if (version >= 7.0)
{
UITableViewCell *QCELL = (UITableViewCell *)[[[[textField superview]superview]superview]superview];
QTable = (UITableView *)[[QCELL superview] superview];
path = [QTable indexPathForCell:QCELL];
}
else if(version >= 8.0)
{
UITableViewCell *QCELL = (UITableViewCell *)[[[textField superview]superview]superview];
QTable = (UITableView *)[[QCELL superview] superview];
path = [QTable indexPathForCell:QCELL];
}
NSIndexPath*path = = [QTable indexPathForCell:QCELL];
return true;
}
I change your original code a little and came out with this:
I made this change because I had a problem when the version was 8 the if for the >= 7 was been fired. And I need the variables outside the if.
CGFloat version =[[[UIDevice currentDevice] systemVersion] floatValue];
UITableViewCell *cell;
UITableView *table;
if ((version > 7) && (version < 8))
{
UITableViewCell *cell = (UITableViewCell*)[[[sender superview] superview]superview];
table = (UITableView *)cell.superview.superview;
}
else if(version > 8)
{
UITableViewCell *cell = (UITableViewCell*)[[sender superview] superview];
table = (UITableView *)cell.superview.superview;
}
Similarly I had a button inside a UITableViewCell.This will work for you. Here buttonView means my UIButton instance
For iOS 8
UITableViewCell *cell = (UITableViewCell*)[buttonView superview];
gave me the UITableViewCell instance
and for iOS 7 as usual
UITableViewCell *cell = [buttonView superview]superview];
gave me the UITableViewCell instance
And the
[QTable indexPathForCell:cell];
Will give you the NSIndexPath(This part is ok in the given answer).
This is what you get for traversing the view hierarchy instead of using delegate methods from the cell itself.
Make the Cell itself respond to the delegate of the textview. Let the cell have it's own protocol (delegate methods), and let your TableViewController be it's delegate.
Then your code in the subclassed UITableViewCell-class will look something like this:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[self.delegate textFieldDidBeginEditingForCell:self];
return true;
}
Then in your TableViewController:
- (void)textFieldDidBeginEditingForCell:(YourCustomCell*)cell
{
NSIndexPath *path = [QTable indexPathForCell:cell];
...
}

indexPathForCell returning NULL under IOS 7, works fine under IOS 6

I'm hoping now apps for IOS 7 are being accepted by Apple we can talk about it?
I'm trying to fix my app so it works on IOS 7 and have made some very good progress this evening. I have two outstanding issues, but will post them separately. The first issue is this line (I added a log line after to debug it) ...
NSIndexPath *indexPath = [settingsTableView indexPathForCell:(UITableViewCell *)[sender superview]];
NSLog(#"Changed %# <-**-> %#", [sender superview], indexPath );
The log shows ....
IOS7
2013-09-11 22:18:02.985 BusTimes[21013:a0b] Changed <UITableViewCellScrollView: 0xbfc1c80; frame = (0 0; 320 44); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0xbfc1e70>; layer = <CALayer: 0xbfc1540>; contentOffset: {0, 0}> <-**-> (null)
2013-09-11 22:18:08.577 BusTimes[21013:a0b] Changed <UITableViewCellScrollView: 0xbfc62d0; frame = (0 0; 320 44); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0xbfc64c0>; layer = <CALayer: 0xbfc5b90>; contentOffset: {0, 0}> <-**-> (null)
IOS 6
2013-09-11 22:25:34.495 BusTimes[2116:907] Changed <UITableViewCell: 0x20862f40; frame = (0 179; 320 44); text = 'Reminder Mins: 5'; autoresize = W; layer = <CALayer: 0x208523d0>> <-**-> <NSIndexPath 0x20861430> 2 indexes [0, 3]
2013-09-11 22:25:47.499 BusTimes[2116:907] Changed <UITableViewCell: 0x20865180; frame = (0 223; 320 44); text = 'AutoRefresh Secs: 60'; autoresize = W; layer = <CALayer: 0x20865340>> <-**-> <NSIndexPath 0x2085c0d0> 2 indexes [0, 4]
So on IOS 7 indexPath is always (null) and .section and .row are always 0. But this works fine on IOS 6 and returns .section 0 and row 3, and .row 4. Can anyone suggest how I might get IOS 7 to behave in the same way for me?
Many Thanks in advance.
Plasma
* SOLUTION - I changed my code to this following the comments *
UIView *view = sender;
while (![view isKindOfClass:[UITableViewCell class]]) {
view = [view superview];
}
NSIndexPath *indexPath = [settingsTableView indexPathForCell:(UITableViewCell *)view];
It's usually safer to make no assumptions about the view hierarchy of a cell. In the past, I've used a category with methods like this on UIView to find the superview which is a cell:
- (UIView*)ancestorOrSelfWithClass:(Class)cls {
if ([self isKindOfClass:cls]) {
return self;
} else if (self.superview) {
return [self.superview ancestorOrSelfWithClass:cls];
} else {
return nil;
}
}
So you'll ask for [sender ancestorOrSelfWithClass:[UITableViewCell class]] to get the actual cell, and it'll work no matter what hierarchy exists within the cell.

Resources