in Storyboard (in Xcode 6) i want design a view like this
user profile view
The rows are dynamic because the content is get from a web services. How can i implement this view?
I have tried with an image view (the upper image with user name and pic) with a table view below but when i scroll the table obviously scroll only the table.
The image in the link is a uitableview with only the first row different from the other? How can implement only one row different from the other?
Thanks
That view could either be a tableHeaderView which does scroll with the table, or a cell. You can create as many prototype cells in the table view as you want, and give them different reuse identifiers. In cellForRowATIndexPath, put in an if-else clause, and dequeue whichever cell you want based on the indexPath.row.
Take two custom cells give different identifiers .one for only your first row and other for n-1 cells.
and load cellForRowATIndexPath as
before that take one temporary array
NSArray *arr=[[NSArra alloc]initWithObjects:#"FirstIdentifer",#"SecondIdientfier"];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [self.menuItems objectAtIndex:indexPath.row];
if ([CellIdentifier isEqualToString:#"FirstIdentifer"]) {
Mycell *cell = (Mycell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TempCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
//do your stuff
return cell;
}
else
{
static NSString *simpleTableIdentifier = #"SecondIdientfier";
cell1 = (Mycell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"Mycell" owner:self options:nil];
cell1 = [nib objectAtIndex:0];
//do your stuff
return cell1;
}
}
Related
I'm having some problem with multiple custom UITableViewCell reuse. I have 3 types of custom UITableViewCell. I tried to reuse the UITableViewCell using dequeueReusableCellWithIdentifier.
I wrote the prepareForReuse and made all possible subviews data nil. But still I was getting some repetitions of data in some UITableViewCell's. So I was thinking of reusing just the xib without any data.
I made up the following code. The app seems to have some freezing problem now. Somebody please show me the correct way to reuse tableview UITableViewCells without data repetition.
static NSString *cellIdentifier = #"SystemListCell";
IXSystemMessageCustomCell *cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:#"IXSystemMessageCustomCell" owner:self options:nil] objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
IXSystemMessageCustomCell *cellToSave = cell;
[self configureSystemCell: cellToSave atIndexPath:indexPath];
return cellToSave;
Do not modify the data in prepareForReuse
A better way is to
dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath
We should always modify the data in cellForRowAtIndexPath as this helps in reuse of cells.
Also, since you have created IXSystemMessageCustomCell class it is better to use this :
[[IXSystemMessageCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]
and write the setup code in initWithStyle:reuseIdentifier:
instead of this:
cell = [[[NSBundle mainBundle] loadNibNamed:#"IXSystemMessageCustomCell" owner:self options:nil] objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
Cheers!
You can use 3 different reuse identifier for your 3 cell types:
IXSystemMessageCustomCell *cell;
if (some condintion) {
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:"CellReuseIdentifierType1"];
} else if (some condition 2) {
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:"CellReuseIdentifierType2"];
} else {
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:"CellReuseIdentifierType3"];
}
In this case you don't need to re-configure cell each time for each cell type
Try this...
IXSystemMessageCustomCell *cell = nil;
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
By setting your cell to nil first, you are clearing out previous data associated with the reused cell.
Also register your nib once in your viewDidLoad or similar table view lifecycle method, so that this is not required at every call to tableView:cellForRowAtIndexPath.
So extract your static call from any method to be a private declaration...
static NSString *cellIdentifier = #"SystemListCell";
and adjust your methods to read...
- (void)viewDidLoad {
UINib *nib = [UINib nibWithNibName:#"IXSystemMessageCustomCell" bundle:nil];
[<<self.tableView>> registerNib:nib
forCellReuseIdentifier:cellIdentifier];
<< ... other code ... >>
}
and
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
IXSystemMessageCustomCell *cell = nil;
cell = (IXSystemMessageCustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[self configureSystemCell:cell atIndexPath:indexPath];
return cell;
}
If I want to make a 10X10 buttons in a view, the simple way is to make 100 buttons,
in Cocoa there is a NSButtonCellcan be used, so is there some thing like it in iOS?
your can create a custom cell
drag and drop a tableView cell and design with your buttons
and
add your custom tableView cell in cellForRowAtIndexPath like this,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *yourCustomeCelldentifier = #"CustomeTableCell";
yourCustomeCell *cell = (yourCustomeCell *)[tableView dequeueReusableCellWithIdentifier:yourCustomeCelldentifier];
if (cell == nil)
{
NSArray *nib;
nib = [[NSBundle mainBundle] loadNibNamed:#"CustomeCell_Nib" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
return cell;
}
hope this way will help you
I am getting EXC_BadAccess error message while i am scrolling tableview.
the following is the code i have done in cellForRowAtIndexPath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier=#"customCellHistory";
customCellHistory *cell=(customCellHistory*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects=[[NSBundle mainBundle]loadNibNamed:#"customCellHistory" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[UITableViewCell class]] ) {
cell=(customCellHistory*)currentObject;
break;
}
}
}
cell.lb11.text=[cellArray1 objectAtIndex:indexpath.row];
cell.lbl2.text=[cellArray2 objectAtIndex:indexpath.row];
return cell;
}
I can sense the problem is arising due to some mistake in the above code.
I used CustomCell in the above code to display a customized cell.
can anyone tell me what wrong have i done in this code
Hey try the following code, dont forget to set the cell identifier in you custom XIB to customCellHistory
At the top
#import "customeCellHistory.h"
then
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"customCellHistory";
customCellHistory *cell = (customCellHistory *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"customCellHistory" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.lb11.text=[cellArray1 objectAtIndex:indexpath.row];
cell.lbl2.text=[cellArray2 objectAtIndex:indexpath.row];
return cell;
}
The problem seems to arise from the strange loop you have. Use the last object method to set cell from the nib.
You are reusing a cell and then changing the cell in your loop which probably leads to a cell not existing where you are looking.
if (cell == nil) {
NSArray *topLevelObjects=[[NSBundle mainBundle]loadNibNamed:#"customCellHistory" owner:self options:nil];
You don't need that code. Just register the nib with the table view, earlier on:
[self.tableView registerNib:[UINib nibWithNibName:#"customCellHistory" bundle:nil]
forCellReuseIdentifier:#"customCellHistory"];
Now when you call dequeueReusableCellWithIdentifier, the nib will be loaded and the cell will be delivered, if there is no spare cell in the reuse pile. This ensures that you consistently have a cell and that it is the right kind of cell. Use the methods the framework gives you.
Here's what I am trying to do ultimately. I want to display a menu of items in a UITableView, but dynamically, so that the type of item displayed determines the custom cell view loaded. For example, let's say the menu item type is 'switch', then it will load a nib named 'switch.xib' and the state will be on/off depending on that particular menu item's value. There may be 5 items that are "switch" type, but different values. So I want to use the same xib for each one, but 5 instances.
So, long way around to the question. When I load the cell view from the nib, I would think it would need unique reuse identifiers for the dequeue for when it scrolls back on the screen, right? (Unique for each instance, i.e. each menu item.) In the UITableViewCell in Interface Builder, I see where I can set a reuse identifier property, but I want to set it at run time for each instance of the switch. For example, Menu Item #1 is a switch, #2 is a text field, #3 is a switch, etc. So #1 and #3 both need unique cell ID's to dequeue.
Here's what my cellForRowAtIndexPath looks like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Cells are unique; dequeue individual cells not generic cell formats
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d", indexPath.row];
ITMenuItem *menuItem = [menu.menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
// Load cell view from nib
NSString *cellNib = [NSString stringWithFormat:#"MenuCell_%#", menuItem.type];
[[NSBundle mainBundle] loadNibNamed:cellNib owner:self options:nil];
cell = myCell;
self.myCell = nil;
}
// Display menu item contents in cell
UILabel *cellLabel = (UILabel *) [cell viewWithTag:1];
[cellLabel setText:menuItem.name];
if ([menuItem.type isEqualToString:#"switch"]) {
UISwitch *cellSwitch = (UISwitch *) [cell viewWithTag:2];
[cellSwitch setOn:[menuItem.value isEqualToString:#"YES"]];
}
else if ([menuItem.type isEqualToString:#"text"]) {
UITextField *textField = (UITextField *) [cell viewWithTag:2];
[textField setText:menuItem.value];
}
return cell;
}
You can set the reuse identifier in the nib file. So for switch.xib you would use 'switch' as the reuse identifier. Then just change
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d", indexPath.row];
to
NSString *CellIdentifier = menuItem.type;
assuming that menuItem.type is 'switch'
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil)
{
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
TextFieldFormElement *item = [self.formItems objectAtIndex:indexPath.row];
cell.labelField.text = item.label;
return cell;
}
For my idea, if your types are not too much design each cell in different xib and swift file. Mainly for performance issues.
If not possible to dequeue, give them different identifier. You can register more than one identifier for tableview or collection view (one of our apps using 12 different cells this way.)
But handling IBActions will be little messy this way.
Your custom cell from xib file can be loaded in a way like this. The xib file name is the same as the cell class name and the reuse id.
- (YourCell *)tableView:(UITableView *)_tableView getCellWithId:(NSString *)cellId
{
YourCell *cell;
/* Cell id and xib have the same name. */
cell = [_tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellId owner:self options:nil];
cell = [nib objectAtIndex:0];
}
return cell;
}
When I run my ios app, only the first cell displays in the TableView, then when clicked the second cell displays. I would like them both to display at the same time, but I cannot figure out this behavior.
Here is the code for my view did load
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ProductCellId";
ProductTableCell *cell =
(ProductTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"ProductTableCell" owner:self options:nil];
cell = self.productCell;
}
Product *product = [products objectAtIndex:indexPath.row];
[cell configureForProduct:product];
return cell;
}
Any help would be much appreciated!
Since you are loading your cell from Interface builder try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ProductTableCell"];
if (cell == nil) {
// Load the top-level objects from the custom cell XIB.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ProductTableCell" owner:self options:nil];
// Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
cell = [topLevelObjects objectAtIndex:0];
}
Product *product = [products objectAtIndex:indexPath.row];
[cell configureForProduct:product];
return cell;
}
Change this:
static NSString *CellIdentifier = #"ProductCellId";
to:
static NSString *CellIdentifier = #"ProductTableCell";
You can find additional information for what you are trying to do in this question: Load cells from XIB files