简体   繁体   English

Swift-在视图控制器之间传递数据

[英]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. 我是移动开发的新手,我正在用Swift构建一个iOS应用程序,其中涉及一个过程,在该过程中,用户以导航控制器堆栈中的多个视图控制器的形式回答一系列问题。

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. 基本上,我需要捕获用户在其从控制器A到控制器D的过程中单击的所有按钮中的文本。(单击一次按钮会转到下一个视图控制器)到用户到达控制器D时,我要具有代表他从控制器A到C按下的数据的数组。

On controller D, I ask the user if they would like to repeat the process. 在控制器D上,我询问用户是否要重复该过程。 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. 例如,我会问用户关于他们拥有的汽车的信息,如果他们拥有另一辆汽车,D会将其带回控制器A,然后再次重复该过程,将新的响应保存为另一个数组。

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. 我考虑过使用SQlite临时保存数据,但是其他人却告诉我使用NSUserDefaults,因为它花费的时间更少。 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): 删除应用程序启动时保存的内容(在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. 我认为从控制器A到控制器D的路径可以称为用户的会话。 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类(抱歉,Objective-C中的示例而不是Swift中的示例):

Session.h 会话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. 这样,您可以创建一个可全局访问的Session对象( Session *s = [[Session alloc] init]; ),并在所有控制器中使用它。

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. 我要做的(这可能不是唯一的方法,但是对我有用)是在主View Controller以及修改数据的每个View Controller上实例化一个我需要的类型的类。 If I need to update information that refers to that class, I pass the object in the segue (Swift 3): 如果我需要更新引用该类的信息,可以在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. 由于它们是通过引用传递的,因此更改“ remoteObject”中的数据成员也会更改“ localObject”中的数据成员,因为它们引用的是同一对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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