页面视图控制器中的子视图控制器无法接收委托调用

如何解决页面视图控制器中的子视图控制器无法接收委托调用

我在父 PageViewController 中的两个子视图控制器出现问题,其中一个子节点调用的委托未被另一个子节点接收。

我的第一个孩子包含按钮,当一个按钮被按下时,另一个孩子的委托被触发以暂停计时器。但是,它无法接收呼叫并且计时器继续运行。

这是我的 PageViewController:

class StartMaplessWorkoutPageViewController: UIPageViewController,UIPageViewControllerDelegate,UIPageViewControllerDataSource {

    lazy var workoutViewControllers: [UIViewController] = {
        return [self.getNewViewController(viewController: "ButtonsViewController"),self.getNewViewController(viewController: "DisplayMaplessViewController")]
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.dataSource = self
        
        // Saw this from another answer,doesn't do anything that helps (at the moment)
        let buttonsViewController = storyboard?.instantiateViewController(withIdentifier: "ButtonsViewController") as! ButtonsViewController
        let displayMaplessViewController = storyboard?.instantiateViewController(withIdentifier: "DisplayMaplessViewController") as! DisplayMaplessViewController
        
        buttonsViewController.buttonsDelegate = displayMaplessViewController
        
        if let firstViewController = workoutViewControllers.last {
            setViewControllers([firstViewController],direction: .forward,animated: true,completion: nil)
        }
        
        let pageControl = UIPageControl.appearance(whenContainedInInstancesOf: [StartWorkoutPageViewController.self])
        pageControl.currentPageIndicatorTintColor = .orange
        pageControl.pageIndicatorTintColor = .gray
    }
    
    func getNewViewController(viewController: String) -> UIViewController {
        return (storyboard?.instantiateViewController(withIdentifier: viewController))!
    }
    
    // MARK: PageView DataSource
    func pageViewController(_ pageViewController: UIPageViewController,viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = workoutViewControllers.firstIndex(of: viewController) else {
            return nil
        }
        
        let previousIndex = viewControllerIndex - 1
        
        guard previousIndex >= 0 else {
            return workoutViewControllers.last
        }
        
        guard workoutViewControllers.count > previousIndex else {
            return nil
        }
        
        return workoutViewControllers[previousIndex]
    }
    
    func pageViewController(_ pageViewController: UIPageViewController,viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = workoutViewControllers.firstIndex(of: viewController) else {
            return nil
        }
        
        let nextIndex = viewControllerIndex + 1
        let workoutViewControllersCount = workoutViewControllers.count
        
        guard workoutViewControllersCount != nextIndex else {
            return workoutViewControllers.first
        }
        
        guard workoutViewControllersCount > nextIndex else {
            return nil
        }
        
        return workoutViewControllers[nextIndex]
    }
    
    func presentationCount(for pageViewController: UIPageViewController) -> Int {
        return workoutViewControllers.count
    }
    
    func presentationIndex(for pageViewController: UIPageViewController) -> Int {
        guard let firstViewController = viewControllers?.first,let firstViewControllerIndex = workoutViewControllers.firstIndex(of: firstViewController) else {
            return 0
        }
        
        return firstViewControllerIndex
    }
}

我的带有按钮的 ChildViewController:

protocol ButtonsViewDelegate: class {
    func onButtonPressed(button: String)
}

class ButtonsViewController: UIViewController {
    
    weak var buttonsDelegate: ButtonsViewDelegate?
    
    var isPaused: Bool = false
    
    @IBOutlet weak var startStopButton: UIButton!
    @IBOutlet weak var optionsButton: UIButton!
    @IBOutlet weak var endButton: UIButton!
    
    @IBAction func startStopButton(_ sender: Any) {
        if isPaused == true {
            buttonsDelegate?.onButtonPressed(button: "Start")
            isPaused = false
        } else {
            buttonsDelegate?.onButtonPressed(button: "Pause")
            isPaused = true
        }
    }
    
