Zoeken…


Segmenten gebruiken (gegevens doorsturen)

Als u gegevens van de huidige viewcontroller wilt doorgeven aan de volgende nieuwe viewcontroller (geen vorige viewcontroller) met behulp van segmenten, maakt u eerst een segue met een ID in het relevante storyboard. Vervang de methode prepareForSegue uw huidige weergavecontroller. Controleer in de methode het segment dat u zojuist hebt gemaakt met de id. Cast de doelweergavecontroller en geef er gegevens aan door eigenschappen in te stellen op de neergeslagen weergavecontroller.

Een ID instellen voor een segment:

Attributeninspecteur voor een segment

Segmenten kunnen programmatisch worden uitgevoerd of met behulp van knopactie-gebeurtenis ingesteld in het storyboard door Ctrl + slepen naar bestemming weergavecontroller. U kunt indien nodig programmatisch een segue oproepen met behulp van een segue-ID in de viewcontroller:

Doelstelling C

- (void)showDetail {
    [self performSegueWithIdentifier:@"showDetailingSegue" sender:self];        
}

Snel

func showDetail() {
    self.performSegue(withIdentifier: "showDetailingSegue", sender: self)
}

U kunt segue-payload configureren in de vervangende versie van de methode prepareForSegue . U kunt vereiste eigenschappen instellen voordat de bestemmingweergavecontroller wordt geladen.

Doelstelling C

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue.identifier isEqualToString:@"showDetailingSegue"]){
        DetailViewController *controller = (DetailViewController *)segue.destinationViewController;
        controller.isDetailingEnabled = YES;
    }
}

Snel

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "showDetailingSegue" {
        let controller = segue.destinationViewController as! DetailViewController
        controller.isDetailingEnabled = true
    }    
}

DetailViewController is de naam van de tweede isDetailingEnabled en isDetailingEnabled is een openbare variabele in die isDetailingEnabled .

Om dit patroon uit te breiden, kunt u een openbare methode op DetailViewController als een pseudo-initialisatie, om eventuele vereiste variabelen te helpen initialiseren. Dit document DetailViewController variabelen die moeten worden ingesteld op DetailViewController zonder de DetailViewController te hoeven doorlezen. Het is ook een handige plek om standaardwaarden in te stellen.

Doelstelling C

- (void)initVC:(BOOL *)isDetailingEnabled {
    self.isDetailingEnabled = isDetailingEnabled
}

Snel

func initVC(isDetailingEnabled: Bool) {
    self.isDetailingEnabled = isDetailingEnabled
}

Het gedelegeerde patroon gebruiken (gegevens teruggeven)

Om gegevens van de huidige weergavecontroller terug te geven aan de vorige weergavecontroller, kunt u het deelnemerspatroon gebruiken.

voer hier de afbeeldingsbeschrijving in

In dit voorbeeld wordt ervan uitgegaan dat u een segment hebt gemaakt in de Interface Builder en dat u het showSecondViewController ID hebt ingesteld op showSecondViewController . De uitgangen en acties moeten ook worden aangesloten op de namen in de volgende code.

First View-controller

De code voor de First View Controller is

Snel

class FirstViewController: UIViewController, DataEnteredDelegate {

    @IBOutlet weak var label: UILabel!
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showSecondViewController", let secondViewController = segue.destinationViewController as? SecondViewController  {
            secondViewController.delegate = self
        }
    }

    // required method of our custom DataEnteredDelegate protocol
    func userDidEnterInformation(info: String) {
        label.text = info
        navigationController?.popViewControllerAnimated(true)
    }
}

Doelstelling C

@interface FirstViewController : UIViewController <DataEnteredDelegate>
@property (weak, nonatomic) IBOutlet UILabel *label;
@end

@implementation FirstViewController
- (void)viewDidLoad {
    [super viewDidLoad];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    SecondViewController *secondViewController = segue.destinationViewController;
    secondViewController.delegate = self;

}
-(void)userDidEnterInformation:(NSString *)info {
    _label.text = info
    [self.navigationController popViewControllerAnimated:YES];
}
@end

Let op het gebruik van ons aangepaste DataEnteredDelegate protocol.

Second View-controller en protocol

De code voor de Second View-controller is

Snel

// protocol used for sending data back
protocol DataEnteredDelegate: class {
    func userDidEnterInformation(info: String)
}

class SecondViewController: UIViewController {

    // making this a weak variable so that it won't create a strong reference cycle
    weak var delegate: DataEnteredDelegate?
    
    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(sender: AnyObject) {
        
        // call this method on whichever class implements our delegate protocol (the first view controller)
        delegate?.userDidEnterInformation(textField.text ?? "")
    }
}

Doelstelling C

@protocol DataEnteredDelegate <NSObject>
-(void)userDidEnterInformation:(NSString *)info;
@end

@interface SecondViewController : UIViewController 
@property (nonatomic) id <DataEnteredDelegate> delegate;
@property (weak, nonatomic) IBOutlet UITextField *textField;
@end

@implementation SecondViewController
- (void)viewDidLoad {
    [super viewDidLoad];
}

- (IBAction) sendTextBackButton:(id)sender{
    [_delegate userDidEnterInformation:textField.text];
}
@end

Merk op dat het protocol buiten de View Controller-klasse valt.

Gegevens achterwaarts doorgeven met behulp van afwikkelen om te segmenteren

In tegenstelling tot segue waarmee u gegevens kunt "doorsturen" van de huidige weergavecontroller naar de doelweergavecontroller:

(VC1) -> (VC2)

Met "afrollen" kunt u het tegenovergestelde doen, gegevens van de bestemming of huidige weergavecontroller doorgeven aan de bijbehorende weergavecontroller:

(VC1) <- (VC2)

OPMERKING : Let erop dat u met behulp van afwikkelen eerst de gegevens kunt doorgeven en dat daarna de huidige view controller (VC2) wordt toegewezen.

Hier is hoe het te doen:

Eerst moet u de volgende verklaring toevoegen aan de presenterende view controller (VC1), de view controller waaraan we de gegevens willen doorgeven:

@IBAction func unwindToPresentingViewController(segue:UIStoryboardSegue)

Het belangrijkste is om het voorvoegsel unwind , dit "informeert" Xcode dat dit een afwikkelingsmethode is die u de mogelijkheid geeft om het ook in een storyboard te gebruiken.

Daarna moet u de methode implementeren, deze ziet er bijna hetzelfde uit als een echt segment:

@IBAction func unwindToPresentingViewController(segue:UIStoryboardSegue)
{
    if segue.identifier == "YourCustomIdentifer"
    {
        if let VC2 = segue.sourceViewController as? VC2
        {
            //    Your custom code in here to access VC2 class member
        }

Nu hebt u 2 opties om de afwikkeloproepen aan te roepen:

  1. U kunt "harde code" aanroepen: self.performSegueWithIdentifier("YourCustomIdentifier", sender: self) die voor u zal performSegueWithIdentifier wanneer performSegueWithIdentifier .
  2. Je kunt de afwikkelmethode met behulp van het storyboard koppelen aan je "Exit" -object: ctrl + sleep de knop die je wilt gebruiken de afwikkelmethode aan het "Exit" -object:

voer hier de afbeeldingsbeschrijving in

Laat los en je hebt de optie om je aangepaste afwikkelmethode te kiezen:

voer hier de afbeeldingsbeschrijving in

Gegevens doorgeven met behulp van sluitingen (gegevens teruggeven)

In plaats van het deelnemerspatroon te gebruiken , dat de implementatie in verschillende delen van de UIViewController klasse splitst, kunt u zelfs closures gebruiken om gegevens heen en weer door te geven. Door aan te nemen dat u de UIStoryboardSegue , kunt u in de methode prepareForSegue de nieuwe controller eenvoudig in één stap instellen

final class DestinationViewController: UIViewController {
    var onCompletion: ((success: Bool) -> ())?

    @IBAction func someButtonTapped(sender: AnyObject?) {
        onCompletion?(success: true)
    }
}

final class MyViewController: UIViewController {
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    
        guard let destinationController = segue.destinationViewController as? DestinationViewController else { return }
    
        destinationController.onCompletion = { success in
            // this will be executed when `someButtonTapped(_:)` will be called
            print(success)
        }
    }
}

Dit is een voorbeeld van gebruik en het is beter om op Swift te gebruiken, de syntaxis van Objective-C block is niet zo eenvoudig om de code leesbaarder te maken

Terugbellen gebruiken (blokkeren) gegevens teruggeven

dit onderwerp is een klassiek probleem in de ontwikkeling van iOS en de oplossing is anders dan andere voorbeelden die al zijn getoond. Het passeren van gegevens met behulp van: In dit voorbeeld zal ik een andere dagelijkse gemeenschappelijk gebruik een tonen closure door aanpassing delegate pattern voorbeeld op deze pagina in callback closure !

één ding deze methode is superieur aan het delegate pattern is in plaats van de configuratiecode op twee verschillende plaatsen te splitsen (kijk naar het voorbeeld van de gedelegeerde op deze pagina, prepareForSegue , userDidEnterInformation ) in plaats van ze te verzamelen (alleen in prepareForSegue , ik zal het tonen)

Start vanuit Second View Controller

we moeten uitzoeken hoe we callback kunnen gebruiken, dan kunnen we het schrijven, dit is waarom we beginnen met de second view-controller, omdat het is waar we callback gebruiken: wanneer we de nieuwe tekstinvoer hebben, roepen we onze callback aan, met de parameter van callback als medium om gegevens terug te geven naar de eerste ViewController, merk op dat ik zei dat ik de parameter van de callback gebruikte, dit is heel belangrijk, beginners (zoals ik waren) zien dit altijd over het hoofd en weten niet waar ze moeten beginnen met het correct afsluiten van de callback

dus in dit geval weten we dat onze callback slechts één parameter gebruikt: tekst en het type is String , laten we het declareren en het eigenschap maken omdat we het moeten invullen vanaf onze first view-controller

Ik geef alleen commentaar op alle delegate en bewaar deze om te vergelijken

class SecondViewController: UIViewController {

    //weak var delegate: DataEnteredDelegate? = nil
    var callback: ((String?)->())?
    
    @IBOutlet weak var textField: UITextField!

    @IBAction func sendTextBackButton(sender: AnyObject) {
        
        //delegate?.userDidEnterInformation(textField.text!)
        callback?(input.text)
        
        self.navigationController?.popViewControllerAnimated(true)
    }
}

Voltooi de eerste-zichtcontroller

het enige dat u hoeft te doen, is het afsluiten van terugbelaanvragen, en we zijn klaar, sluiting zal het toekomstige werk voor ons doen, omdat we het al hebben ingesteld in de tweede weergave-controller

kijk hoe het onze code korter maakt in vergelijking met het delegate pattern

//no more DataEnteredDelegate
class FirstViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "showSecondViewController" {
            let secondViewController = segue.destinationViewController as! SecondViewController
            //secondViewController.delegate = self
            secondViewController.callback = { text in self.label.text = text }
        }
    }

    // required method of our custom DataEnteredDelegate protocol
    //func userDidEnterInformation(info: String) {
    //    label.text = info
    //}
}

en tot slot, misschien zal iemand van jullie in de war raken door te kijken dat we de gegevens (in dit geval afsluiting) slechts op één manier doorgeven, van first view controller naar tweede, niet rechtstreeks terugkomen van second view controller, hoe kunnen we beschouw het als een communicatiemiddel? misschien moet je het echt uitvoeren en het zelf bewijzen, alles wat ik zal zeggen is de parameter , het is de parameter van de callback-afsluiting die gegevens teruggeeft!

Door eigenschap toe te wijzen (gegevens doorgeven)

U kunt gegevens rechtstreeks doorgeven door de eigenschap van de volgende viewcontroller toe te wijzen voordat u erop drukt of presenteert.

class FirstViewController: UIViewController {

    func openSecondViewController() {

        // Here we initialize SecondViewController and set the id property to 492
        let secondViewController = SecondViewController()
        secondViewController.id = 492

        // Once it was assign we now push or present the view controller
        present(secondViewController, animated: true, completion: nil)
    }

}

class SecondViewController: UIViewController {
    
    var id: Int?

    override func viewDidLoad() {
        super.viewDidLoad()

        // Here we unwrapped the id and will get the data from the previous view controller.
        if let id = id {
            print("Id was set: \(id)")
        }
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow