在视图控制器之间有很多segues可以吗?

Posted

技术标签:

【中文标题】在视图控制器之间有很多segues可以吗?【英文标题】:Is it okay to have a lot of segues between view controllers? 【发布时间】: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
    

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

【问题讨论】:

【参考方案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,所以你可以通过它的标识符调用特定的一个(我相信这更容易)。当然,你可以随心所欲地使用任何你想要的东西。

以上是关于在视图控制器之间有很多segues可以吗?的主要内容,如果未能解决你的问题,请参考以下文章

iOS希望在按下按钮时延迟视图控制器之间的segue

我可以将 segue 与视图控制器的指定初始化程序一起使用吗?

我可以通过 Segues 在视觉上完全“绕过”视图控制器吗?

UITabBarController 可以是 segue.destinationViewController 吗?

通过 segue 在视图控制器之间传递数据

两个视图控制器之间的 Segue