UITableViewCell Subclass loading from nib, subclass is file owner
Hi,
I'm trying to make a table view with special cells that have labels and sliders, and so I made a UITableViewCell subclass and I am having trouble setting up the view (program crashes)
I've got a TableViewController that has the following "CellForRowAtIndexPath" Function: (change names to be more generic)
The documentation that talks about subclassing UITableViewCell talks about using loadNibNamed, and setting the TableViewController as the file owner. What I've done is set the UITableViewCell subclass as the file owner of the nib (and connected all the outlets to it as well). I thought this would be a much cleaner approach, especially since my custom cells have sliders in them that I want to monitor. If I make the tableViewController the file owner, it has to manage all those sliders individually (or is there something I'm missing there?) My method is to set the controller as the delegate and send it a message from the cell instance describing the slider change.
Here is the custom init method from the UITableViewCell subclass (it crashes in here)
Am I supposed to use load nib named here? Isn't it enough to set the file owner? Are you supposed to use a view controller subclass to load nibs? Any help would be appreciated. Please let me know if you need to see more code. I hope I didn't mis-type anything when I changed the variables, but if you see something that looks like that, that's probably not what's causing the problem. I'm not very clear on what the crash is caused by, but it does say:
Warning: the current language does not match this frame.
warning: Unable to restore previously selected frame. in the console
I guess it's just hanging indefinitely? Not even sure how to debug this, although I did pinpoint the location of the crash using my NSLogs.
Or both? Or include the label as a member but don't put IBOutlet on both things?
thanks!
EDIT: The documentation seems to focus more on programmatically drawing the content for UITableViewCells, and I've seen some people online saying you shouldn't build table view cells from Nibs. Any comments?
Last edited by shimmy; 11-08-2011 at 11:33 AM.
Reason: additional comment
anyone...?
I'm thinking I should do something like, LoadNibNamed in the CellForRowAtIndexPath function in the UITableViewController, and set the file owner to be the subclass?
What does it mean if your file owner is nil in that function?
Can only view controllers load nibs?
Last edited by shimmy; 11-08-2011 at 11:37 AM.
Reason: better bump
See the table view link in my signature for guidance.
Hey, I feel like my approach has probably been all wrong.
Have a few questions though.
Does it really matter whether you put
Code:
@class CustomCell;
in the .h file, and then #import in the .m? Can't you just put #import in the .h file and leave it out in the .m?
I tried doing @class in one and #import in the other, but it wouldn't recognize the delegate protocols in the table view controller class delegate (CustomCellDelegate) in the .h file, so that the cell can communicate with the table view controller.
Also, why do you subclass UIViewController? Why not UITableViewController?
Is it really true that the only way to manage actions inside a table view cell is by using tags/indices? That was essentially how I did it originally, and I felt that was extremely disorganized and inefficient, so I made a UITableViewSubclass with the intention that it would manage all that, and just let the controller know what changed. Why doesn't my approach work (setting the nib's owner to the UITableViewCell subclass) ? Are you not allowed to load a nib from anything other than a view controller subclass (I guess that makes sense...) ? Either there's something very wrong with my approach, or there is a way to make it work...
in the .h file, and then #import in the .m? Can't you just put #import in the .h file and leave it out in the .m?
Generally speaking, you put @class in the .h file, and #import in the .m file. However...
Quote:
Originally Posted by shimmy
I tried doing @class in one and #import in the other, but it wouldn't recognize the delegate protocols in the table view controller class delegate (CustomCellDelegate) in the .h file, so that the cell can communicate with the table view controller.
...that would be the exception. Although I don't see people making cell delegates all that often, so I'm suspicious of the approach.
Quote:
Originally Posted by shimmy
Also, why do you subclass UIViewController? Why not UITableViewController?
Choice. UITVC is more trouble that it's worth, IMO.
Quote:
Originally Posted by shimmy
Is it really true that the only way to manage actions inside a table view cell is by using tags/indices?
The question doesn't really make sense, so I'm going to say no.
Quote:
Originally Posted by shimmy
That was essentially how I did it originally, and I felt that was extremely disorganized and inefficient, so I made a UITableViewSubclass with the intention that it would manage all that, and just let the controller know what changed. Why doesn't my approach work (setting the nib's owner to the UITableViewCell subclass) ? Are you not allowed to load a nib from anything other than a view controller subclass (I guess that makes sense...) ? Either there's something very wrong with my approach, or there is a way to make it work...
Well, you don't really seem to know what you're doing, so there's that. There's nothing magical about File's Owner. Who should own the objects being created by this nib file? That's File's Owner. And you can load a nib from any class.
If you think about a common view controller structure - .h, .m, .xib - what you are doing in the .xib is creating a view. Where is that view going to be used? It will be the view that is managed by the view controller. How does that happen? By linking it to the VC's "view" outlet. All you are doing when you change the class of File's Owner is changing which outlets are available. When you select a UIVC subclass, there's your view outlet. If you made it, say, an NSString, then you wouldn't have that outlet, so you couldn't make that connection.
Once that is set, the specific class of File's Owner doesn't really matter. You could load that nib from any class, and as long as that class has a view outlet, it will work. If it doesn't, it will crash as the loader attempts to use the view property that isn't actually there.
The problem with your code as it appears in the OP is that you never actually use the nib. The simple act of creating a nib does not mean it gets used automatically. You have to deliberately use it.
So, try again using the technique outlined in my tutorial. I'm a little unclear on the problem you are attempting to solve. But when you make statements like this:
Quote:
Originally Posted by shimmy
If I make the tableViewController the file owner, it has to manage all those sliders individually
...it's quite clear that you don't really understand table views, so you are prematurely trying to "improve" things.
You're absolutely right; My post is a bit chaotic and confused; sorry for my ignorance.
(I've been trying to get onto this site for a while and it was giving me malware warnings until now. What gives?)
I went through the tutorial and I think I have a much better handle on everything. I was missing some important elements in my understanding on how interface builder files work. I now have the UITableViewController as the file owner in the nib file, with an outlet for my custom UITableViewCell subclass, which is also connected in the nib, as well as the labels and a UISlider inside the subclass. Unfortunately, it looks like I'm still missing something, as the cell is not being allocated properly, and the cell is still nil after the loadFromNib call in the cellForRowAtIndexPath function. I don't see where the cell is being allocated. loadFromNib allocates it? Shouldn't there be some kind of call to initWithStyle, etc? Your tutorial code works fine on my computer, but I must be missing something because I don't see any major differences except that you don't use a UITableViewController subclass. I'll keep looking, please let me know if you are aware of anything I might be missing.
By the way, I am using a delegate method to send slider value changes (the sliders are inside the custom cells) up to the UITableViewController so it can save the changes. The delegate method is able to pass the table view controller what cell it's coming from, as well as the changed value, so it can store it in the appropriate place. I'm not familiar with a better way to do this. Do you have any suggestions?
Figured it out. Made a pretty shamefully simple mistake in the subclass (along with a few other newb mistakes). I had customized the setter methods for the members of the UITableViewSubclass, but like a complete fool I had used the '.' syntax inside the setter method.
eg.
-(NSString*) setTitle: (NSString*) title {
self.title = title;
//and other stuff
}
which, of course, ends up in an infinite loop, presumably.
This is what happens when you make a lot of code without testing it in little bits first.
Your tutorial helped me a lot. I used your example code to replace my subclass and found that the cell was allocated fine, so it was something else. Then I brought one piece at a time into the class until I found the culprit (along with a few other missing things). Thanks a lot for your help and patience Brian!