web-dev-qa-db-ja.com

PrepareForSegueを渡す方法:オブジェクト

私は(rightCalloutAccessoryボタンを使って)mapviewにたくさんのアノテーションを持っています。ボタンはこのmapviewからtableviewへのセグエスを実行します。どのコールアウトボタンがクリックされたかに応じてtableviewに異なるオブジェクト(データを保持する)を渡したいです。

例えば:(完全に構成されている)

  • annotation1(Austin) - >データobj 1を渡す(Austinに関連)
  • annotation2(Dallas) - >データobj 2を渡す(Dallasに関連)
  • annotation3(Houston) - > obj 3などのデータを渡す...(アイデアが得られます)

どの吹き出しボタンがクリックされたかを検出できます。

prepareForSegue:を使用して、データobjを宛先のViewControllerに渡します。この呼び出しで、必要なデータオブジェクトに対して余分な引数を取ることはできません。同じ効果を得るための優れた方法は何ですか(動的データオブジェクト)。

どんなチップでも評価されるでしょう。

353
chizzle

prepareForSegue:メソッドでターゲットのView Controllerへの参照を取得し、必要なオブジェクトをそこに渡します。これは一例です...

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Make sure your segue name in storyboard is the same as this line
    if ([[segue identifier] isEqualToString:@"YOUR_SEGUE_NAME_HERE"])
    {
        // Get reference to the destination view controller
        YourViewController *vc = [segue destinationViewController];

        // Pass any objects to the view controller here, like...
        [vc setMyObjectHere:object];
    }
}

改訂:performSegueWithIdentifier:sender:メソッドを使用して、選択またはボタンを押すことに基づいて新しいビューへのトランジションをアクティブにすることもできます。

たとえば、View Controllerが2つあるとします。最初のボタンは3つのボタンを含み、2番目のボタンはトランジションの前にどのボタンが押されたかを知る必要があります。このようにperformSegueWithIdentifier:メソッドを使用するコードでボタンをIBActionに配線することができます。

// When any of my buttons are pressed, Push the next view
- (IBAction)buttonPressed:(id)sender
{
    [self performSegueWithIdentifier:@"MySegue" sender:sender];
}

// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"MySegue"]) {

        // Get destination view
        SecondView *vc = [segue destinationViewController];

        // Get button tag number (or do whatever you need to do here, based on your object
        NSInteger tagIndex = [(UIButton *)sender tag];

        // Pass the information to your destination view
        [vc setSelectedButton:tagIndex];
    }
}

編集:私が最初に添付したデモアプリケーションは現在6歳ですので、混乱を避けるために削除しました。

671
Simon

場合によっては、2つのView Controller間にコンパイル時の依存関係を作成しないようにすると便利です。移動先のView Controllerの種類を気にせずにそれを実行する方法は次のとおりです。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.destinationViewController respondsToSelector:@selector(setMyData:)]) {
        [segue.destinationViewController performSelector:@selector(setMyData:) 
                                              withObject:myData];
    } 
}

送信先のView Controllerがパブリックプロパティを宣言している限り、以下のようになります。

@property (nonatomic, strong) MyData *myData;

上記のように、前のView Controllerでこのプロパティを設定できます。

82
Macondo2Seattle

Swift 4.2では、次のようにします。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let yourVC = segue.destination as? YourViewController {
        yourVC.yourData = self.someData
    }
}
20
Remy Cilia

私はこのように送信者クラスを持っています

@class MyEntry;

@interface MySenderEntry : NSObject
@property (strong, nonatomic) MyEntry *entry;
@end

@implementation MySenderEntry
@end

私はオブジェクトをprepareForSeque:sender:に渡すためにこのsender classを使います

-(void)didSelectItemAtIndexPath:(NSIndexPath*)indexPath
{
    MySenderEntry *sender = [MySenderEntry new];
    sender.entry = [_entries objectAtIndex:indexPath.row];
    [self performSegueWithIdentifier:SEGUE_IDENTIFIER_SHOW_ENTRY sender:sender];
}

