Best way of loading custom cells from a XIB - ios

I have an app, and I'd need custom UITableViewCells, I've been trying different ways, but no one works for what I want, or simply don't work. Can someone guide me how can I do it? Actually the cell, needs to have some UIImageViews and an UILabel and a UITextView. Thanks in advance!

Create a NIB file with a single UITableViewCell in it.
Loading the cell from the nib is a two liner:
NSArray* objects = [[NSBundle mainBundle] loadNibNamed:#"TheFile"
owner:nil
options:nil];
UITableViewCell* cell = [objects objectAtIndex:0];
This method will allways access disk when used, so it can be slow. On iOS 4 and later the is a better help class that caches the NIB in memory, for faster creation. Use like this:
// Cache this one!
UINib* nib = [UINib nibWithNibName:#"TheFile" bundle:nil];
// Then do:
NSArray* objects = [nib instantiateWithOwner:nil
options:nil];
UITableViewCell* cell = [objects objectAtIndex:0];

Related

How to implement reusable xib in other uiviewcontrollers?

I have a an app where I need a form (uitextfield + UIButton) that can be reused in several viewcontrollers.
What is the best way of doing this? I am thinking create a myForm~iPad.xib and myForm~iPhone.xib with one myFormVC.h and one myFormVC.m. But then how would I import this form into my Storyboard views or in to ViewControllers through code?
Or is there a better approach altogether?
There are many different approaches to take but it all depends on your business need so you would need to do some research. This is how you would load a xib via code though:
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"MyNib" owner:self options:nil];
MyNibViewController *myvc = [topLevelObjects objectAtIndex:0];

Correct way to setup a custom cell in the cellForRowAtIndexPath method?

Man, it's annoying how I have to keep referring back to my old xcode projects to find out how to setup a custom cell in my cellForRowAtIndexPath delegate method only because of the magnitude of methods I've seen.
What is the correct code for setting up a custom cell in the cellForRowAtIndexPath method without the use of storyboards?
I am currently doing something like this:
//This works for me btw
static NSString *simpleTableIdentifier = #"customcell";
CustomTableViewCell *customCell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (customCell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomTableViewCell" owner:self options:nil];
customCell = [nib objectAtIndex:0];
}
Then I see other people using loadWithNibName and others that are registering their nibs in the viewDidLoad method using the registerWithNib method.
What in the world is the correct way to setup a custom cell in the delegate method?
I have also been told recently that I dont need to call the dequeueReusable.. method when I'm dealing with custom cells. Can someone please clarify the correct way to setup your cellForRowAtIndexPath delegate method once and for all for me. Without the use of story boards. I have correctly setup my custom cell view with its respective .m and .h files.
If it is CustomTableViewCell nib file exist in same UITableViewController nib your code will works fine. Otherwise you need to load nib file in cellForRowAtIndexPath:
if(cell==nil){
NSArray * nibContents = [[NSBundle mainBundle] loadNibNamed:"CustomTableViewCell" owner:self options:NULL];
NSEnumerator * nibEnumerator = [nibContents objectEnumerator];
NSObject * nibItem = nil;
while ((nibItem = [nibEnumerator nextObject]) != nil) {
if ([nibItem isKindOfClass:[UITableViewCell class]]) {
cell=(CustomTableViewCell*)nibItem;
}
}
}

loadnibnamed method removes registered cells

I use storyboarding for my iOS application. I also need to use
[[NSBundle mainBundle] loadNibNamed:#"myxib" owner:self options:nil];
method to load a nib file.
After I loaded the nib file,
UICollectionViewCell* newCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"recentItemsCell" forIndexPath:indexPath];
starts giving runtime error.
I think calling loadNibNamed method removes the registered cells (that are registered by storyboard) because when I delete the loadNibNamed line, I can dequeueCell without any problem.
is there any way to load a nib file for a view controller by not removing the prototype cell registrations made by the storyboard?
Thanks in advance
Try to load nib manuallay
CustomCell *cell = (CustomCell*)[[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil] objectAtIndex:0];
If the cell is in storyboard , then why do you need to load it using loadNibNamed? If you want to make a separate class for the cell , you can subclass UICollectionViewCell and the call registerClass method in View Controller's viewDidLoad method. In this way you can load the cell which is in storyboard and declare all the properties related to cell in subclass you created.
Hope i am clear.

