Search code examples
swiftuser-interfacetvos

How to keep the segment chosen when change view in tvOS?


I have a segmented control in a tvOS app that is used to choose the background of the main view. Unfortunately every time I change view and back to the main view the chosen segment is lost and the contro resets to the default choice. What is the best way to get keep the user choice?


Solution

  • MVC (Model-View-Controller) pattern is the solution.

    • Segmented Control in this case is a View
    • The ViewController with SegmentedControl is a Controller
    • You have to create a Model for the background color.

    The model is changed and stored upon selected segment UIControlEventValueChanged event. The Segmented Control selection is determined from the Model when Controller refreshes the View.

    Below is a one example, how you could do this. As a Model I decided to use BackgroundColorIndex translated to/from selectedSegmentIndex. The snipped utilise NSUserDefaults to store the model and determines the background color and index when the controller reads from model.

    #import "ViewController.h"
    
    typedef NS_ENUM(NSUInteger, BackgroundColorIndex) {
        BackgroundColorIndexBlack = 0,
        BackgroundColorIndexBlue,
        BackgroundColorIndexGreen,
    };
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UISegmentedControl *segmentedControl;
    @end
    
    @implementation ViewController
    
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
    
        // restore & set previously stored state
        [self restoreState];
        [self changeBackgroundColorWithIndex:self.segmentedControl.selectedSegmentIndex];
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // the code from viewWillAppear: could be here, but I don't know specifycally
        // what flow do you have and what method is appropriate to handle selected segment change action
    }
    
    - (IBAction)segmentedControlDidChangeValue:(id)sender {
        if ([sender isEqual:self.segmentedControl]) {
            // change & save current state
            [self changeBackgroundColorWithIndex:self.segmentedControl.selectedSegmentIndex];
            [self saveState];
        }
    }
    
    - (void)saveState
    {
        NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:@(self.segmentedControl.selectedSegmentIndex) forKey:@"colorIndex"];
        [defaults synchronize];
    }
    
    - (void)restoreState
    {
        NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
        id storedObj = [defaults objectForKey:@"colorIndex"];
        if (storedObj) {
            NSInteger index = [(NSNumber *)storedObj integerValue];
            self.segmentedControl.selectedSegmentIndex = index;
        }
        else {
            // first launch state
            self.segmentedControl.selectedSegmentIndex = 0;
        }
    }
    
    - (void)changeBackgroundColorWithIndex:(BackgroundColorIndex)colorIndex
    {
        switch (colorIndex) {
            case BackgroundColorIndexBlack: {
                self.view.backgroundColor = [UIColor blackColor];
            } break;
            case BackgroundColorIndexBlue: {
                self.view.backgroundColor = [UIColor blueColor];
            } break;
            case BackgroundColorIndexGreen: {
                self.view.backgroundColor = [UIColor greenColor];
            } break;
            default:
                break;
        }
    }
    @end