Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何将数据从子视图控制器传递到父视图控制器?迅速地_Ios_Swift_Xcode_Childviewcontroller_Childviews - Fatal编程技术网

Ios 如何将数据从子视图控制器传递到父视图控制器?迅速地

Ios 如何将数据从子视图控制器传递到父视图控制器?迅速地,ios,swift,xcode,childviewcontroller,childviews,Ios,Swift,Xcode,Childviewcontroller,Childviews,我创建了一个活动,当其中一个文本字段单击时,它将弹出一个子项(警报对话框),其中包含产品列表,但当我单击列表中的一个项目时,一旦警报解除,我就无法在文本字段中显示它 这是父视图 import Foundation import UIKit class ViewAward: UIViewController{ @IBOutlet var tfMCN: UITextField! @IBOutlet var tfAmount: UITextField! @IBOutlet var tfProduc

我创建了一个活动,当其中一个文本字段单击时,它将弹出一个子项(警报对话框),其中包含产品列表,但当我单击列表中的一个项目时,一旦警报解除,我就无法在文本字段中显示它

这是父视图

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)

}
}
当用户点击其中一个项目时

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

}

}

有几种方法可以实现回调功能来传递数据

  • 代表
  • 使用块回调
  • 发布通知

但我建议使用委托,这是最好的方式,后通知也是一种方式,但我不想选择。

您可以使用协议/委托

这里有一个非常简单的解释,没有bs:

或者在您的情况下,您也可以使用NSNotificationCenter

您可以这样做:

“发送者”视图控制器就可以了

let nc = NSNotificationCenter.defaultCenter()
nc.postNotificationName("printValue", object: nil, userInfo: ["value" : "Pass Me this string"])
然后,接收器视图控制器可以侦听通知

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)
}
let nc=NSNotificationCenter.defaultCenter()
nc.addObserver(self,选择器:#选择器(printValue),名称:“printValue”,对象:nil)
func printValue(通知:NSNotification){
让userInfo:Dictionary=notification.userInfo作为!Dictionary
让item=userInfo[“value”]!作为字符串
打印(项目、自身)
}

为此,我通常使用闭包。比委托更简单、更不冗长:

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

}
class MainViewController:UIViewController{
func showChildViewController(){
guard let vc=storyboard?。将EVIEWControllerWithiIdentifier(“ChildViewController”)实例化为?ChildViewController else{
返回
}
vc.didSelectItem={[weak self](项)在中
如果让vc=self{
//用这个东西做点什么。
}
}
presentViewController(vc,动画:true,完成:nil)
}
}
类ChildViewController:UIViewController{
var didSelectItem:((项目:项目)->无效)?
@iAction func按钮按下(){
didSelectItem?(项目:)
}
}
  • 我的第一个偏好必须是快速完美的自定义委托。(如果您可以使用闭包作为回调,那么这也是一个不错的选择。选择“委托”可以稍微解释一下代码的用法。)

  • 请尽可能避免使用NSNotificationCenter,因为使用它时需要处理的事情太多了,而且它比代理稍慢一点。你也可能很容易陷入错误

  • 这是我的代码

    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.
        }
    
    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)")
            }
        }
    
    }
    
    2。此处为父视图控制器代码。

       //  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.
        }
    
    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)")
            }
        }
    
    }
    
    希望这有帮助。抱歉出错。

    在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()
      }
    }
    
    在父视图中调用子视图时共享实例

    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)
     }
    }
    
    现在在删除子视图之后
    访问结果变量并享受

    你能添加你的代码和你显示的警报类型吗?试着用一些你已经实现的代码更新你的问题,这会让我们正确地了解你正在做什么。我已经用最简单的方式更新了问题:当你要展示儿童控制器时,传递对
    self
    的引用或作为回调的闭包。vadian我使用了自呈现孩子,但当孩子被解职时,我无法更新textfield的值。你能帮我处理代码吗?我已经分配了一个全局变量,但它会在重新加载视图时更新textfield值,而不是在解除子视图时更新,但我的问题是,我没有使用segue加载子视图,并且在该子视图中,当我单击某个项时,会获取所选项并解除子视图,并将其删除在文本字段中显示抓取的数据对于相关视图控制器来说,通知是最糟糕和最昂贵的方式。协议/委托更好(闭包作为回调是最先进的)。@vadian然后给我们您的解决方案:|我用它来显示子'code'func productTapped(textfield:UITextField){//tfProduct.endEditing(true)tfProduct.resignFirstResponder()让poovervc=UIStoryboard(名称:“Main”,bundle:nil)。实例化ViewControllerWithiIdentifier(“sbPopUpID”)为!ViewPopUpProduct self.addChildViewController(popOverVC)popOverVC.view.frame=self.view.frame-self.view.addSubview(popOverVC.view)popOverVC.didMoveToParentViewController(self)}“代码”@JosephVincentMagtalas我给了你一个实现这一目标的总体思路。请根据您的需要修改我的答案。商品来自哪里?在'var didSelectItem:((item:item)->Void)`我是开发应用程序的新手thanks@JosephVincentMagtalas检查按下的
    按钮
    方法。在这里,您使用适当的参数调用闭包。我使用了相同的方法,但是当从childViewController调用时,customDelegate返回NIL。有什么我遗漏的吗?@Arjun你确定你传递了正确的值吗?您是否已使代表符合要求?如果你认为你的观点是正确的,那么你可以分享你到目前为止所做的代码,这样我就可以研究它了。谢谢