I'm creating custom UITableViewCells using the approach outlined on this page:
http://icodeblog.com/2009/05/24/custom-uitableviewcell-using-interface-builder/
So my cellForRowAtIndexPath code looks a bit like this:
static NSString *CellIdentifier = #"CustomCell";
TableCellWithLogo *cell = (TableCellWithLogo *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:#"TableCells" owner:nil options:nil];
for (id currentObject in nibObjects)
{
if ([currentObject isKindOfClass:[TableCellWithLogo class]] )
{
cell = (TableCellWithLogo *)currentObject;
}
}
}
cell.customTextLabel.text = [tableArray objectAtIndex:indexPath.row];
return cell;
Now, the table I'm creating looks like a stylized version of the grouped tableview style, with drop-shadows etc. So it needs four possible styles of table (top, center, bottom .. and top+bottom for when only a single cell is showing).
I'm having trouble working out how to put all of these table cells into one nib, and then refer to them. At the moment I have a nib with a UITableViewCell whose class is 'TableCellWithLogo'. This class has all the relevant IBOutlets. If I put several UITableViewCells in the nib (all of TableCellWithLogo class), how would I be able to differentiate between them in code? You can see in the example above I'm finding out the class:
if ([currentObject isKindOfClass:[TableCellWithLogo class]] )
..but all the classes would be the same, so I'm not sure how to differentiate?
Create one empty nib and add table view cells to it. Also, for each of them create a corresponding class and assign the relevant class for each of them (see the screenshot).
Then, in the cellForRowAtIndexPath you'll need to create different cells based on indexPath.row
Related
This is very common question at SO though I have google and cross check my code few times but I am not able to figure out the crash
*** -[MyCustomCell performSelector:withObject:withObject:]: message sent to deallocated instance 0x96f6980
I have a CustomCell named MyCustomCell with XIB where I have 3 buttons for Facebook,Twitter,LinkedIn. I gave them all IBAction in CustomCell class.
When I click on any of them I get this kind of crash.
I am using ARC.
In my ViewController class I have cellForRowAtIndexPath
{
static NSString *CellIdentifier = #"MyCustomCell";
MyCustomCell *cell = (MyCustomCell*)[myTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (MyCustomCell *)[nib objectAtIndex:1];
}
return cell;
}
MyCustomCell.m
- (IBAction)facebookPressed:(BaseButton *)sender {
}
- (IBAction)twitterPressed:(BaseButton *)sender {
}
- (IBAction)linkedInPressed:(BaseButton *)sender {
}
I made this mistake just today! :) all you gotta do is replace the 2 lines
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"NameOfCustomCellNibFile" owner:self options:nil];
cell = [nib objectAtIndex:1];
You have to load the loadNibNamed: with the .xib file's name. I also thought it was with the identifier, but that is regarding the name that is referenced into the cell instead of the nib for the cell.
Hope this helps!
you can also code for Custom cell like this way. At nib of custom cell drag one UIButton and set it's tag in Xib. then use bellow Method:-
UIButton *btnMulSelected;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier =[NSString stringWithFormat:#"%d_%d",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
[[NSBundle mainBundle]loadNibNamed:#"cell_custome_iphones" owner:self options:nil];
cell = self.tblCell;
self.tblCell = nil;
btnMulSelected =(UIButton*)[cell.contentView viewWithTag:2];
[btnMulSelected addTarget:self action:#selector(MyButtonAction:) forControlEvents:UIControlEventTouchUpInside];
}
return cell;
}
Do not connect IBAction from Nib. just connect Custom-cell IBOutlate or put Unique UIButton tag from nib.
You've to keep the class name of cell and the XIB names same.
Keep the owner nil generally.
Also, if there is only 1 view ( i.e. 1 UITableViewCell in your case ), then this view is available at index 0 instead of index 1.
Inside the XIB file, make sure you link the button to your view itself, i.e. to IBOutlet or IBAction.
The linked buttons must be already added to your view, not floating outside in XIB. Otherwise they will instantiate and come at other indices of the loaded array. If you don't want a certain button for some time, then just keep it hidden.
So the code can be as below:
NSArray *views = [[NSBundle mainBundle] loadNibNamed:#"MyCustomCell" owner: nil options:nil];
MyCustomCell *cell = (MyCustomCell*)[views objectAtIndex:0];
Further make sure you do the following for creating XIB
Ok, then here goes the other portion simple process:
Create a MyCustomCell class derived from UITableViewCell class.
Create a separate .xib file with same name as MyCustomCell.xib.
Open .xib and delete the existing view in it. drag and drop a new
UITableViewCell from the objects of editor.
See the image to change the class name of the UITableViewCell in XIB to your class name.
Now the objectAtIndex 0 will return MyCustomCell.
Add all your buttons and other views in this UITableViewCell of your XIB.
My tableView scrolls with lags if extra populated. Up to 20 cells go well, but above - it starts lagging while scrolling. Please, suggest an implementation with a better scrolling result. Here is the way I did it:
I have defined a custom UITableViewCell class.
The cell has 4 labels and an imageView (each outlet is a synthesized property):
I have placed a tableView in my viewController, and populated it like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomCell";
MyCustomCell *cell = (MyCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"MyCustomCell" owner:self options:nil];
for (id currentObject in topLevelObjects)
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (MyCustomCell *) currentObject;
break;
}
}
[cell.label_descr setText:#"bla-bla-bla"];
[cell.label_date setText:#"bla-bla-bla"];
[cell.label_time setText:#"bla-bla-bla"];
[cell.label_numeric setText:#"bla-bla-bla"];
[cell.image_view setImage:[UIImage imageWithContentsOfFile:#"bla-bla-bla"]];
return cell;
}
The amount of text in each cell, as you can see, is miserable, and the image used for the UIImageView is about 25x25 .png file.
My tableView is supposed to hold more than 300 cells (don't blame on me, I have a "customer from hell").
Please, suggest a way to make the tableView scroll smoother, without (much) lags. Or an alternative way to present those "damn-over-300-cells" to my "from hell" customer.
300 thanks in advance!
P.S.: sorry if duplicated, but the solutions found didn't help at all.
EDIT:
About the image used for the imageView:
I use 2 different images only:
a "checkmark" - transaction done
and a "pending" - transaction in process
Maybe I use to define 2 imageView outlets in my tableViewCell xib, and just selecting the needed imageView, instead of setting each time the required image?
SOLUTION FOUND, thanks to everybody, especially to iNoob and max_.
In tableViewCell's xib, I have set the "checkMark" as the default image of the imageView.
When defining the cell's values, in cellForRowAtIndexPath, only if needed, I say:
if_I_should_present_a_pending_image:
[cell setPending];
to replace the "checkMark" with a "pending" image (method defined in tableViewCell class):
- (void)setPending{
self.image_view.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"pending_1.png"],
[UIImage imageNamed:#"pending_2.png"],
[UIImage imageNamed:#"pending_3.png"],
[UIImage imageNamed:#"pending_4.png"],
nil];
self.image_view.animationDuration = 2.0;
self.image_view.animationRepeatCount = 0;
[self.image_view startAnimating];
}
l
After that, the table scrolls like a charm. Thanks to everybody again. Cheers.
Don't iterate through all of the subviews: cell = [topLevelObjects objectAtIndex:0];
Load the images in the background using gcd, and store them in an NSDictionary for easy access:
Pseudo code:
If caches dict contains an object for the URL you want to load
Retrieve that image from the dict
Set it as the image
Else
Load the image using dispatch_async()
Add it to the dict
I found this article suggesting that creating the cells programatically instead of using a nib file could be up to 5-10% faster. I don't know if it's true or not, so take it with a grain of salt, but it may be worth a try.
Replace your code with following one and try it out.
For the below code :
1) Take IBOutlet of your UITableViewCell in the your controller. for below code it is myCustomTableViewCell.
MyCustomCell *customCell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:#"MyCustomCell"];
if(customCell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"MyCustomCell" owner:self options:nil];
customCell = myCustomTableViewCell;
}
Hope it will work.
Is there any way to show data in the grid view form in ipad application
I want to show the data in grid view in ipad application i have searched a lot some say use custom table view but it is not looking i want full professional i found iOS DataGrid TableView for ipad.
Is it ok to use wether it is free or not. And how to implement this if it possible or not.
Below is the link of iOS Grid
http://www.binpress.com/app/ios-data-grid-table-view/586
How can you not have stumbled upon AQGridView.
However if you are just interested in styling a cell only, you can implement a custom uitableview cell which has few grids and style them according to your requirement.
There are many tutorials out there showing how to customize a UITableViewCell.
Create custom UITableViewCell as per your requirement and load that cell to table view cell.
You can use below sample code to load custom cell with in table's cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *sCellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:sCellIdentifier];
if (cell == nil) {
NSArray *topLevelObject = [[NSBundle mainBundle] loadNibNamed: #"CustomCell" owner:self options:nil];
for (id currentObject in topLevelObject) {
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (CustomCell *)currentObject;
break;
}
}
}
cell.label1.text = #"label1"; // you can access all controllers of your custom cell like this way
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
By Using the CustomUITableViewCell you can get the same.i.e Take the UITableviewcell and add the three or four labels to it.Then Pass the data in cellForRowAtIndexPath method.
I used GMGridview, it has an example and basically if you change the cell size, and columns you can make it fit in iPad or iPhone. You can also add UITextField (instead of the default UILabel), if you need to input data. One nice feature is it can scroll.
http://www.gmoledina.ca/projects/gmgridview/
Feel free to ask if you have any questions.
We use this one in our application : http://www.ioscomponents.com/. We like it so far.
Currently I have the following method, but it doesn't quite work...
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TVCell" owner:self options:nil];
cell = tvCell;
self.tvCell = nil;
}
UILabel *label;
label = (UILabel *)[cell viewWithTag:5];
label.text = [NSString stringWithFormat:#"Hole #%d", indexPath.row];
return cell;
}
The table view gets created with no errors, but each individual cell contains nothing, but clearly the TVCell.xib has a label with a tag of 5. The only question I have is this. I don't quite understand these steps apple gives here...
Select File’s Owner in the nib document window, open the Identity pane of the inspector, and set the class of File’s Owner to your custom view controller class.
Connect the cell outlet of File’s Owner (now the placeholder instance of your custom subclass) to the table-view cell object in the nib-file document.
Here is where those steps are...
http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7
Can someone please explain those steps for a noob like me? I think that is what I messed up on, but I could have done anything wrong.
I don't think TcCell becomes a property of self. Try this instead when the cell queue is empty:
if (cell == nil) {
cell=[[NSBundle mainBundle] loadNibNamed:#"TVCell" owner:self options:nil];
}
It's kind of difficult to explain the steps that you said you don't understand in words. I would suggest looking for tutorials that have images or videos for that. (I did a quick search and there are lots available, but I didn't really want to choose one to direct you to without having read them more closely).
However, I prefer to create custom table view cells this way:
http://www.mobilesce.com/2011/12/27/the-best-way-to-do-custom-reusable-uitableviewcells/
It's slightly different from the way described in the apple docs, but I've seen a lot of people use it and I find it easier.
The NSBundle method loadNibNamed:owner:options: returns an NSArray containing the top level objects in your nib file. Try this:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:#"TVCell" owner:self options:nil];
cell = [nibArray objectAtIndex:0];
}
I have Custom uitableviewcell: ScrollViewCell
I want to know what the difference is between the following code
static NSString *CellIdentifier = #"ScrollViewCell";
ScrollViewCell *cell = (ScrollViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
//***** WHAT IS THE DIFFERENCE BETWEEN THIS CODE AND..
NSArray *xibObj = [[NSBundle mainBundle] loadNibNamed:#"ScrollViewCell" owner:nil options:nil];
for(id currentObj in xibObj){
if ([currentObj isKindOfClass:[ScrollViewCell class]]) {
cell = (ScrollViewCell *) currentObj;
}
}
//***** ..THIS CODE
cell = [[ScrollViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Which one should I use and why?
The first example will load a cell from a .xib file in your application's bundle. Each cell can handle it's own code, and behaves a lot like a UIViewController. This approach can get complicated when you try and load data from an array. You have to pass the object you're getting data out of to the cell, and have a very clear design before you start coding.
The other method allocates an empty instance of the UITableViewCell class as normal. This approach is typically used for programmatic configuration of the cells. You'll probably see this one in most places.
Good luck,
Aurum Aquila