【问题标题】:Calling child view controller using segmented control action?使用分段控制动作调用子视图控制器?
【发布时间】:2017-08-18 09:58:02
【问题描述】:

我的父视图控制器中有两个子视图控制器,我想在分段控件中的值更改时调用它们,并希望通过子视图控制器设置父 imageView 的值。

protocol UserEdittedPhoto {
    func UserIsDone(image:UIImage)
}

class ControllerFinal:UIViewController, UserEdittedPhoto{

    func UserIsDone(imageEditted: UIImage){
        self.usedImage=imageEditted
        self.imageView.image=self.usedImage
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func segmentAction(sender:UISegmentedControl){

        if (segmentedControl.selectedSegmentIndex==0){

            performSegueWithIdentifier("EditIAm", sender: nil)
        }

        else if (segmentedControl.selectedSegmentIndex==1){

            performSegueWithIdentifier("EditIAm", sender: nil)
        }
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == "EditIAm"{

            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let controller = storyboard.instantiateViewControllerWithIdentifier("ControllerEdit")
            self.presentViewController(controller, animated: true, completion: nil)

            let nextView = segue.destinationViewController as! ControllerEdit
            nextView.originalImage=self.imageView.image!
            nextView.delegate=self
        }

        else if segue.identifier == "FilterIAm"{

            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let controller = storyboard.instantiateViewControllerWithIdentifier("ControllerFilters")
            self.presentViewController(controller, animated: true, completion: nil)

            let nextView = segue.destinationViewController as! ControllerFilters
            nextView.toBeFilter=self.imageView.image!
        }
    }

    class ControllerEdit:UIViewController{
        var delegate: UserEdittedPhoto? = nil
        if (delegate != nil){
        self.originalImage = UIImage(CIImage: CIImage(image: self.originalImage)!.exposureAdjustFilter(sliderValue.value)!)
        self.delegate!.UserIsDone(self.originalImage)
        print("I am Called!")
        }
    }

    class ControllerFilters:UIViewController{
        override func viewDidLoad() {
            print("SAHASHhqdwiuhiuhsaiuhsaiudhiuash")
            controllerFinal?.imageView.image=toBeFilter
            print("SAHASHhqdwiuhiuhsaiuhsaiudhiuash")
            super.viewDidLoad()
        }
}

【问题讨论】:

  • 请检查这个。 @反斜杠-f
  • 你遇到了什么问题?
  • 我在展示分段控制动作的子视图控制器时遇到了问题。 @ParthoBiswas

标签: ios swift uisegmentedcontrol uicontainerview childviewcontroller


【解决方案1】:

更新

为了在下面的 cmets 中反映我们的讨论,我认为您并不真的需要 ContainersView Controllers 来管理您的自定义控件(编辑/过滤器)。太矫枉过正了。

相反,我认为您应该创建custom Views,然后将它们添加到您的主Storyboard

然后,当用户点击Segmented Control 并将值传递给他们时,您可以简单地隐藏/显示您的自定义视图,例如:

CustomEditView.valueY = newValueY
CustomFiltersView.valueX = newValueX

关于:

我需要通过segmentedControl动作强制调用它,这样 我在 childView 中的值被更新

然后您需要将目标View Controllers 映射到局部变量,并在用户按下段时使用它们来更新目标View Controller variables

我已经更新了答案中的代码和“演示”以反映这一点。
(请注意,我只是在 labels 中添加随机的 Strings 以表明观点。)

现在是完整的答案...


在您描述的基于containersin your other question 设置中,View Controllers 已经存在于Storyboard 中。您绝对不需要再次展示它们(您可以删除 performSegueWithIdentifier 调用)。

如果我理解正确,您只是想根据用户通过Segmented Control 选择的内容向用户显示不同的“控制器”。

有一些方法可以做到这一点,但最简单的方法是隐藏并显示 ControllerEdit / ControllerFilters View Controllerscontainers -- 通过更改 containers isHidden 变量状态。

像这样:

Storyboard 设置:

代码(基于my other answer):

import UIKit

protocol UpdateImageProtocol {
    func userIsDone(image: UIImage)
}

class ViewController: UIViewController, UpdateImageProtocol {

    @IBOutlet weak var imageView: UIImageView!

    @IBOutlet weak var changeImageContainer: UIView!
    var controllerEdit: ControllerEdit?

    @IBOutlet weak var applyFilterContainer: UIView!
    var controllerFilters: ControllerFilters?

    var image = UIImage(named: "hello")

    override func viewDidLoad() {
        super.viewDidLoad()
        userIsDone(image: image!)
    }

    func userIsDone(image: UIImage) {
        imageView.image = image
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "controllerEdit" {
            let nextView = segue.destination as! ControllerEdit
            nextView.delegate = self
            controllerEdit = nextView

        } else if segue.identifier == "controllerFilters" {
            let nextView = segue.destination as! ControllerFilters
            controllerFilters = nextView
        }
    }

    @IBAction func segmentAction(_ sender: UISegmentedControl) {
        if sender.selectedSegmentIndex == 0 {
            changeImageContainer.isHidden = false
            applyFilterContainer.isHidden = true

            controllerEdit?.customLabel.text = String(arc4random_uniform(999))

        } else {
            changeImageContainer.isHidden = true
            applyFilterContainer.isHidden = false

            controllerFilters?.customLabel.text = String(arc4random_uniform(999))
        }
    }
}

class ControllerEdit: UIViewController {

    @IBOutlet weak var customLabel: UILabel!

    var image = UIImage(named: "newHello")
    var delegate: UpdateImageProtocol?

    @IBAction func changeImage(sender: UIButton) {
        delegate?.userIsDone(image: image!)
    }
}

class ControllerFilters: UIViewController {

    @IBOutlet weak var customLabel: UILabel!

    // TODO
}

【讨论】:

  • 我对 view1 中的图片和 view2 中的一些过滤器进行了基本编辑,仅显示和隐藏子视图是一种好方法吗? @反斜杠-f
  • 每次按下分段控件时,我都需要将更新的值从 segue 传递给 childviewController,但它只在开始时调用一次,然后它会显示并隐藏自己。 @backslah-f
  • 这可行,但我个人认为从架构的角度来看这不是一个很好的方法......看起来你并不真的需要视图控制器来处理你的自定义控制器。太矫枉过正了。最好创建自定义视图并简单地显示/隐藏这些自定义视图。我为此写了一个教程:stackoverflow.com/documentation/ios/1362/…,看看。我将使用此信息更新我的答案。
  • 关于“每次按下分段控件时,我都需要将更新的值从 segue 传递到 childviewController”,这些将是您自定义视图中的变量。然后每次用户按下分段控件时,你会,例如:“editView.customValue = value”/“filterView.customValue = value”。
  • 我不认为我理解这一点,我的意思是每次用户单击segmentedControl 并通过segue 执行此操作时我都必须传递imageView 值,但不是每次单击segmentedControl 时都会调用一次。 @反斜杠-f
【解决方案2】:

在这个函数中放一个断点:

@IBAction func segmentAction(sender:UISegmentedControl){

    if (segmentedControl.selectedSegmentIndex==0){

        performSegueWithIdentifier("EditIAm", sender: nil)
    }

    else if (segmentedControl.selectedSegmentIndex==1){

        performSegueWithIdentifier("EditIAm", sender: nil)
    }
}

如果它没有被调用,那么您可能没有将它连接到 IB 中的操作(@IBAction 左侧的圆圈是否已填充?)

如果它被调用,那么确保 segue 名称是正确的——另外,修复 else if 中的那个,因为看起来你想要“FilterIAm”在那里。

然后,在prepareForSegue:... 中放置一个断点——这会被调用吗?如果不是,请重新检查名称是否与 IB 中的名称相同。

编辑:基于评论

您的 prepareForSegue 不应该创建 ViewController。目标视图控制器是作为执行 segue 的结果创建的,并传递给此函数。

if segue.identifier == "EditIAm"{
    let nextView = segue.destinationViewController as! ControllerEdit
    nextView.originalImage=self.imageView.image!
    nextView.delegate=self
}

你不需要展示任何东西——destinationViewController 将会被展示。你可以设置它的任何变量(就像你一样)——这就是准备转场的意思。

【讨论】:

  • 你能检查一下prepareforsegue函数吗,我认为错误在那个函数中,我想展示childviewController并将值传递给它。这是正确的吗? @LouFranco
猜你喜欢
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多