首页 > 解决方案 > 委托方法没有被 UITabBarController 调用

问题描述

FourthViewController中,我有一个滑块,其值从 1 到 1000 不等。设置的值通过委托发送到PatternViewController,它应该被用来做某事(我将打印用于测试目的)。

我以前和代表一起工作过,一切都好,多次检查代码,堆栈上有多个答案,我似乎找不到问题。任何帮助将非常感激

更新:我添加了一个按钮,以便更容易跟踪。事实证明,第一次按下按钮,什么都没有发生。但是如果我首先结帐PatternViewController,然后我返回FourthViewController并按下按钮,代表就会被触发。有人知道为什么会这样吗?

第四视图控制器

import UIKit

class FourthViewController: UIViewController {

//MARK: Outlets

@IBOutlet var persistenceButton: UIButton!
@IBOutlet var persistenceSlider: UISlider!
@IBOutlet var persistenceLabel: UILabel!
weak var delegate: FourthViewControllerDelegate?

//MARK: Stored Properties - Constants

let userDefaults = UserDefaults.standard
let keyName = "sliderValue"

//MARK: Initializer

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

//MARK: Actions

@IBAction func handleValueChanged(_ sender: UISlider) {
    updateLabel()
    persistSliderValue(value: persistenceSlider.value, key: keyName)
    }

//MARK: Methods

func updateLabel() {
    persistenceLabel.text = String(format: "%.2f", persistenceSlider.value)
    }

func persistSliderValue(value: Float, key: String) {
    userDefaults.set(value, forKey: key)
    }

func loadSliderValue() {
    let persistedValue = userDefaults.float(forKey: keyName)
    persistenceSlider.value = persistedValue
    updateLabel()
    }
}

func initialSetUp()  {
    persistenceButton.addTarget(self, action: #selector(handleButtonPressed), for: .touchUpInside)
    }

@objc func handleButtonPressed() {
    delegate?.valueChanged(value: persistenceSlider.value)
    }
}

模式视图控制器

import UIKit

class PatternViewController: UIViewController, FourthViewControllerDelegate {

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

    func setUp() {
        if let tabBar = self.tabBarController, let viewController = tabBar.viewControllers, let fourthViewController = viewController[3] as? FourthViewController  {
            fourthViewController.delegate = self
        }
    }

    func valueChanged(value: Float) {
        print(value)
    }
}

标签: iosswiftmethodsdelegatesuitabbarcontroller

解决方案


这取决于您如何实例化选项卡视图控制器。例如,如果您使用情节提要执行此操作,则各个选项卡的视图控制器会延迟实例化,仅在用户点击它们时才实例化。(这有助于减少因实例化所有四个选项卡的视图控制器而导致的延迟。)

虽然理论上您可以继续让标签栏控制器以编程方式预先实例化四个视图控制器,而不是通过情节提要即时实例化,但我可能会考虑UITabBarControllerDelegate为标签栏控制器指定一个。让标签栏控制器的委托方法更新相关标签的视图控制器模型。

这是一个带有两个选项卡的示例,第一个有一个滑块,第二个有一个显示滑块值的标签。在这个简化的示例中,我已将模型对象(与滑块关联的值)移动到选项卡栏控制器中,并在您选择关联的选项卡时将其传递给第二个视图控制器。

//  TabViewController.swift

import UIKit

class TabBarController: UITabBarController {
    var value: Float = 0.5
    
    override func viewDidLoad() {
        super.viewDidLoad()

        delegate = self
    }
}

// MARK: - UITabBarControllerDelegate

extension TabViewController: UITabBarControllerDelegate {
    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        guard let viewController = viewController as? SecondViewController else { return }

        viewController.value = value
    }
}

//  FirstViewController.swift

import UIKit

class FirstViewController: UIViewController {

    @IBOutlet weak var slider: UISlider!

    override func viewDidLoad() {
        super.viewDidLoad()
        guard let tabBarController = tabBarController as? TabViewController else { return }
        slider.value = tabBarController.value
    }

    @IBAction func didAdjustSlider(_ sender: UISlider) {
        guard let tabBarController = tabBarController as? TabViewController else { return }
        tabBarController.value = sender.value
    }

}

//  SecondViewController.swift

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    var value: Float = 0 { didSet { updateLabel() } }

    let formatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .percent
        return formatter
    }()

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

    func updateLabel() {
        label?.text = formatter.string(for: value)
    }
}

在此处输入图像描述

大概不用说,我不仅为两个tab的view controller设置了base view controller类,还为tab bar controller的storyboard场景设置了上面的base view controller TabBarController


推荐阅读