xcode 如何将数据从子视图控制器传递给父视图控制器?迅速
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39285588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to pass data from child to parent view controller? in swift
提问by Joseph Vincent Magtalas
I created an activity where when one of the text fields clicked it will pop up a child(alert dialog) with list of product but when i click one item on the list I can't display it on the text filed once the alert dismissed.
我创建了一个活动,当单击其中一个文本字段时,它会弹出一个带有产品列表的子项(警报对话框),但是当我单击列表中的一项时,一旦警报解除,我就无法在提交的文本上显示它。
this is the parent view
这是父视图
import Foundation
import UIKit
class ViewAward: UIViewController{
@IBOutlet var tfMCN: UITextField!
@IBOutlet var tfAmount: UITextField!
@IBOutlet var tfProduct: UITextField!
@IBOutlet var tfTotal: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let rightAddBarButtonItem:UIBarButtonItem = UIBarButtonItem(title: "Send", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(ViewAward.searchTapped))
self.navigationItem.setRightBarButtonItems([rightAddBarButtonItem], animated: true)
let state = String(ViewPopUpProduct.Product.ProductDescription)
print("My view state:"+state)
self.tfProduct.text = state
tfProduct.addTarget(self, action: #selector(ViewAward.productTapped), forControlEvents: UIControlEvents.TouchDown)
}
func searchTapped(sender:UIButton) {
let alertController = UIAlertController(
title: "Award",
message:"Award successfully posted!",
preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
}
func productTapped(textfield: UITextField){
//tfProduct.endEditing(true)
tfProduct.resignFirstResponder()
let popOverVC = UIStoryboard(name:"Main",bundle:nil).instantiateViewControllerWithIdentifier("sbPopUpID") as! ViewPopUpProduct
self.addChildViewController(popOverVC)
popOverVC.view.frame = self.view.frame
self.view.addSubview(popOverVC.view)
popOverVC.didMoveToParentViewController(self)
}
}
and this when the user clicked on of the items
当用户点击项目时
import UIKit
class ViewPopUpProduct: UIViewController {
@IBOutlet var tableView: UITableView!
var productDescription = ["Product 1","Product 2","Product 3"]
var productID = ["prdct1","prdct2","prdct3"]
// Global Variables
struct Product {
static var ProductID = String()
static var ProductDescription = String()
}
override func viewDidLoad() {
super.viewDidLoad()
self.showAnimate()
self.view.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.4)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func cancelPopUp(sender: AnyObject) {
self.removeAnimate()
}
func showAnimate()
{
self.view.transform = CGAffineTransformMakeScale(1.3, 1.3)
self.view.alpha = 0.0;
UIView.animateWithDuration(0.25, animations: {
self.view.alpha = 1.0
self.view.transform = CGAffineTransformMakeScale(1.0, 1.0)
});
}
func removeAnimate()
{
UIView.animateWithDuration(0.25, animations: {
self.view.transform = CGAffineTransformMakeScale(1.3, 1.3)
self.view.alpha = 0.0;
}, completion:{(finished : Bool) in
if (finished)
{
self.view.removeFromSuperview()
}
});
}
//Mark - Table View
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.productID.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell",forIndexPath: indexPath) as! ProductViewCell
cell.productLabel.text = productDescription[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
Product.ProductID = String(productID[indexPath.row])
Product.ProductDescription = String(productDescription[indexPath.row])
self.removeAnimate()
}
}
采纳答案by Tommy
You can use protocols/delegate
您可以使用协议/委托
Here is a very very straightforward explanation, no bs: https://www.youtube.com/watch?v=guSYMPaXLaw
这是一个非常非常直接的解释,没有bs:https: //www.youtube.com/watch?v=guSYMPaXLaw
Or in your situation you can also use NSNotificationCenter
或者在你的情况下你也可以使用 NSNotificationCenter
You can do something like this:
你可以这样做:
The "sender" view controller would do
“发件人”视图控制器会做
let nc = NSNotificationCenter.defaultCenter()
nc.postNotificationName("printValue", object: nil, userInfo: ["value" : "Pass Me this string"])
The receiver view controller then can listen to the notification.
然后接收器视图控制器可以收听通知。
let nc = NSNotificationCenter.defaultCenter()
nc.addObserver(self, selector: #selector(printValue), name: "printValue", object: nil)
func printValue(notification:NSNotification) {
let userInfo:Dictionary<String,String> = notification.userInfo as! Dictionary<String,String>
let item = userInfo["value"]! as String
print(item,self)
}
回答by Andrey Gordeev
I usually use closures for this purpose. Much simpler and less verbose than delegates:
为此,我通常使用闭包。比委托更简单、更简洁:
class MainViewController: UIViewController {
func showChildViewController() {
guard let vc = storyboard?.instantiateViewControllerWithIdentifier("ChildViewController") as? ChildViewController else {
return
}
vc.didSelectItem = { [weak self](item) in
if let vc = self {
// Do something with the item.
}
}
presentViewController(vc, animated: true, completion: nil)
}
}
class ChildViewController: UIViewController {
var didSelectItem: ((item: Item) -> Void)?
@IBAction func buttonPressed() {
didSelectItem?(item: <#your item goes here#>)
}
}
回答by Sandy
There are few ways by which you can implement the callback functionality to pass data.
有几种方法可以实现回调功能来传递数据。
- Delegate
- Using Block CallBack
- Post Notification
- 代表
- 使用块回调
- 发布通知
But I would suggest to use delegate which is best way, Post Notification is also a way but I do not want to prefer.
但我建议使用委托,这是最好的方式,发布通知也是一种方式,但我不想更喜欢。
回答by onCompletion
My first preference must be Custom Delegate which is faster and perfect. (If you can use closures as callbacks then that can also be a good option. Choosing delegate to explain using your code a bit.)
Please avoid using NSNotificationCenter as much as you can because there are so many thing you have to deal with when using this and it is little slower than delegates. You may easily get into bugs with that too.
我的首选必须是自定义委托,它更快更完美。(如果您可以使用闭包作为回调,那么这也是一个不错的选择。选择委托来解释一下使用您的代码。)
请尽量避免使用 NSNotificationCenter,因为在使用它时有很多事情需要处理,而且它比委托慢一点。你也可能很容易陷入错误。
Now here is my code.
现在这是我的代码。
1. Child ViewController Setup.
1. 子视图控制器设置。
// TrendingProductPageViewController.swift
// buddyiOSApp
//
// Created by Tuhin Samui on 5/21/16.
// Copyright ? 2016 Buddy. All rights reserved.
//
import UIKit
protocol TrendingProductsCustomDelegate: class { //Setting up a Custom delegate for this class. I am using `class` here to make it weak.
func sendDataBackToHomePageViewController(categoryToRefresh: String?) //This function will send the data back to origin viewcontroller.
}
class TrendingProductPageViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, NetworkReachabilityDelegate {
@IBOutlet weak var productListTableView: UITableView! //Having a tableview outlet here from storyboard itself. BTW not going to explain with tableView delegate and datasource, Sorry..:(
weak var customDelegateForDataReturn: TrendingProductsCustomDelegate? //Please use weak reference for this to manage the memory issue.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let rowNumberFromTable: Int = indexPath.row //Getting the index of the selected cell.
let dataToSendBack = moreMenuTableData[rowNumberFromTable] as! String //This is an array which contains the data for the tableview. Getting the exact data which is selected on the table.
customDelegateForDataReturn?.sendDataBackToHomePageViewController?(dataToSendBack) //Now sending the selected data back to parent viewController using the custom delegate which I made before. presentingViewController?.dismissViewControllerAnimated(true, completion: nil) //Dismissing the viewController here.
}
2. Parent ViewController code here.
2. 父 ViewController 代码在这里。
class HomePageViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, TrendingProductsCustomDelegate, UINavigationControllerDelegate{ //Adding the protocol here as `TrendingProductsCustomDelegate`
@IBAction func topTrendingProductsBtnAction(sender: UIButton) { //Normal IBAction of UIButton as you are using.
let trendingProductsPageForAnimation = storyboard!.instantiateViewControllerWithIdentifier("showTrendingProductpage") as! TrendingProductPageViewController //You can understand this right. Same as yours.
trendingProductsPageForAnimation.customDelegateForDataReturn = self //Setting up the custom delegate for this class which I have written on the presenting class.
trendingProductsPageForAnimation.modalPresentationStyle = UIModalPresentationStyle.FullScreen
presentViewController(trendingProductsPageForAnimation, animated: true, completion: nil) //Same as yours.
}
func sendDataBackToHomePageViewController(categoryToRefresh: String?) { //Custom delegate function which was defined inside child class to get the data and do the other stuffs.
if categoryToRefresh != nil {
print("Got the data is \(categoryToRefresh)")
}
}
}
Hope this helped. Sorry for any mistake.
希望这有帮助。抱歉,有任何错误。
回答by AlbinMrngStar
In ChildVC(ViewPopUpProduct) add instance of ParentVC
在 ChildVC(ViewPopUpProduct) 中添加 ParentVC 的实例
class ViewPopUpProduct: UIViewController {
var parentVC = ViewAward? //ParentView
var someValueToSend : String?
.
.
.
fun sendData(){
// After fetching some value call this function from child
parentVC.result = someValueToSend
self.view.removeFromSuperview()
}
}
In Parent View While you invoke child(subview) share the instance
在父视图中调用子视图时共享实例
class ViewAward: UIViewController{
var result = String?//Variable to store result from child
func productTapped(textfield: UITextField){
//tfProduct.endEditing(true)
tfProduct.resignFirstResponder()
let popOverVC = UIStoryboard(name:"Main",bundle:nil).instantiateViewControllerWithIdentifier("sbPopUpID") as! ViewPopUpProduct
popOverVC.parentVC = self//Sharing Parent Views Instance
self.addChildViewController(popOverVC)
popOverVC.view.frame = self.view.frame
self.view.addSubview(popOverVC.view)
popOverVC.didMoveToParentViewController(self)
}
}
now after removing the child view Access the Result variable and enjoy!
现在删除子视图后访问结果变量并享受!