disclosure indicator moves cell subviews - ios

I have a table with some cells using a disclosure indicator and some not.
Obviously the disclosure indicator scrunches the contents so not all of the cells line up together in perfect columns.
How can I adjust my contents to stay in the same location regardless of there being a disclosure indicator or not?

One trick to solve this issue is to create an empty view and use it as the cell's accessoryView. Do this only for the cells that don't have a detail disclosure.
The trick is setting the size of the view properly. A little trial and error should do it.
In your cellForRowAtIndexPath:... method:
UITableViewCell *cell = ... // get the cell
If (/* there is no detail disclosure */) {
// Try different "width" value for this view to get the desired results
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 40)];
cell.accessoryView = view;
}

Another alternative is to use different cells. One with the disclosure indicator, and one without. You then have complete control over the layout. And by using the cell reloading mechanism rather than the table reloading mechanism this is efficient.
Better than using blank views IMHO.

Related

Can not remove sub view from tableview custome cell

When table will be scroll it will repeat subview on cell, I am use below code for display embedded view on tableview custome cell. any one know so please help me. How to resolve this issues.
long tag = 100 + indexPath.row;
URLEmbeddedView *embeddedView = [custom.contentView viewWithTag:tag];
if ([custom.contentView viewWithTag:tag]) {
[embeddedView loadURL:#"" completion:nil];
[embeddedView removeFromSuperview];
}
embeddedView = [[URLEmbeddedView alloc] initWithFrame:CGRectMake(35, 60, 220, 110)];
//URLEmbeddedView *embeddedView = [[URLEmbeddedView alloc] initWithFrame:CGRectMake(custom.img_bgOther.frame.origin.x + 35, custom.img_bgOther.frame.origin.y + 50, 220, 110)];
embeddedView.tag = tag;
[custom.contentView addSubview:embeddedView];
[embeddedView loadURL:str_Website completion:nil];
Presumably the code in your question is taken from your cellForRowAtIndexPath: method. The problem you describe is a consequence of cells being reused. Cells for rows that have scrolled off screen are reused for rows that scrolling on screen. Suppose row 0 is scrolled off screen. It will have an embedded view with tag 100. And suppose it is reused for row 10. The above code will try to find a view with tag 110 and remove it from its superview. Since the tag does not match, the existing embedded view is not removed, and the new embedded view is added on top of it.
I would suggest you do things differently. You shouldn't be adding and removing the embedded view in cellForRowAtIndexPath. You have a custom cell, so just design the embedded view into it. Create a URLEmbeddedView property in your custom cell class, so you can access that subview without having to use viewWithTag. You can use that property to call the loadURL:completion: method with the correct values for the current row.
When cells are reused, the tableView will call the cell's prepareForReuse method. So override that method in your custom cell class, and clear the loadURL/completion at that point.

How to add multiple cells in header of a table view (not section header)?

I would like to implement segmented controls like this (circled with red) :
(When we scroll this view, the segmented controls stay sticky at the top of the view, that makes me think it's a cell on its own ? but I may be wrong).
I have already implemented a custom cell (that displays kind of what is above the red ellipse in the above picture, in purple) and add it to the header of my table view like so :
BigCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"BigCell"];
self.tableView.tableHeaderView = cell;
Now, I think I should create a second cell with the segmented controls in it and add it also to the table header (and not in the section header, because I have many sections with their titles).
Then, I would create a UIView containing this two cells and add this view as the header of my tableView ? Is this a correct way to do it ?
Thank you very much for the help !
I think you have a couple of options.
1) Make a container view to host both of your "cells" (which needn't be UITableViewCells - just views...). Add the singular container view as the table header.
2) Forego using the table header altogether and just place your views above the table, making it shorter. This is more complicated if you're using a UITableViewController, but simple if you're just hosting a UITableView in some other custom UIViewController.
this is an example with uilabel that stick to the top - just change it to your uisegmentedcontrol
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *viewForSectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, SETTINGS_HEADER_HEIGHT)];
[viewForSectionHeader setBackgroundColor:[Utils colorHeaderBlue]];
UILabel *lblSectionTitle = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, SETTINGS_HEADER_HEIGHT)];
lblSectionTitle.text = #"PROFILE";
lblSectionTitle.textAlignment = NSTextAlignmentCenter;
lblSectionTitle.textColor = [UIColor whiteColor];
[viewForSectionHeader addSubview:lblSectionTitle];
return viewForSectionHeader;
}

Prevent UITableViewCells from creating as you scroll down

