Strange Tableview scrolling behavior - ios

I've got two views, each of which contains a tableview. They are identical in every respect except the height. They are each fed data from the same entity (currently filled with gibberish) in my Core Data store.
One of them works perfectly when scrolled, the other behaves differently. The problem is that the cells scroll past the top section header. Succeeding section titles bump older ones up as expected, and the header title slides up along with the cells.
Here are a couple of screenshots that I hope will illustrate the issue:
First, the one that works properly:
"A" is the top section header, and the cells don't scroll past it.
The next two shots are of the tableview that's behaving weirdly. I've added some arrows to show what's happening:
I've compared the settings in the Attributes Inspector, and unless I've overlooked something, they appear identical.
Anyone have any ideas?
Thanks!
Edit:
Here's the code from the associated UIViewController which is the delegate and the datasource for the TableView:
//
// AvsAViewController.m
// WMDGx
//
// Created by Tim Jones on 2/6/14.
// Copyright (c) 2014 TDJ. All rights reserved.
//
#import "AvsAViewController.h"
#interface AvsAViewController ()
{
NSFetchedResultsController *frc;
}
#end
#implementation AvsAViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self refreshData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[frc sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id<NSFetchedResultsSectionInfo> sectionInfo = [[frc sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
// Customize the appearance of table view cells.
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
// Configure the cell to show the activity's name
ListActivity *thisActivity = [frc objectAtIndexPath:indexPath];
cell.textLabel.text = thisActivity.activityName;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"aVSaCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
cell.textLabel.textColor = [UIColor redColor];
NSAttributedString *attString;
attString = cell.textLabel.attributedText;
return cell;
}
// Section Label
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *sectionLabel = [[[frc sections] objectAtIndex:section]name];
return [sectionLabel uppercaseString];
}
-(void) refreshData
{
//This was the turning point for proper MR grouping. The two Properties (activityCategory and activityName) are used as Sort descriptors in the underlying core data methods
frc = [ListActivity MR_fetchAllSortedBy:#"activityCategory,activityName"
ascending:YES withPredicate:nil
groupBy:#"activityCategory"
delegate:nil];
[self.myTableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

Make sure "Clip Subviews" is selected for that UITableView in the Property Inspector, and that the table's clipsToBounds is not set to NO somewhere in the code.

I resolved the issue by simply deleting the TableView and dragging in a new one, wiring it up. The problem is therefore fixed, but I have no idea what caused it.
Thanks to #drhr, who commented, and all others who took a look!
Edit:
Just wondering if anyone else has run across this problem. I just had it repeat on another tableview, and had to resolve it as above. FWIW, I'm using Xcode 5, and developing an iPhone app.
I guess fixed is good, but it would be nice to actually know what caused the problem.

Related

TableView not scrolling in iOS7

I have a UITableView inside of a View. I've dragged the size of the UITableView to only displays 4 rows at a time. In the ViewController code that loads data into that UITableView, I've generated 6 items to load into the UITableView, because I wanted to verify that it would scroll.
However, when I run the program and preview it in iOS Simulator, it is not scrolling. I have checked that scrolling is enabled (Screenshot).
Here is the code in which the UITableView is populated:
#import "APFacebookFriendsViewController.h"
#interface APFacebookFriendsViewController ()
#end
#implementation APFacebookFriendsViewController
#synthesize facebookFriendsTableView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// set View title
self.title = #"Facebook Friends";
// load Facebook friends
self.facebookFriends = [self getFacebookFriends:#"Test Facebook User"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.facebookFriends count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"CellIdentifier";
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellIdentifier];
UITableViewCell *cell = [self.facebookFriendsTableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
// Configure the cell
NSString *facebookFriend = [self.facebookFriends objectAtIndex:[indexPath row]];
[cell.textLabel setText:facebookFriend];
return cell;
}
- (NSMutableArray *)getFacebookFriends:(NSString *)facebookUser
{
// placeholder data
NSMutableArray *facebookFriendsArray = [NSMutableArray array];
[facebookFriendsArray addObject:#"Friend A"];
[facebookFriendsArray addObject:#"Friend B"];
[facebookFriendsArray addObject:#"Friend C"];
[facebookFriendsArray addObject:#"Friend D"];
[facebookFriendsArray addObject:#"Friend E"];
[facebookFriendsArray addObject:#"Friend F"];
// END placeholder code
return facebookFriendsArray;
}
#end
It's pretty hard to tell what you're doing wrong without looking at your whole project. A few things that you might want to try:
Make sure that the table view is on the top of the other views
Check that table view's userInteractionEnabled is set to true.
Make sure that the table view's delegate and data source points to your view controller.
Try to make the table view full size and see if it's still not scrolling. If so, probably you didn't set one of the table view properties right. You can try to remove and re add the table view.
There are many more things that can go wrong, and as I said it's pretty hard to tell without seeing your project.
1.Check Your table view, and its superviews, has userInteractionEnabled set to TRUE.
2.The custom view that the table view is inside is smaller than the table view with clipsToBounds=NO, a subview that beyond the bounds of its parentview and its not interacted with. so set to clipsToBounds YES.
Insert this into viewDidLoad;
table.delegate=self;
table.datasource=self;

How to let the user reorder sections in a UITableView

I'm working on an app with stocks, arranged in portfolios. So this is a natural fit for the table view, and I'm working on the editing interaction; it's straightforward enough to allow the user to add or delete stocks, drag them around within one portfolio or to another portfolio, but one thing that I haven't been able to do gracefully is let the user drag one portfolio above or below another.
I've got a hacky solution right now, where row 0 of each section is the portfolio name, and if they drag that row above another portfolio, the whole table is reloaded with the portfolios switched. This works, but doesn't feel very natural.
I'm sure I'm not the first to encounter this problem; anyone have a more refined solution?
A related question - how do I let users create a new portfolio/section?
Easy peasy:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
{
NSMutableArray *_data;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_data = [NSMutableArray arrayWithObjects:#"One", #"Two", #"Three", nil];
self.tableView.editing = YES;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"reuseIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:identifier];
}
cell.textLabel.text = _data[indexPath.row];
cell.showsReorderControl = YES;
return cell;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
[_data exchangeObjectAtIndex:sourceIndexPath.row withObjectAtIndex:destinationIndexPath.row];
}
#end
EDIT:
What you've asked for now is a little more complicated. I created an example that puts tables into cells, which gives you nested cells. The example is highly unattractive, but it works, and there's no reason you can't make it look pretty, so check it out:
https://github.com/MichaelSnowden/TableViewInCell
If that doesn't work for you, try making UITableView moveSection:(NSInteger) toSection:(NSInteger) look pretty.
Documentation for that method is here.
My experience with the above method was that it's very easy to use, and it looks nice when it's called. A smart way to use it would be to create headers with tap gesture recognizers. On the first tap, highlight that section and record that indexPath, and on the second tap, call the method on the two index paths. It should work nicely, but you won't get drag-and-drop from it.

Update to Xcode 5.1.1 changed my table view behaviour

I was working in Xcode 4.6 and have a basic UItableview set up where the cells are populated from an array. When working in 4.6, the view behaved perfectly and was just how I liked it. After the update to 5.1.1, scrolling seems to have been enabled on the table view, the table view is loaded from the bottom of the view and the 3 populated cells at the top are not visible. Sometimes the view will rubber band and not allow me to scroll all the way back up to the top, and sometimes it won't rubber band and will let me. I am fairly new to this, but have tried messing around with auto layout, but to no avail.
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_Manufacturers = #[#"1",
#"2",
#"3"];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return _Manufacturers.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
int row = [indexPath row];
cell.TitleLabel.text = _Manufacturers[row];
return cell;
}
The code for UITableView working in Xcode 4.6 should work perfectly in Xcode 5.1.1. Major change I have observed is that table moves under status bar. This can be fixed-up by below snippet :
self.edgesForExtendedLayout=UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars=NO;
self.automaticallyAdjustsScrollViewInsets=NO;
However, provide code so that I can get what's going on.

Why did my bar buttons disappear? And my title didn't change? And a non-existent tableview appears?

I'm making a simple little iOS app incorporating MagicalRecord and Core Data. But I'm baffled by the discrepancies between the storyboard and the app as presented. My two bar buttons (Status and +) do not appear as expected. And regardless of what I type in the title for the view, it always reads "Home" (which was the original text). Also, I originally had a tableview but removed it. Nevertheless, it still appears, slightly askew, as shown in the accompanying screenshot.
I'll mention one other possible clue. I don't understand why it is there, nor do I understand how it could be causing this problem. In fact I plan to make it a separate question. I mention it here only because it is a mystery that a more experienced developer may recognize as suspect. Here it is, from the console:
2014-01-01 22:37:50.691 WMLG1[32260:a0b] CoreData: warning: no NSValueTransformer with class name 'ImageToDataTransformer' was found for attribute 'image' on entity 'Image'
2014-01-01 22:37:50.693 WMLG1[32260:a0b] CoreData: warning: no NSValueTransformer with class name 'ImageToDataTransformer' was found for attribute 'thumbnailImage' on entity 'Recipe'
2014-01-01 22:37:50.724 WMLG1[32260:a0b] +[NSManagedObjectContext(MagicalRecord) MR_contextWithStoreCoordinator:](0x2f30ac) -> Created Context UNNAMED
2014-01-01 22:37:50.724 WMLG1[32260:a0b] +[NSManagedObjectContext(MagicalRecord) MR_setRootSavingContext:](0x2f30ac) Set Root Saving Context: <NSManagedObjectContext: 0x8a47b60>
2014-01-01 22:37:50.726 WMLG1[32260:a0b] +[NSManagedObjectContext(MagicalRecord) MR_newMainQueueContext](0x2f30ac) Created Main Queue Context: <NSManagedObjectContext: 0x8a481b0>
2014-01-01 22:37:50.727 WMLG1[32260:a0b] +[NSManagedObjectContext(MagicalRecord) MR_setDefaultContext:](0x2f30ac) Set Default Context: <NSManagedObjectContext: 0x8a481b0>*
The reason this is mysterious to me is that I have no entities called "Image" or "Recipe" in my model.
I'm pretty green, so anything is possible, although I was being really careful and felt I had a good grasp on the code (although I believe there may be some redundancy). Can someone please point out what I've done wrong?
Here's the relevant code from the HomeViewController:
//
// HomeViewController.m
// WMLG1
//
// Created by Tim Jones on 1/1/14.
// Copyright (c) 2014 TDJ. All rights reserved.
//
#import "HomeViewController.h"
#import "ListActivity.h"
#interface HomeViewController ()
{
NSFetchedResultsController * frc;
}
#end
#implementation HomeViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark Table View stuff
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
frc = [ListActivity MR_fetchAllGroupedBy:#"category" withPredicate:nil sortedBy:#"name" ascending:NO];
return [[frc sections ]count];
}
- (NSInteger)sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)sectionIndex
{
frc = [ListActivity MR_fetchAllGroupedBy:#"category" withPredicate:nil sortedBy:#"name" ascending:NO];
return [frc sectionForSectionIndexTitle:#"category" atIndex:sectionIndex];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
frc = [ListActivity MR_fetchAllGroupedBy:#"category" withPredicate:nil sortedBy:#"name" ascending:NO];
NSInteger count = 0;
NSInteger realNumberOfSections = [frc.sections count];
if (section < realNumberOfSections)
{
// fetchedResultsController has this section
id <NSFetchedResultsSectionInfo> sectionInfo = [frc.sections objectAtIndex:section];
count = [sectionInfo numberOfObjects];
}
else
{
// section not present in fetchedResultsController
count = 0; // for empty section, or 1 if you want to show a "no objects" cell.
}
return count;}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
frc = [ListActivity MR_fetchAllGroupedBy:#"category" withPredicate:nil sortedBy:#"name" ascending:NO];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Check if a reusable cell object was dequeued
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Populate the cell with the appropriate name based on the indexPath
cell.textLabel.text = [frc.sections objectAtIndex:indexPath];
return cell;
}
#pragma mark Table View Delegate stuff
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
#end
Delete the app from the simulator by selecting "Hardware" from the bar at the top of screen and then "Home". Click and hold down on your app icon until a little "X" appears then click it to delete the app. In Xcode go to "Product" at the top and click "Clean". Then try running the app on the simulator again.
Is the Home View Controller your Initial View Controller?
You implemented UITableView control methods in your Home View Controller but asked about a UITableView showing up. Is that controller supposed to be a UITableViewController or is it simply a delegate?

Why can't I initialize a UITextField from a subclass of UITableViewCell?

I've created a subclass of UITableViewCell for an iPad app. I need to dynamically generate text fields, take input from the user, and then store that information in an array. I thought of asking the UITableViewCell for the UITextField.text object, which would hold whatever the user wrote before my View Controller's segue (I'm saving the NSString objects upon the segue being called). So I've got an array of UITableViewCells which I ask for the UITextField.text object. But for some reason while my UITableViewCell subclass is being created, my UITextField is not. I can call UITableViewSubclass and it's initialized, but UITableViewSubclass.UITextField is nil.
Here's my UITableViewCell Subclass header (Yes, the UITextField is connected in the storyboard):
#import <UIKit/UIKit.h>
#interface ConditionCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UITextField *condition;
#end
Here's my implementation file:
#import "ConditionCell.h"
#implementation ConditionCell
#synthesize condition;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.condition = (UITextField *)[self viewWithTag:10];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
This here is the Table View Controller handling the table that contains the cells:
.h file:
#import <UIKit/UIKit.h>
#import "ConditionCell.h"
#interface ConditionsTableViewController : UITableViewController
#property (strong, nonatomic) NSMutableArray *conditionCellArray;
- (void)addNewConditionCell;
#end
.m file:
#import "ConditionsTableViewController.h"
#interface ConditionsTableViewController ()
#end
#implementation ConditionsTableViewController
#synthesize conditionCellArray = _conditionCellArray;
- (NSMutableArray *)conditionCellArray
{
if (_conditionCellArray == nil) {
// Create the array object
_conditionCellArray = [[NSMutableArray alloc] init];
}
return _conditionCellArray;
}
- (void)addNewConditionCell
{
ConditionCell *condCell = [[ConditionCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"conditionCell"];
[self.conditionCellArray addObject:condCell];
[self.tableView beginUpdates];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.conditionCellArray.count-1 inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
[self.tableView reloadData];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.conditionCellArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"conditionCell";
ConditionCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ConditionCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
//cell.condition = (UITextField *)[cell viewWithTag:1];
return cell;
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
This Table View Controller lives inside a UIView Controller as the table view does not take up the whole screen. When the user presses an 'ok' button there is a segue that is triggered and it is here that I ask this Table View Controller for the array containing the UITableViewCells, which I then run through a foreach to get their .text properties. Unfortunately I can't seem to get anything I input into the text fields, hence the .text's are always nil. If anyone could help me with this issue it would be greatly appreciated!
You might find this much easier to do using the free Sensible TableView framework. The framework has these text field cells out of the box, and can even create them automatically from your array.
I figured out a better way to do what I wanted to do here that works. Turns out that the way iOS's UITableView works is totally different from what I wanted to do. UITableView works by looking at your storyboard and given the identifiers for the cells, it creates them and allows you to set their properties within the cellForRowAtIndexPath method. However, when the cell goes offscreen, it is not retained as it's own separate object; it is reused. So, you can think of it as if when you scroll a table view, the cells that disappear to one end reappear on the other end with new information. This is key - UITableView want YOU to provide the cell's information. It was not made for input of information directly on a UITableViewCell, which is what I wanted to do.
So what I ended up doing was copy-pasting my cells into their own .xib file, and in the subclass initWithStyle:reuseIdentifier method, do:
NSArray *nibArray = [[NSBundle mainBundle] loadNibNamed:#"ConditionCell" owner:self options:nil];
self = [nibArray objectAtIndex:0];
And that creates the cell with whatever style - setup - UI elements you want.
Next, I want to hold on to a reference to the cell, because that cell has a textbox, and I need to save what's on the textbox when the user presses a "done" button. However, testing revealed the reuse problem I explained above. So how to do this? In my Table's view controller, whenever the user wants to add a new textbox (and presses the button to do so) I have a method which does
[self.conditionCellArray insertObject:[[ConditionCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"conditionCell"] atIndex:0];
This adds a new cell to an array - this is important because I need to have a reference to ALL cells at all times. (It is adding the cell at index 0 because I want to insert it at the top). Then, in the cellForRowAtIndexPath method, I did
return [self.conditionCellArray objectAtIndex:indexPath.row];
Which will return the corresponding cell. Bear in mind, from what I have read this whole thing about keeping a reference to each and every cell in the table is contrary to Apple's stated best practices when using UITableView. However, as I said before, UITableView is meant to display information, not to gather it from user input. So this is why I had to break the rules, if you will, to achieve the desired effect (that I wanted). I hope this helps others who are looking to do the same thing; and if there is a better way don't be shy about telling me.
EDIT: Oh by the way, when you copy paste the cells created in storyboard to their own .xib file make sure to disconnect any IBOutlets and change their class back to UITableViewCell. That way there won't be any problems or conflicts when you connect your .xib file cell.

Resources