0

My problem's pretty simple. I have a UITableViewController (well, I subclassed it, but that's not the issue), with a static layout, and it's large enough it doesn't fit on the screen all at one time.

I'm using viewWithTag to retrieve the values of a couple UISwitches, but they're just off the screen, so viewWithTag is infuriatingly returning nil.

Frankly, I neither know nor care about the memory overhead of leaving them in memory; it's not much memory to leave lying around, and I'm short on time.

How can I prevent scrolling from triggering deallocation?

EDIT: I know exactly what's wrong, as explained above, just not how to fix it (my usual google-fu came up dry). But since you asked to see the code...

int tag=200
int prefs = 0;
for (int i=0; i != 3; ++i) // There are only 3 preferences
{
    prefs = prefs << 1;
    UISwitch *swt = (UISwitch *)[self.view viewWithTag:tag + i];
    NSLog(@"%@", swt);
    if ([swt isOn])
        ++prefs;
    NSLog(@"%d", prefs);
}

The above code works in viewDidAppear (because the switches are at the top of the table), but not once I have scrolled to the bottom of the table (viewWithTag returns null).

Parthian Shot
  • 1,390
  • 1
  • 13
  • 24
  • Where are the switches placed? Paste your code here, it might help us in understanding the issue ! – Saif Apr 22 '15 at 09:13
  • 1
    Using proper variable names instead of abbreviations won't make your code run any slower. – gnasher729 Apr 22 '15 at 09:28
  • What you are trying to do is bad design pattern: You should not use view components for storing data - only for displaying them. I would suggest using variables representing values you are displaying by `UISwitch`, and keeping them in sync with your `UISwitch`. – Jakub Vano Apr 22 '15 at 09:30
  • @JakubVano I didn't ask whether it was a good design pattern. I know how to do it with event handlers. I just also know it would require me to rewrite a bunch of code I'd rather not rewrite. Besides which, the data _is_ already in the view. When the user scrolls back up, the switch is in the same position. So it's being stored **somewhere**. I just want that storage to be available, rather than duplicated. – Parthian Shot Apr 22 '15 at 09:32
  • @gnasher729 Does the mapping of `prefs --> preferences`, `swt --> switch`, and `i --> index` really throw you? Incidentally, I'm the only one who has to maintain it, and it's pretty clear to me. By which I mean to say that those are the abbreviations I've been using consistently for the past few years, so I'm unlikely to forget them. – Parthian Shot Apr 22 '15 at 09:35
  • @gnasher729 Additionally, `switch` is a keyword, so I'd need to use an abbreviation there, regardless. – Parthian Shot Apr 22 '15 at 09:47

3 Answers3

0

All objects of your cells are available and not destroyed whether on or off the screen. TableView simply reuses the cell.

Hence, you can get any cell's object by:

UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:<requiredIndexPath>];
// Check the status of your cell's switch.

Loop through all the cells of the tableView and you will get it Take a look at the documentation by Apple

Kaey
  • 4,615
  • 1
  • 14
  • 18
  • You shouldn't call cellForRowAtIndexPath yourself. That will only interfere with the operation of the TableViewController. – gnasher729 Apr 22 '15 at 09:26
  • Try it, it simply returns you the object of the required cell. – Kaey Apr 22 '15 at 09:28
  • Yes, and it will explode right in your face when you use it seriously. Because you are not supposed to call it yourself, and it will interfere with the operation of TableViewController. – gnasher729 Apr 22 '15 at 09:30
  • If he can keep an eye on the switch status from the datasource itself, I would prefer that else he has to use this. – Kaey Apr 22 '15 at 09:38
0

If you are using UITableView, then this is absolutely not how it works.

For a UITableView, implement numberOfRowsInSection and cellForRowAtPathIndex, and when you want to change one of the cells, call reloadRowsAtIndexPath.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
0

If you want to access the switch, you should access the object you pass to the data source. There you can access the switch value.

I think you are trying to make a setting in tableView. Here on what I usually do

// create an array to hold the setting data
NSArray *settingArray = @[@{@"title":@"Frequently Asked Questions"},@{@"title":@"Need Help?"},@{@"title":@"Push Notification",@"hasSwitch":[NSNumber numberWithBool: YES],@"switchValue":[[NSUserDefaults standardUserDefaults]boolForKey:@"kPushPreference"]}];

// data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.settingsArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    SettingCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SettingCell" forIndexPath:indexPath];

    NSDictionary *dictionary = self.settingsArray[indexPath.row];
    [cell.settingName setText:dictionary[@"title"]];
    if (dictionary[@"hasSwitch"]) {
        [cell.settingSwitch setHidden:NO];
        [cell.settingSwitch setOn:dictionary[@"switchValue"]];
    }
    return cell;
}

`

usergio2
  • 469
  • 3
  • 12
  • I'm relatively new to iOS, so I'm not sure how I'd go about doing that. I didn't explicitly declare a data source; I just placed a switch. Would `view.dataSource` be what I'd need? – Parthian Shot Apr 22 '15 at 09:45
  • yes exactly, you need to set your `tableView.dataSource = self` and set the protocol – usergio2 Apr 22 '15 at 09:47