I'm creating a mail screen using which visually resembles the iOS native email app. It looks like this (Both images are of the same screen. First one is the top half and the second one is the rest of it).
The difference is my mail screen has more custom fields in addition to normal To, Cc, Subjet fields.
I'm using a UITableViewController to create this. Below is a code snippet which creates a cell (For each cell it's pretty much the same).
- (UITableViewCell *)tokenTableView:(TITokenTableViewController *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
self.tableView.frame = CGRectMake(0,0,320,320);
UIView *contentSubview = nil;
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifierSubject];
if(!self.txtSubject) {
self.txtSubject = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
self.txtSubject.frame = CGRectMake(10, cell.frame.size.height / 2 - self.txtSubject.font.lineHeight / 2, tableView.tableView.bounds.size.width, 30);
self.txtSubject.placeholder = #"Subject";
[self setupMailData:indexPath.row];
}
contentSubview = self.txtSubject;
}
Say, I open up a draft. All the details in the input fields are filled and without changing anything, I hit send and it crashes the app. I know what's causing this. The problem is that normally the cells that are under the viewable portion of the screen gets created as you scroll down, right? But in this scenario, if I send it without scrolling down but those cells below the viewport don't exist thus it throws the error.
If I open the draft, scroll down and hit send, it works fine.
I need to know if there's a way to create all these cells at once. Even the cells that are below the viewport at first. Not depending on the user to scroll down.
I hope you have an idea about my situation. Can anyone suggest a solution?
Thank you.
follow steps:
Take uiscrollview and set scrollview frame as which you want to display.
Take uitableview as a subview of uiscrollview
set property Scrolling Enabled = NO (uncheck checkbox in .xib) of uitableview
call reloaddata method of uitableview
set tableview frame and contentsize of scrollview
tblEmail.frame = CGRectMake(yourXPos, yourYPos, yourWidth, tblEmail.contentSize.height);
scrollObj.contentSize = CGSizeMake(yourScrollWidth,tblEmail.contentSize.height+10);
so, the height of tableview is equal its contentsize. so, its create all cells at a time. and set contentsize of scrollview is equal tableview contentsize. so, the scrolling feature is worked like uitableview scrolling...
Use a Storyboard, add a UITableViewController and set the 'Content' to StaticCells.
Then you can define all the cells and their content in the Storyboard. You can even wire stuff up to IBOutlets in your UITableViewController subclass and they will all be there for you when viewDidLoad is fired ...
When using a Storyboard your code for getting the ViewController looks like:
[[UIStoryboard storyboardWithName:#"MyStoryboard" bundle:nil] instantiateInitialViewController];

Avoid auto resize of uitableview cell content view on entering edit mode

I have a uitableviewcell with content view containing some custom view.'
When the table view enters edit mode the content view resizes (becomes narrower) there by the image in the content view is shrunk horizontally
Does anyone know how to prevent this ?
I have set the cell indentation to none.
Thanks
Have you tried setting shouldIndentWhileEditing to NO
Take a look at properties :
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html
Have you tried setting the auto-resize masks on the view?
theView.autoresizingMask = UIViewAutoresizingNone;
You may need to set it on the content view and/or the image view - it's not clear exactly how your view hierarchy is structured. However, the frame might be set explicitly (rather than auto-resized) by the framework, in which case this won't work.
If you are trying to have a background image for the entire table cell, you may also want to try an alternative method which is to set the backgroundColor of the cell like this:
UIImage* someImage = [UIImage imageNamed:#"someImage"];
cell.backgroundColor = [UIColor colorWithPatternImage:someImage];
Remember to make sure the backgroundColor of all other views you place inside are [UIColor clearColor] so that you can see through to the background image.
You can always get a tableviewcell with an indexpath. Using that tableviewcell reuseidentifier, You can avoid the tableview cell content size to be resized or not. I had a requirement to implement the similar kind of functionality to avoid resizing of seperate cells. PFB the code.
-(BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{
BOOL shouldIndentWhileEditingRow = NO;
UITableViewCell *lTableViewCell = [tableView cellForRowAtIndexPath:indexPath];
/*Change the position of the target rect based on Sending messages or Receiving messages*/
if ([lTableViewCell.reuseIdentifier isEqualToString:#"SendingChatCellIdentifier"]) {
shouldIndentWhileEditingRow = NO;
}else if ([lTableViewCell.reuseIdentifier isEqualToString:#"ReceivingChatCellIdentifier"]){
shouldIndentWhileEditingRow = YES;
}
return shouldIndentWhileEditingRow;
}
I did something similar to avoid the cell content to be resized when using cell automatic dimension.
My problem was that the textView inside the cell, after the selection, was wrapping its content in more lines, and I just wanted to avoid this.
To solve this "issue":
I added a trailing constraint of 40px (the size of the accessory view) to the cell content
On cell select, i change the constraint to 0, so the text is 40 px larger, but as the accessory shows up, you don't see any changes.
The pro of this solution is that the content dimension is not changing anymore when user select a row.
the con is that you have always 40px of free space on the right of the cell, also when not selected.

Why is my UILabel in a UIView in a UITableCellView not updating after a correct database call, (it seems cell reuse related)?

I have a UITableview cell that gets a tally from a core data database. The tallyTable is in a view controller inside a UITab view. I have an NSLog statement that prints out the tally value whenever it gets updated. Another tab has a list to change the source (different day) for the tallies. I am using iOS5 with ARC targeting iOS 4.2.
Here's the problem. When I load the application, the correct tallies for whatever the last selected day show up in the table tab. If I then go to the day tab and change the day and return to the tally tab there is no change in the display. However, the viewWillAppear on the tally tab runs and as the table cycles through cellForIndexPath, my NSLog statement prints out all the correct new values. If I then scroll the top label off the screen and back the label updates to the new value.
I've tried setNeedsLayout and setNeedsDisplay on the UILabel, the UITableViewCell, the UITableView and the view controller loading the table. I tried changing the CellReuse identifier so that it would never reuse a cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CollectionItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CollectionItemTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.collectionKeys objectAtIndex:row] valueForKey:#"collectionTitle"];
NSInteger test1 = indexPath.row + 150;
NSLog(#"tag = %i", test1);
cell.tallyButton.tag = test1;
NSNumber * questionID = [[self.collectionKeys objectAtIndex:row] valueForKey:#"answerID"];
cell.tallyLabel.text = [NSString stringWithFormat:#"%i",[self updatePointTotal:questionID]];
NSLog(#"Collection text should be = %#", [NSString stringWithFormat:#"%i",[self updatePointTotal:questionID]]);
[cell setNeedsLayout];
return cell;
}
I've read over a half dozen other similar questions. Got about three hours invested so far in trying to solve this.
EDIT: I thought I fixed it by using the navigation controller to repush the top level view controller on to the view again. I'll admit now this feels like a classically kludgy hack in every way. When the view is PUSHED everything updates and it is seamless. However, in order to have a fixed footer to make selection settings for the table buttons, I used a UIView with two subviews, a UITableView on top and a simple UIView with four buttons below.
The captions on the buttons need to change with the data source. Now when the view controller is pushed onto the view it obscures my fixed footer view. So, I inserted the fixed footer into the UITableview and everything appeared fine until I scrolled the UITableView and the footer scrolled up with it. The table is basically a tally sheet with buttons next to each item and in the footer is four buttons to note the color of the tallied item. Say the next item was a green lego, you would tap "green" in the footer and the button next to "lego" in the table. When I push the view controller with the two subviews the UITableview labels do not update. Thus the tableview needs to be pushed itself (as far as I can tell).
ANSWER: see comment below but ultimately I needed to reload both the visible UITableView data and the delegate UITableView controller data behind it.
I'll give it a shot. First, are you using ARC? If not, you need to add autorelease when you alloc/init a new cell. Otherwise, it's fine as is.
If I'm understanding your question correctly:
The tableView displays the correct data at app launch
You switch away from the tab with the tableView and change the tableView dataSource
You switch back to the tab with the tableView and you see (via NSLog) that the table cells are reloaded with the correct data yet the old data is still visible in the cells
If you scroll a cell off the display and back forcing it to refresh it contains the correct data
Some thoughts:
the tableView will not reload itself automatically when it's view appears. You need to call [tableView reloadData] whenever the dataSource changes. This is independent of whether the tableView is currently displayed or not. My guess is this alone will solve your problem.
You don't need to call setNeedsLayout on the cell unless you want the cell to relayout its subviews based on the data. You also don't need setNeedsDisplay.
I'm assuming there aren't other complicating factors (such as multiple tableViews displaying the same data) that could confuse things.
If you use prepare for reuse method, remember to over the original method with [super prepareForReuse];
Another method if the above way does not work is re setup cell as describe here.
I use the same method i applied for some of my collection view : we should remove/reset your subview where you create/add it to cell 's content. That mean we need set up data each cell completely for each row.
I move the code reset data value from prepare reuse to where i set value and I worked simply !
In my CustomCell.m :
- (void)configCellWith:(id)item At:(NSUInteger)row {
if (_scrollView) {
[[_scrollView subviews]
makeObjectsPerformSelector:#selector(removeFromSuperview)];
_scrollView = nil;
[_scrollView removeFromSuperview];
}
else {
CGFloat y = labelHeight+15;
float scrollHeight = _imgArray.count*200;
_scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(10, y,SCREEN_WIDTH-20, scrollHeight)];
_scrollView.scrollEnabled=YES;
_scrollView.userInteractionEnabled=YES;
_scrollView.layer.masksToBounds = YES;
[self.contentView addSubview:_scrollView]; } }
Remember to change your data source appropriately too.

Resources