Custom table cell, custom XIB and long press recognizer - can't make them work together

I have a custom cell that has a button on it. I would like to experiment with using a long press instead.
The code that creates the cell looks like this:
CustomCell *cell = (CustomCell *)[aTableView dequeueReusableCellWithIdentifier:#"CustomCell"];
if (!cell)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil] lastObject];
}
(etc)
So I did this:
CustomCell *cell = (CustomCell *)[aTableView dequeueReusableCellWithIdentifier:#"CustomCell"];
if (!cell)
{
// cell = [[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil] lastObject];
cell = [[[NSBundle mainBundle] loadNibNamed:#"CustomCellDwellToSpeak" owner:self options:nil] lastObject];
}
Then I made a copy of the original xib. Deleted the button. Dropped an UILongPressGestureRecognizer on the cell, and created a target by control-dragging form the recognizer to the file's owner:
- (IBAction)longPress:(UILongPressGestureRecognizer *)sender;
However, once I start generating cells, I get this error:
TypOHD[41541:c07] -[UILongPressGestureRecognizer label]: unrecognized selector sent to instance 0x17d0be60
What's up with that?
I never got or found an answer to the question as such. What I did learn was that this plan is potentially flawed. Apparently mixing your won gesture recognizers in with the table view is a recipe for disaster, or at least heartbreak.
I my case, I decided to go with a fixed layout that consisted of just the number of items that would be shown anyway. In my app I was really only using a table for historical reasons anyway, and never needed to display more than 7 items.
A workaround and a hack, but it worked for me.

More than one custom cell with in the same XIB

Is it possible to have more than one custom uitableviewCell within the same xib?
I'm trying to save XIB files by combining different customized cells within the same xib and then having the Table load different ones from it.
In IB, I tried setting each of the uiTableViewCell class to a different custom class .m/.h implementation. Here is what I tried:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"DevConfigCell";
DeviceInfoCell *cell = (DeviceInfoCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomTableViewCell~iphone" owner:self options:nil];
cell = ( DeviceInfoCell *)[nib objectAtIndex:0];
}
return cell;
}
In another table, i would reuse the nib, but i would do this:
cell = ( SecondDeviceInfoCell *)[nib objectAtIndex:0];
For some reason it always loads the first cell.
Should this all work? or is there a way?
Thanks
I'm trying to save XIB files by combining different customized cells
within the same xib
Why? There's no limit on the number of .xib files you can create.
and then having the Table load different ones from it.
When you load a .xib, all the objects that file contains are created. If you put 10 custom cells in one .xib, loading that .xib will create an instance of each of those 10 cells. That's probably not what you want. Keeping your cells in separate .xibs is probably a better plan.
cell = ( SecondDeviceInfoCell *)[nib objectAtIndex:0];
You seem to be confused about what casting does. When you cast from one type to another, you're not somehow selecting a different object. The object returned by [nib objectAtIndex:0] is always going to be the same if the nib array has the same contents. Casting just changes the type that the compiler associates with the value; in this case it changes the type of the pointer.
You can create an IBOutletCollection in your view controller and then connect several different custom cells to that outlet collection; that'll give you an array of cells that you can select from using objectAtIndex:. But again, that's really not a good idea since you'll be creating all the cells in the file every time you need just one.
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"PlayerAvgsTableCell" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[PlayerAvgsTableCell class]])
{
cell = (PlayerAvgsTableCell *)currentObject;
break;
}
}
}

Resources