【问题标题】:Is it okay to have a lot of segues between view controllers?在视图控制器之间有很多segues可以吗?
【发布时间】:2016-03-08 01:35:14
【问题描述】:

所以我对 iOS 开发还很陌生,并决定冒险走这条捷径。我现在正在使用多个视图控制器并在它们之间传递数据,我想知道在 2 个视图控制器之间有多个(如 9-15 个)segues 是否是不好的做法?

基本上我拥有的是一个普通的 VC,有 9 个不同的按钮。现在,我想要的是每个按钮将不同的数据发送到后续的选项卡式 VC,而不是为每个按钮/类别使用不同的 VC。

它看起来像这样:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    let tabBarController = segue.destinationViewController as! UITabBarController
    let svc = tabBarController.viewControllers![0] as! InfoViewController
    let svc2 = tabBarController.viewControllers![1] as! DIYViewController

    if segue.identifier == "wind" {
        svc.titleString = "Wind Power... what a powerful thing"

    } else if segue.identifier == "geothermal" {
        //send info about geothermal
    } else if segue.identifier == "hydroelectric" {
        //send infor about hydroelectricity
    } else if segue.identifier == "" {
        //code
    } else if segue.identifier == "" {
        //code
    } else if segue.identifier == "" {
        //code
    } else if segue.identifier == "" {
        //code
    }
}

有没有更传统的方法来实现这一点?

【问题讨论】:

    标签: ios swift uiviewcontroller uitabbarcontroller


    【解决方案1】:

    您应该只有一个 segue,并在 prepareForSegue(_:sender:) 中传递数据。例如。在您的第一个视图控制器中,您传递变量:

    class ViewController: UIViewController {
        var myVariable: String!
        @IBAction func button1Action(sender: AnyObject) {
            myVariable = "Hello"
        }
        @IBAction func button2Action(sender: AnyObject) {
            myVariable = "Hola"
        }
        override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
            if segue == "MySegue" {
                let secondViewController = segue.destinationViewController as! ViewController
                secondViewController.myVariable = myVariable
            }
        }
    }
    

    在你的第二个视图控制器中,你可以对你的变量做任何你想做的事情:

    class SecondViewController: UIViewController {
        var myVariable: String!
    
        override func viewDidLoad() {
            title = myVariable
        }
    }
    

    【讨论】:

    • 谢谢先生!我现在遇到了如何组织数据的问题......假设我有 5 个按钮,每个按钮将发送 10 个不同的变量来相应地填充子序列 VC。我应该按照您的描述继续,在按下按钮时创建和设置每个变量吗?或者创建一个单独的文件/类来保存要调用的变量是否有意义。
    • 理想情况下,我希望能够尽快从数据库中添加这些变量,所以我想知道是否有更传统的组织可能遵循 MVC 协议
    • 啊..下面好像有人已经回答了我的问题,谢谢!
    【解决方案2】:

    您可以创建一个NSObject 子类(例如MyAtmospherologyObject)并将所有需要的属性放入其中以存储您可能需要的所有 9 个类别的所有信息。

    然后给它一个type属性并使用enum作为唯一的segue来确定它得到了什么以及它应该如何处理其余的数据。

    在此之后,您只需要发送一个对象,即MyAtmospherologyObject。这可能很有用,因为您可以在初始化对象后将其作为一个整体传递到任何地方,并从那里重用它。

    例如Objective-C(我知道它不是 Swift,但你明白了。)

    MyAtmospherologyObject.h

    //
    //  MyAtmospherologyObject.h
    //
    
    @import Foundation;
    
    typedef NS_ENUM(NSUInteger, MyAtmospherologyType) {
        MyAtmospherologyGeothermalType   = 0,
        MyAtmospherologyHydroelectricType
    };
    
    @interface MyAtmospherologyObject : NSObject
    
    @property (nonatomic)           MyAtmospherologyType type;
    @property (nonatomic, strong)   NSString *mySting;
    
    - (MyAtmospherologyType)type;
    
    @end
    

    MyAtmospherologyObject.m

    //
    //  MyAtmospherologyObject.m
    //
    
    #import "MyAtmospherologyObject.h"
    
    @implementation MyAtmospherologyObject
    
    - (instancetype)initWithType:(MyAtmospherologyType)aType
    {
        self = [super init];
        if (self) {
            _type = aType;
        }
        return self;
    }
    
    #pragma mark - NSKeyedArchiver
    
    - (id)initWithCoder:(NSCoder *)decoder
    {
        if (self = [super init]) {
            _type       = [decoder decodeIntegerForKey:@"type"];
            _mySting    = [decoder decodeObjectForKey:@"mySting"];
        }
        return self;
    }
    
    - (void)encodeWithCoder:(NSCoder *)encoder
    {
        [encoder encodeInteger:_type    forKey:@"type"];
        [encoder encodeObject:_mySting  forKey:@"mySting"];
    }
    
    #pragma mark - Methods
    
    - (MyAtmospherologyObject)type
    {
        return _type;
    }
    
    @end
    

    MyAtmospherologyViewController.m

    // ...
    
    #import "MyAtmospherologyObject.h"
    
    @implementation MyAtmospherologyViewController
    
    // ...
    
    - (IBAction)buttonAction:(id)sender
    {
        MTKGSJournalQuestionnaireObject *object = [[MTKGSJournalQuestionnaireObject alloc] initWithType:MyAtmospherologyGeothermalType];
        object.myString = @"aString";
        [self performSegueWithIdentifier:@"MySegueIdentifier"
                                  sender:object];
    }
    
    #pragma mark - UIStoryboardSegue
    
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        MyAtmospherologyObject *object = (MyAtmospherologyObject *)sender;
        MyAtmospherologySegueViewController *vc = (MyAtmospherologySegueViewController *)segue.destinationViewController;
    
        switch (object.type) {
            case MyAtmospherologyGeothermalType:
                vc.navigationItem.title = object.myString;
                break;
            case MyAtmospherologyHydroelectricType:
                vc.navigationItem.title = object.myString;
                break;
            default:
                break;
        }
    }
    
    // ...
    
    @end
    

    【讨论】:

    • 在您的 viewcontroller.m 类中,是否有必要使用 switch-case 语句?似乎在任何一种情况下您都在做同样的事情,所以我想知道只是将其设置为:vc.navigation.title = object.myString; //enough?
    • 这只是一个例子,以防您可能需要为不同的类型做不同的事情。如果您不在乎,那么可以肯定的是,没有开关就可以了。毕竟是同一个对象。
    • 谢谢,很有意义!我还想知道另一个问题,在您的 IBAction buttonAction 中,您调用 performSegueWithIdentifier 发送对象的位置,但是当我们仅通过 performSegueWithIdentifier 发送对象时,您似乎使用了来自 prepareForSegue 的发件人跨度>
    • 我应该在我的 IBAction 中调用 prepareForSegue 吗?如果是这样,我将为 segue 参数输入什么?
    • 来自 Apple -" prepareForSegue:sender:: 通知视图控制器即将执行转场。" 因此,任何将启动转场操作的操作都会导致调用这个代表。我使用了performSegueWithIdentifier:sender:,因为你可能有多个连接到这个VC,所以你可以通过它的标识符调用特定的一个(我相信这更容易)。当然,你可以随心所欲地使用任何你想要的东西。
    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    • 2010-09-07
    相关资源
    最近更新 更多