简体   繁体   中英

Saving an array of booleans to UITableView

What I'm trying to accomplish is to build a UITableView where each cell has a UISwitch on the right, and when the user opens the app again the switches stay in their on/off positions at the corresponding index path.

I created an NSArray of Booleans and saved them to NSUser defaults but had some road blocks while looping back through them to get the bool at the correct index to set the cells toggle switch to either on or off.

Would creating a custom cell with an index path property be a better idea? Then just have a method to save the bool to the index path?

I'm relatively new to programming so I would just like to know what some more advanced folks think is the quickest and easiest way to go about this.

Many thanks!

Here is my boolean controller where the save method is public,

#import "BoolController.h"

static NSString *const boolArrayKey = @"boolArrayKey";

@implementation BoolController

+ (BoolController *)sharedInstance {
static BoolController *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    sharedInstance = [BoolController new];
});

return sharedInstance;

}

- (void)saveBool:(BOOL)boolean {

NSArray *arrayOfBooleans = [[NSArray alloc]init];

arrayOfBooleans = [arrayOfBooleans arrayByAddingObject:[NSNumber         numberWithBool:boolean]];

[[NSUserDefaults standardUserDefaults]setObject:arrayOfBooleans     forKey:boolArrayKey];
[[NSUserDefaults standardUserDefaults]synchronize];

}

- (NSArray *)booleans {

   return [[NSUserDefaults standardUserDefaults]objectForKey:boolArrayKey];

}

@end

and here is my cell for row at index path method

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

UISwitch *toggleSwitch = [[UISwitch alloc]initWithFrame:CGRectMake(50, 10, 50, 30)];
[cell addSubview:toggleSwitch];

if (toggleSwitch.isOn == YES) {

    [[BoolController sharedInstance]saveBool:YES];
}

if (toggleSwitch.isOn == NO) {

    [[BoolController sharedInstance]saveBool:NO];
}

return cell;

}

As far as I understand your problem I've come to the following conclusion:

  1. You should definitely honor the MVC pattern - so you don't store data in an UI object ( VIEW ).
  2. Your saveBool method creates a new instance of the array on every call and overwrites the recent one when you sync it to the user defaults. Use an ivar in your CONTOLLER that outlives the scope of your function call instead...

You should just take the index path of your row and store the ON/OFF state at the same index of your array. This array is the MODEL in your MVC setting...

So next time you create your tableview every row (index) gets exactly the right bool from the array (index) for your switches!!!

  1. The switch is an UI element ( VIEW ). You put it in the cell in the storyboard. All that you see there is UI - the table view, your cells etc. The only thing in the storyboard that is not UI is the view controller ( CONTROLLER ).
  2. For such a little application you don't need an independent class for your model. Anyways, it will get stored in your user defaults... -> So just add an array ( MODEL ) as an instance variable (or declared property) to your view controller. So it will be alive as long as your view is.
  3. Whenever you loop through your row index - for instance to check the state of your switches - do it with a for loop (i=0 ... i++) and you already get your index with the i variable of the loop. So write it exactly at that index into your array. Of course you created the the table view with the same indexes out of the array (of your data MODEL ) in the first place - so the rows and your whole table VIEW reflect your MODEL array. That way you are always in sync. When the user moves the switch ( VIEW ) you'll get notified which row it was in and voila -> update your MODEL array and refresh your table VIEW with the new information of your model. All the updating an synching should be done by the CONTROLLER .

The MODEL is TRUTH. Always create and refresh the VIEW with the information you find in your MODEL . If the VIEW changes - let the CONTROLLER update the MODEL and vice versa... - And every now and then update your user defaults with the values of your temporary MODEL array. Because if the app crashes or gets killed by the system you need to read back the model values for your array from the user defaults. If it's not up to date you will get the values of your last sync...

In summary I would advice you to have some more reading about the design patterns in iOS programming. That's the scaffolding of every application. Without that you'll be lost anyways. If you're not that much into reading (which is pretty bad for a programming geek) definitely go to ' iTunes U ' -> Stanford University / Paul Hagerty

  • Coding Together
  • iOS application programming

Lectures of 2010 - 2014 (sometimes two courses per year) for ObjC
Lectures of late 2014 for Swift.

Every quarter has about 18 lectures of video. They all cover the same topics and just extend information on new technologies added to iOS. Watch them ALL - starting with 2010 - Table views eg get covered better in the first years...

This is really a hardcore corrida from absolutely newbie to (almost) pro ;-) and is a lot of fun - The guy, his knowledge and his way of lecturing is simply amazing.

So - enough talking - back to work!

Have fun exploring the SDK

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM