iOS
Gegevens doorgeven tussen View Controllers
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:
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.
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:
- U kunt "harde code" aanroepen:
self.performSegueWithIdentifier("YourCustomIdentifier", sender: self)
die voor u zalperformSegueWithIdentifier
wanneerperformSegueWithIdentifier
. - 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:
Laat los en je hebt de optie om je aangepaste afwikkelmethode te kiezen:
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)")
}
}
}