简体   繁体   中英

Swift - Passing data between view controllers

I am new to mobile development, and I am building an iOS application with Swift that involves a process where a user answers a series of questions in the form of multiple view controllers in a navigation controller stack.

Basically, I need to capture the text from all the buttons that the user clicks on in his process from controller A to controller D. (One button click leads to the next view controller) By the time, the user reaches controller D, I want to have a array of data that represents what he pressed from controllers A to C.

On controller D, I ask the user if they would like to repeat the process. For example, I would ask the user about a car they own, and, if they own another car, D would take them back to controller A and repeat the process again where the new responses would be saved as another array.

After the user has no more cars, the program moves on to the next section where I would need to load these arrays from before and display different view controllers based on what they entered.

What would be the best way to handle this? I have considered using SQlite to temporarily save the data, but other people have told me to use NSUserDefaults since it takes less time. I will NOT need persistence for this application since I want the user to restart the process from the beginning after they quit the application.

to store a value in one of the viewcontrollers:

let userDefaults = NSUserDefaults.standardUserDefaults()
// user tapped on button 3 (value 2, because 4 buttons => indices 0-3)
userDefaults.setInteger(2, forKey: "Answer1")
userDefaults.synchronize()

to load the values after answering all the questions:

let userDefaults = NSUserDefaults.standardUserDefaults()
let answer1 = userDefaults.integerForKey("Answer1")
let answer2 = userDefaults.integerForKey("Answer2")
...
userDefaults.synchronize()

to delete the saved stuff on application launch (in applicationdidfinishlaunching):

let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.removeObjectForKey("Answer1")
userDefaults.removeObjectForKey("Answer2")
...
userDefaults.synchronize()

good luck! :)

I think the path from controller A to controller D can be called a Session for your user. What you need is a way to store information about this session outside any controller, and this session to be accessible from any controller.

You should create a class Session (sorry, example in objective-C not in Swift):

Session.h

@interface Session : NSObject

- (void)addValue:(id)value;
- (NSArray *)allValues;
- (NSUInteger)valueCount;
- (void)reset;

@end

Session.m

@interface Session () 
{
    NSMutableArray *_values; 
} 
@end

@implementation Session

- (instancetype)init 
{
    self = [super init];

    if( !self ) return nil;

    _values = [[NSMutableArray alloc] init];

    return self; 
}

- (void)addValue:(id)value 
{
    [_values addObject:value]; 
}

- (NSUInteger)valueCount 
{
    return _values.count; 
}

- (NSArray *)allValues 
{
    // NSArray to have a immutable array of values
    return [NSArray arrayWithArray:_values]; 
}

- (void)reset 
{
    [_values removeAllObjects]; 
}

@end

This way, you can create a globally accessible Session object ( Session *s = [[Session alloc] init]; ), and use it throughout all your controllers.

Edit : Learned a lot since my original answer.

What I do (this may not be the only way, but works for me), is to instantiate a class of the kind I need on the main View Controller, as well as on each View Controller that modifies the data. If I need to update information that refers to that class, I pass the object in the segue (Swift 3):

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if let identifier = segue.identifier {

        switch identifier {

            case constants.aSegue: // not the real name of my segue :-P

                // grab inside the navcon
                if let navCon = segue.destination as? UINavigationController {
                    if let destinationVC = navCon.viewControllers.first as? CGSettingsPopupViewController {

                        destinationVC.remoteObject = localObject 
                        // localObject is a kind of the class I need, as is remoteObject 
                        // now, changes to destinationVC.remoteObject will be accessible locally, when the destinationVC returns control


                }
            }

            default:
                break
        } 

    } 

} 

Since they are passed by reference, changing data members in 'remoteObject' also changes the ones in 'localObject' since they refer to the same object.

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