ReadyForSegue Nasıl Geçirilir: Bir Nesne


358

Bir harita görünümünde çok sayıda ek açıklama var ( rightCalloutAccessorydüğmeli). Düğmesi bu bir segue yapacak mapviewbir etmek tableview. tableviewHangi belirtme çizgisi düğmesine tıklandığında bağlı olarak farklı bir nesne (veri tutan) geçmek istiyorum .

Örneğin: (tamamen yapılmış)

  • ek açıklama1 (Austin) -> veri aktarımı obj 1 (Austin ile ilgili)
  • ek açıklama2 (Dallas) -> veri aktarımı obj 2 (Dallas ile ilgili)
  • annotation3 (Houston) -> veri obj 3'ü geçirin ve böyle devam edin ...

Hangi ek bilgi düğmesinin tıklandığını algılayabiliyorum.

Ben prepareForSegueveri obj hedefe geçmek için kullanıyorum ViewController. Bu çağrıyı istediğim veri objesi için fazladan bir tartışma yapamadığımdan, aynı etkiyi (dinamik veri objesi) elde etmenin zarif yolları nelerdir?

Herhangi bir ipucu takdir edilecektir.


Yanıtlar:


674

prepareForSegue:Yöntemde hedef görünüm denetleyicisine bir referans alın ve ihtiyacınız olan nesneleri oraya iletin. İşte bir örnek ...

- (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];
    }
}

REVİZYON: performSegueWithIdentifier:sender:Bir seçime veya düğmeye basarak yeni bir görünüme geçişi etkinleştirmek için yöntemi de kullanabilirsiniz .

Örneğin, iki görünüm denetleyicim olduğunu düşünün. Birincisi üç düğme içerir ve ikincisi geçişten önce bu düğmelerden hangisine basıldığını bilmelidir. Düğmeleri , böyle bir yöntem IBActionkullanan kodunuzdaki bir kabloya bağlayabilirsiniz performSegueWithIdentifier:...

// 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];
    }
}

EDIT: Başlangıçta eklediğim demo uygulaması şimdi altı yaşında, bu yüzden herhangi bir karışıklığı önlemek için kaldırdım.


Teşekkür ederim ama bunu [vc setMyObjectHere:object];dinamik olarak ayarlamak istiyorum . yani button1 için obj1, button2 için obj2 Sorun bir argümanı iletemem. Bunun bir yolu var mı?
chizzle

2
Yazımı, bahsettiğim şeyin indirilebilir bir örneğiyle güncelledim.
Simon

işe yaradı! Çok teşekkürler. Yan not olarak preparForSegue: UIButton'un ana sınıfı olan bir UIControl argümanı vardır (etiketi alabilir): D
chizzle

Bir storyboard segue olmadan bir navigasyon kontrol cihazına bastığınızda bile preparForSegue çağrılıyor mu?
zakdances

Bu şimdiye kadar gördüğüm en kapsamlı cevaplardan biri. İyi kod örnekleri, sorunu çözer, indirilebilir örnek sunar ... vay. Etkilendim!
lewiguez

82

Bazen iki görünüm denetleyicisi arasında derleme zamanı bağımlılığı oluşturmaktan kaçınmak yararlı olabilir. Hedef görünümü denetleyicisinin türünü umursmadan nasıl yapabileceğiniz aşağıda açıklanmıştır:

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

Hedef görünüm denetleyiciniz herkese açık bir mülk beyan ettiği sürece, örneğin:

@property (nonatomic, strong) MyData *myData;

bu özelliği yukarıda açıkladığım gibi önceki görünüm denetleyicisinde ayarlayabilirsiniz.


12
Bu gerçekten bir görüş meselesi. Söylediklerinizi takdir etsem de, doğru şartlarda önemli olabilmesine rağmen, görünüm denetleyicilerini 'sıkı bir şekilde' kontrol etmek istemediğim (henüz) bir durumum olmadı.
Simon

2
@Simon: evet, sadece sizin için en uygun yaklaşımı seçersiniz. Şu anda üzerinde çalıştığım uygulamada, örneğin, aynı veri nesnesine ihtiyaç duyan görünüm denetleyicileri eklemeye devam ettiğim için yaklaşımım çok mantıklı. Onları sadece bir segue ile bağlayabilmek ve doğru verileri elde edeceklerini bilmek süper uygun.
Macondo2Seattle

10
Bu bir görüş meselesi değil, sadece yanlış :) "Kabul edilen cevap bunu yapmanın en iyi yolu değildir" ifadesi yanlıştır. "Belirli durumlarda, bunu yapmanız gerekir ..."
yazmalıdır

2
Simon'un yöntemini tercih ederim. Derleme zamanında hataları bana söyleyeceği gibi. Örneğin, hedef görünüm denetleyicisindeki myData bildirimini kaçırırsam, hemen bileceğim. Ancak senaryonuz için yaklaşımınız iyi görünüyor!
Abdurrahman Mubeen Ali

14
Hedef görünüm denetleyicisine sahip olmanız gerektiğinden bu yaklaşım kesinlikle bir bağımlılık oluşturur setMyData:. Bu bir bağımlılık. Derleme hatasını önlemek için bir seçici kullanmanız , bir yarar değil, yaklaşımınızın bir zayıflığı olarak ele alınmalıdır . Kaç geliştiricinin derleme zaman hatalarını çalışma zamanı hatalarına tercih etmesi gerektiği kavramını kaybetmesi bana şaşırtıcı geliyor.
Nate

21

Swift 4.2'de böyle bir şey yapardım:

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

`` Super.prepare (için: segue, gönderen: gönderen) '' çağırmanız gerekiyor mu?
Andrew K

16

Bir gönderen sınıfım var , böyle

@class MyEntry;

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

@implementation MySenderEntry
@end

Bu gönderen sınıfını nesneleri iletmek için kullanıyorumprepareForSeque:sender:

-(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;
    }
}

Biz edilir kullanılarak prepareForSegue ya da biz edilir uygulayan onu ve varsayım biz yani prepareForSegue kendisini çağrılan olduğu yok gibi bir şey yapmak gerekir[self prepareForSegue]
Bal

15

Bir soru denetleyicisinden diğerine veri aktarmayı öğrenmeye çalışırken bu soruya rastladım. Yine de öğrenmeme yardımcı olacak görsel bir şeye ihtiyacım var, bu yüzden bu cevap zaten burada bulunan diğerlerine bir ektir. Orijinal sorudan biraz daha geneldir, ancak işe uyarlanabilir.

Bu temel örnek şu şekilde çalışır:

resim açıklamasını buraya girin

Fikir, First View Controller'daki metin alanından Second View Controller'daki etikete bir dize geçirmektir.

İlk Görüş Kontrolörü

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!
    }

}

İkinci Görünüm Kontrol Cihazı

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
    }

}

Hatırla

  • controlDüğmeyi tıklatıp İkinci Görünüm Denetleyicisine sürükleyerek segue yapın .
  • İçin çıkışları bağlayın UITextFieldve UILabel.
  • Birinci ve ikinci Görünüm Denetleyicilerini IB'deki uygun Swift dosyalarına ayarlayın.

Kaynak

Segue yoluyla veri gönderme (hızlı) (YouTube eğitimi)

Ayrıca bakınız

Denetleyicileri Görüntüle: Verileri iletme ve verileri geri iletme (daha eksiksiz yanıt)


5

For Swift bunu kullanın,

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

    if(segueID! == "yourSegueName"){

        var yourVC:YourViewController = segue.destinationViewController as YourViewController

        yourVC.objectOnYourVC = setObjectValueHere!

    }
}

4

Bu işlemi basitleştiren UIViewController kategorisine sahip bir kütüphane uyguladım. Temel olarak, segue gerçekleştiren UI öğesiyle ilişkili bir NSDictionary içinde iletmek istediğiniz parametreleri ayarlarsınız. Manuel segues ile de çalışır.

Örneğin,

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

manuel segue için veya segue ile düğme oluşturma ve kullanma

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

Hedef görüntüleme denetleyicisi bir anahtar için anahtar / değer kodlaması uyumlu değilse, hiçbir şey olmaz. Anahtar / değer çiftleriyle de çalışır (gevşeme segueleri için yararlıdır). Buradan kontrol edin https://github.com/stefanomondino/SMQuickSegue


2

Benim çözümüm benzer.

// 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
    }
}

1

Sadece bu işlevi kullanın.

 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

}

0

Segue ve veri iletişiminin çağrılmasını aynı işlev içinde tutabilmek için bu çözümü kullandım:

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)
}

Bir kullanım örneği şöyle olacaktır:

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
        }
    }
}

Bu benim için çalışıyor gibi görünüyor, ancak, gerçekleştirmek ve hazırlamak işlevlerinin her zaman aynı iş parçacığında yürütüldüğünden% 100 emin değilim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.