-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_SHOW_ENTRY]) {
        NSAssert([sender isKindOfClass:[MySenderEntry class]], @"MySenderEntry");
        MySenderEntry *senderEntry = (MySenderEntry*)sender;
        MyEntry *entry = senderEntry.entry;
        NSParameterAssert(entry);

        [segue destinationViewController].delegate = self;
        [segue destinationViewController].entry = entry;
        return;
    }

    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_HISTORY]) {
        // ...
        return;
    }

    if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_FAVORITE]) {
        // ...
        return;
    }
}
16
neoneye

あるView Controllerから別のView Controllerにデータを渡す方法を学ぼうとしていたときに、この質問に出会いました。私は私が学ぶのを助けるために何か視覚的なものが必要なので、この答えはすでにここにいる他の人への補足です。それは元の質問よりももう少し一般的ですが、動作するように調整することができます。

この基本的な例は次のように機能します。

enter image description here

これは、First View ControllerのテキストフィールドからSecond View Controllerのラベルに文字列を渡すことです。

ファーストビューコントローラ

import UIKit

class FirstViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    // This function is called before the segue
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        // get a reference to the second view controller
        let secondViewController = segue.destinationViewController as! SecondViewController

        // set a variable in the second view controller with the String to pass
        secondViewController.receivedString = textField.text!
    }

}

セカンドビューコントローラー

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    // This variable will hold the data being passed from the First View Controller
    var receivedString = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        // Used the text from the First View Controller to set the label
        label.text = receivedString
    }

}

忘れないで

  • でセグエを作る control ボタンをクリックしてSecond View Controllerにドラッグします。
  • UITextFieldUILabelのアウトレットを接続します。
  • 1番目と2番目のView ControllerをIBの適切なSwiftファイルに設定します。

ソース

どのようにsegue(Swift)を通してデータを送信する (YouTubeチュートリアル)

また見なさい

View Controllers:データの受け渡しとデータの受け渡し (より完全な答え)

14
Suragch

Swift これを使う、

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    var segueID = segue.identifier

    if(segueID! == "yourSegueName"){

        var yourVC:YourViewController = segue.destinationViewController as YourViewController

        yourVC.objectOnYourVC = setObjectValueHere!

    }
}
5
Zaid Pathan

この操作を簡単にするために、UIViewControllerにカテゴリを持つライブラリを実装しました。基本的には、セグエを実行しているUIアイテムに関連付けられたNSDictionaryに、渡したいパラメータを設定します。これは手動のセグエでも動作します。

たとえば、

[self performSegueWithIdentifier:@"yourIdentifier" parameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];

手動セグエ用、またはセグエ付きのボタンを作成して使用する

[button setSegueParameters:@{@"customParam1":customValue1, @"customValue2":customValue2}];

変換先View Controllerがキーに対応したキー値コーディングに準拠していない場合は、何も起こりません。これはKey-Valueでも機能します(くつろいだセグエに役立ちます)。ここからチェックしてください https://github.com/stefanomondino/SMQuickSegue

4
Stefano Mondino

私の解決策は似ています。

// In destination class: 
var AddressString:String = String()

// In segue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
   if (segue.identifier == "seguetobiddetailpagefromleadbidder")
    {
        let secondViewController = segue.destinationViewController as! BidDetailPage
        secondViewController.AddressString = pr.address as String
    }
}
2
A.G

この機能を使うだけです。

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let index = CategorytableView.indexPathForSelectedRow
    let indexNumber = index?.row
    let VC = segue.destination as! DestinationViewController
   VC.value = self.data

}
1
Parth Barot

私は、この機能を使用して、セグエの呼び出しとデータ通信を同じ機能内で維持できるようにしました。

private var segueCompletion : ((UIStoryboardSegue, Any?) -> Void)?

func performSegue(withIdentifier identifier: String, sender: Any?, completion: @escaping (UIStoryboardSegue, Any?) -> Void) {
    self.segueCompletion = completion;
    self.performSegue(withIdentifier: identifier, sender: sender);
    self.segueCompletion = nil
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    self.segueCompletion?(segue, sender)
}

ユースケースは次のようになります。

func showData(id : Int){
    someService.loadSomeData(id: id) {
        data in
        self.performSegue(withIdentifier: "showData", sender: self) {
            storyboard, sender in
            let dataView = storyboard.destination as! DataView
            dataView.data = data
        }
    }
}

これは私にはうまくいくようですが、perform関数とprepare関数が常に同じスレッドで実行されるとは限りません。

0
dannrob