    @IBAction func endButton(_ sender: Any) {
        let menu = UIAlertController(title: "End",message: "Are you sure you want to end?",preferredStyle: .actionSheet)
        
        let end = UIAlertAction(title: "End",style: .default,handler: { handler in
            self.buttonsDelegate?.onButtonPressed(button: "End")
        })
        
        let cancelAction = UIAlertAction(title: "Cancel",style: .cancel)
        menu.addAction(end)
        menu.addAction(cancelAction)
        
        self.present(menu,completion: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

}

我的另一个 ChildViewController,它应该接收 ButtonsViewDelegate 的调用:

import UIKit

class DisplayMaplessViewController: UIViewController,ButtonsViewDelegate {
    
    var timer = Timer()
    var currentTime: TimeInterval = 0.0
    var isCountdown: Bool = false
    var isInterval: Bool = false
    var currentRepeats: Int = 0
    var currentActivity: Int = 0
    var count: Int = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        startIntervalTimer(withTime: 0)
    }

    // Currently not being called
    func onButtonPressed(button: String) {
        switch button {
        case "Start":
            restartIntervalTimer()
        case "Pause":
            pauseIntervalTimer()
        case "End":
            stop()
        default:
            break
        }
    }
    
    func startIntervalTimer(withTime: Double) {
        if withTime != 0 {
            currentTime = withTime
            if isInterval != true {
                isCountdown = true
            }
        }

        timer = Timer.scheduledTimer(timeInterval: 1.0,target: self,selector: #selector(intervalTimerUpdate),userInfo: nil,repeats: true)
    }
    
    func pauseIntervalTimer() {
        timer.invalidate()
    }
    
    func restartIntervalTimer() {
        timer = Timer.scheduledTimer(timeInterval: 1.0,repeats: true)
    }

    // Currently Not being called
    func stop() {
        timer.invalidate()
        let formatter = DateComponentsFormatter()
        formatter.unitsStyle = .positional
        formatter.allowedUnits = [.hour,.minute,.second]
        formatter.zeroFormattingBehavior = [.pad]
        
        let timeString = formatter.string(from: currentTime)
        
        // save the data etc

        print("Stop is called")
    }
    
    @objc func intervalTimerUpdate() {
        currentTime += 1.0
        print(currentTime)
    }

}

很抱歉,这太啰嗦了,已经尝试了很长时间,但真的很生气,因为它不起作用!谢谢!

解决方法

我会尽量说清楚,希望我能做到,因为英语不是我的母语。

在我看来,您正在实例化您的 ViewControllers 以在 getNewViewController() 方法中呈现并将它们存储在 workoutViewControllers 数组中,但是您将委托设置为一个您从未设置过的单独实例在您的 PageVC 中。您需要使用相同的实例设置委托。

这两个是两个 VC 两个实例(也不确定标识符“DisplayViewController”是否正确,我希望“DisplayMaplessViewController” ",没有故事板就很难讲了):

    let buttonsViewController = storyboard?.instantiateViewController(withIdentifier: "ButtonsViewController") as! ButtonsViewController
    let displayMaplessViewController = storyboard?.instantiateViewController(withIdentifier: "DisplayViewController") as! DisplayMaplessViewController
    
    buttonsViewController.buttonsDelegate = displayMaplessViewController

数组中的这些另外两个实例,与上面的那些无关,属于相同的两个类

    lazy var workoutViewControllers: [UIViewController] = {
    return [self.getNewViewController(viewController: "ButtonsViewController"),self.getNewViewController(viewController: "DisplayMaplessViewController")]
}()

为了更好地理解我的意思,我从头开始重构并简化了您的项目(必须以编程方式进行,因为我不习惯故事板)。 它现在由一个 PageController 组成,该 buttonsVC 显示一个带有红色按钮的 displayMaplessVC 和一个带有蓝色背景的 buttonsVC.buttonsDelegate = displayMaplessVC。 按下红色按钮后,将调用委托方法,使蓝色背景变为绿色。
看看我在做什么,因为我正在附加我设置委托的相同实例:

  1. 实例化一个 DisplayMaplessViewController 对象和 ButtonsViewController 对象;
  2. 设置StartMaplessWorkoutPageViewController;
  3. 将两个 ViewController 附加到数组中。

这是完成任务的一种方式,但可以肯定的是,还有其他几种方法可以实现相同的结果,一旦您明白了自己的错误,就可以选择您最喜欢的方式。

只需将其复制并粘贴到新项目中,构建并运行即可(您必须将 Storyboard 中起始 ViewController 的类设置为 import UIKit class StartMaplessWorkoutPageViewController: UIViewController,UIPageViewControllerDelegate,UIPageViewControllerDataSource { private var workoutViewControllers = [UIViewController]() private let pageController: UIPageViewController = { let pageController = UIPageViewController(transitionStyle: .scroll,navigationOrientation: .horizontal,options: nil) return pageController }() override func viewDidLoad() { super.viewDidLoad() pageController.delegate = self pageController.dataSource = self let buttonsVC = ButtonsViewController() let displayMaplessVC = DisplayMaplessViewController() buttonsVC.buttonsDelegate = displayMaplessVC workoutViewControllers.append(buttonsVC) workoutViewControllers.append(displayMaplessVC) self.addChild(self.pageController) self.view.addSubview(self.pageController.view) self.pageController.setViewControllers([displayMaplessVC],direction: .forward,animated: true,completion: nil) self.pageController.didMove(toParent: self) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() pageController.view.frame = view.bounds } func pageViewController(_ pageViewController: UIPageViewController,viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let viewControllerIndex = workoutViewControllers.firstIndex(of: viewController) else { return nil } let previousIndex = viewControllerIndex - 1 guard previousIndex >= 0 else { return workoutViewControllers.last } guard workoutViewControllers.count > previousIndex else { return nil } return workoutViewControllers[previousIndex] } func pageViewController(_ pageViewController: UIPageViewController,viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let viewControllerIndex = workoutViewControllers.firstIndex(of: viewController) else { return nil } let nextIndex = viewControllerIndex + 1 let workoutViewControllersCount = workoutViewControllers.count guard workoutViewControllersCount != nextIndex else { return workoutViewControllers.first } guard workoutViewControllersCount > nextIndex else { return nil } return workoutViewControllers[nextIndex] } func presentationCount(for pageViewController: UIPageViewController) -> Int { return workoutViewControllers.count } } ):

protocol ButtonsViewDelegate: class {
    func onButtonPressed()
}

import UIKit

class ButtonsViewController: UIViewController {

weak var buttonsDelegate: ButtonsViewDelegate?

let button: UIButton = {
    let button = UIButton()
    button.backgroundColor = .red
    button.addTarget(self,action: #selector(onButtonPressed),for: .touchUpInside)
    return button
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(button)
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    button.frame = CGRect(x: 50,y: 50,width: 100,height: 100)
}

@objc private func onButtonPressed() {
    buttonsDelegate?.onButtonPressed()
}

}

.

import UIKit

class DisplayMaplessViewController: UIViewController,ButtonsViewDelegate {

private let testView: UIView = {
    let view = UIView()
    view.backgroundColor = .blue
    return view
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(testView)
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    testView.frame = view.bounds
}

internal func onButtonPressed() {
    testView.backgroundColor = .green
}

}

.

inject

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res