Swift - 通过导航控制器委托

     2023-02-23     136

关键词:

【中文标题】Swift - 通过导航控制器委托【英文标题】:Swift - Delegate through Nav Controller 【发布时间】:2017-05-01 03:09:57 【问题描述】:

我将在其中包含我的完整代码,但我会尝试指出相关位的位置。基本上,我从 Unwind Segue 返回到带有一些新数据的视图控制器。我在“NBARotoHome”VC 中成功使用了该数据,但我还需要通过嵌入式导航控制器将其中一些数据传递给“NBARotoTabPager”vc。

我正在尝试使用“UpdateChildView”委托(在第一个代码块的顶部)并在“loadViewData()”中调用它的方法(在靠近第一个块底部的“if 语句”中)来执行此操作.

protocol UpdateChildView : class 
 func updateView()
 func test()
 var playerSelected: Player?  get set 




class RotoViewRoundCell: UITableViewCell

@IBOutlet weak var categoryLabel: UILabel!



class RotoViewRoundHeader: UITableViewCell




class NBARotoHome: UIViewController


@IBOutlet weak var posPaidLabel: UILabel!
@IBOutlet weak var progressIndicator: UIProgressView!
@IBOutlet weak var vsLabel: UILabel!
@IBOutlet weak var fantasyFundsAmountLabel: UILabel!
@IBOutlet weak var fantasyFundsLabel: UILabel!
@IBOutlet weak var playerName: UILabel!
@IBOutlet weak var roundIndicator: UILabel!


var selectedPlayer: Player!

var firstNavController: UINavigationController!

weak var updateChildView : UpdateChildView?

override func viewDidLoad() 
    super.viewDidLoad()

    loadViewData()

    firstNavController = self.navigationController



    let rightBarButton = UIBarButtonItem(title: "Select", style: UIBarButtonItemStyle.plain, target: self, action: #selector(myRightSideBarButtonItemTapped(_:)))
    self.navigationItem.rightBarButtonItem = rightBarButton
    self.title = "NBA Roto"





func myRightSideBarButtonItemTapped(_ sender:UIBarButtonItem!)

    performSegue(withIdentifier: "ShowDraft", sender: nil)



override func prepare(for segue: UIStoryboardSegue, sender: Any?) 

    if segue.identifier == "ShowDraft" 
        let navVC = segue.destination as? UINavigationController
        let nbaDraftList = navVC?.viewControllers.first as! NBADraftList
        nbaDraftList.mainNavController = firstNavController
    


    if (segue.identifier == "buyNavControllerChild")

//            let navVC = segue.destination as? UINavigationController
//            let buyVC = navVC?.viewControllers.first as! NBARotoTabPager
//            buyVC.delegate = self

    





override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)




@IBAction func prepareForUnwind(segue: UIStoryboardSegue) 





func loadViewData()

    if((selectedPlayer) != nil)
        roundIndicator.text = "Upcoming: " + selectedPlayer.game_time
        playerName.text = selectedPlayer.Name
        vsLabel.text = selectedPlayer.visiting + " @ " + selectedPlayer.home
        fantasyFundsLabel.text = ""
        fantasyFundsAmountLabel.text = ""

          updateChildView?.test()
     //   updateChildView?.playerSelected = selectedPlayer
    //    updateChildView?.updateView()

    else
        roundIndicator.text = "Select a Player"
        playerName.text = "No Player Selected"
        vsLabel.text = "--"
        fantasyFundsLabel.text = "Fantasy Funds"
        fantasyFundsAmountLabel.text = "$10,000"

    




因为我无法让代理工作,所以我一直在尝试在上面的“准备”方法中设置其代理属性 -'buyVC.delegate = self' - 但我得到的是 'buyVC没有成员代表”,所以这是一条死胡同。

下一段代码是嵌入在导航控制器中的 NBARotoTabPager vc。由于我不再确定的原因,我决定将其设为 NBARotoHome 的子类,但它基本上是一个自定义选项卡寻呼机,它使用分段控件在两个额外的 vcs 之间切换。

此时最重要的一步是让“test”函数工作(它只是打印“test”。它在下面的代码块中实现,从底部倒数第二个 updateView)。

class NBARotoTabPager: NBARotoHome, UpdateChildView

@IBOutlet weak var segmentedControl: UISegmentedControl!
@IBOutlet weak var scoreKey: UIBarButtonItem!
@IBOutlet weak var standings: UIBarButtonItem!

 var playerSelected: Player?


override func viewDidLoad() 



    navigationController?.navigationBar.barTintColor = UIColor(red: 27/255, green: 27/255, blue: 27/255, alpha: 1)


    scoreKey.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Helvetica", size: 13.0)!], for: UIControlState.normal)
    scoreKey.tintColor = UIColor.blue

    standings.setTitleTextAttributes([NSFontAttributeName: UIFont(name: "Helvetica", size: 13.0)!], for: UIControlState.normal)
    standings.tintColor = UIColor.blue

    setupView()


private func setupView() 
    setupSegmentedControl()
    updateView()


private func setupSegmentedControl() 
    // Configure Segmented Control
    segmentedControl.removeAllSegments()
    segmentedControl.insertSegment(withTitle: "Live", at: 0, animated: false)
    segmentedControl.insertSegment(withTitle: "Avg / +", at: 1, animated: false)
    segmentedControl.addTarget(self, action: #selector(selectionDidChange(_:)), for: .valueChanged)
    segmentedControl.selectedSegmentIndex = 0


func selectionDidChange(_ sender: UISegmentedControl) 
    updateView()



private lazy var viewLiveTab: NBARotoLive = 
    // Load Storyboard
    let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)

    // Instantiate View Controller
    var viewController = storyboard.instantiateViewController(withIdentifier: "NBARotoLive") as! NBARotoLive


    if((self.playerSelected) != nil)
        viewController.selectedPlayer = self.playerSelected
    


    // Add View Controller as Child View Controller
    self.add(asChildViewController: viewController)

    return viewController
()

private lazy var viewAvgsTab: NBARotoAvgs = 
    // Load Storyboard
    let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)

    // Instantiate View Controller
    var viewController = storyboard.instantiateViewController(withIdentifier: "NBARotoAvgs") as! NBARotoAvgs

    if((self.playerSelected) != nil)
        viewController.selectedPlayer = self.playerSelected
    


    // Add View Controller as Child View Controller
    self.add(asChildViewController: viewController)

    return viewController
()

private func add(asChildViewController viewController: UIViewController) 
    // Add Child View Controller
    addChildViewController(viewController)

    // Add Child View as Subview
    view.addSubview(viewController.view)

    // Configure Child View
    viewController.view.frame = view.bounds
    viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    // Notify Child View Controller
    viewController.didMove(toParentViewController: self)


private func remove(asChildViewController viewController: UIViewController) 
    // Notify Child View Controller
    viewController.willMove(toParentViewController: nil)

    // Remove Child View From Superview
    viewController.view.removeFromSuperview()

    // Notify Child View Controller
    viewController.removeFromParentViewController()


internal func test()
    print("test")


internal func updateView() 

    if segmentedControl.selectedSegmentIndex == 0 



        let position = viewAvgsTab.tableView.contentOffset.y;
        viewLiveTab.tableView.contentOffset = CGPoint(x:0, y:position);


        remove(asChildViewController: viewAvgsTab)
        add(asChildViewController: viewLiveTab)

     else 

        let position = viewLiveTab.tableView.contentOffset.y;
        viewAvgsTab.tableView.contentOffset = CGPoint(x:0, y:position);

        remove(asChildViewController: viewLiveTab)
        add(asChildViewController: viewAvgsTab)
    



我查看了很多示例,但我不理解整个“设置委托”的内容,即 theSecondViewController.delegate = self.有时我会看到您不需要这样做的示例。而其他时候,我的 VC 似乎甚至没有委托财产。所以我不确定这是否是我的具体问题,但任何方向都将不胜感激。谢谢

【问题讨论】:

【参考方案1】:

实现委托分为三个步骤。

    创建协议..(您已经通过创建 updateChildView 协议完成了此操作) 您需要在您希望接收和处理此数据的类中实现此协议。(您尚未完成此步骤,这就是您无法设置 buyVC.delegate = self 的原因) 您需要在 ViewController2 中添加一个名为“delegate”的属性,并在步骤 1 中将其作为您的协议类型(您尚未完成此步骤,并且 vc2 中没有名为“delegate”的属性..这就是为什么你得到这个错误'buyVC没有成员代表')

这是一个简单的例子:

协议:

protocol UpdateChildView //removed :class
  func updateView()
  func test()
  var playerSelected: Player?  get set 

视图控制器 A:

class NBARotoHome: UIViewController, UpdateChildView  //added conformance to the protocol

  //add the methods for conforming to protocol and add your implementation

   func updateView() 
        //add your implementation
   
   func test()
        //add your implementation
   
   var playerSelected: Player? 
        //add your implementation
   

  prepare(for: Segue) 
    /** code for passing data **/
    let navVC = segue.destination as? UINavigationController
    let buyVC = navVC?.viewControllers.first as! NBARotoTabPager
    buyVC.delegate = self
            //sets the delegate in the new viewcontroller 
            //remember.. delegate is a property in the next vc
           // and the property only accepts any viewcontroller that is implements updatechildview protocol
    present(vc2)
    
   

viewcontroller2:

class viewControllerB: UIViewController 

  var delegate: UpdateChildView? //add this

  viewdidload 
      delegate?.test() //call the func in the previous vc
  

【讨论】:

谢谢,这绝对给了我一个清晰而有用的例子。我不确定这是否能满足我的特殊需求,因为我认为我需要在 viewControllerB 中实现方法的一致性和实现。这是完全奇怪和不可能的吗? 协议只是给出一个类必须实现的所需方法和属性的列表。所以只要继承协议,实现需要的方法,应该没问题... 您的代码的问题是您在 NBARtoHome 视图控制器中有一个 updateChildView 属性,并且未设置,因此为 nil。 尝试将 NBArtolive viewcontroller 设置为 NBARtoHome.updatechildview 属性中的一个属性,您应该可以调用测试函数 所以我让协议按照您在示例中显示的方式工作。我真正的问题是我想从 LoadViewData()(NBARotoHome 中的最后一个方法)调用 updateView()(NBATabPager 中的最后一个方法)。您的意思是将 NBARotoTabPager 设置为 NBARotoHome.loadViewData() 中的属性吗?还是我都倒退了?

通过导航控制器时丢失指向委托的指针

】通过导航控制器时丢失指向委托的指针【英文标题】:LosepointertoDelegatewhilegoingthroughNavigationController【发布时间】:2012-06-2818:01:37【问题描述】:我不完全确定如何解释我的问题,但我会尝试。所以我一直在尝试学习如何使用... 查看详情

如何在 Swift iOS 中自定义导航控制器

】如何在SwiftiOS中自定义导航控制器【英文标题】:HowtocustomizeanavigationcontrollerinswiftiOS【发布时间】:2015-08-1808:37:02【问题描述】:我正在尝试自定义导航控制器,但它不起作用我认为这是因为我正在使用应用程序委托通过此代... 查看详情

使用标签栏控制器 -> 导航控制器 -> 视图层次结构 - iOS Swift 从应用程序委托呈现视图

】使用标签栏控制器->导航控制器->视图层次结构-iOSSwift从应用程序委托呈现视图【英文标题】:PresentviewfromappdelegatewithatabbarController->Navcontroller->ViewHierarchy-iOSSwift【发布时间】:2017-03-0715:48:55【问题描述】:我搜索了整... 查看详情

Swift:如何使用 UISwitch 控制 UITextField 通过委托启用或禁用

】Swift:如何使用UISwitch控制UITextField通过委托启用或禁用【英文标题】:Swift:howtouseUISwitchtocontrolUITextFieldtobeenabledordisabledwithadelegate【发布时间】:2015-06-2800:42:08【问题描述】:在XCode6.3.2,我有一个UITextField:@IBOutletweakvaruiswitchCo... 查看详情

UIView 类中的 Swift 集合视图委托

...作用。我可以通过这个类分配委托和数据源还是必须通过控制器来完成?这是我的代码: 查看详情

UIPageViewController 不调用委托方法(Swift 5)

...非常简单的UIPageViewController设置。当我创建我的页面视图控制器并导航到它时,一切似乎都正常工作并且它正确加载了第一页。但是,当我尝试滑动或切换到Vi 查看详情

Swift BarButtonItem 不更新

...发布时间】:2020-02-0413:48:59【问题描述】:我有一个导航控制器和一个根视图控制器。在这个vc中,我将一个表视图控制器作为弹出框呈现。当在此tvc上选择一行时,我执行一个委托方法(我知道它已执行)并关闭tvc。委托是我... 查看详情

无法使用 Swift 通过导航控制器返回到另一个导航控制器的 VC

】无法使用Swift通过导航控制器返回到另一个导航控制器的VC【英文标题】:UnabletogobackthroughanavigationcontrollertoaVCofanothernavigationcontrollerusingSwift【发布时间】:2016-08-2510:57:08【问题描述】:正如您在下面看到的,notificationsVC是TabBar... 查看详情

Swift:通过presentViewController传递导航栏

...】:2016-08-0423:41:31【问题描述】:在我的故事板中有导航控制器、viewContrl1和viewContrl2。对于下一次更新,我必须设法将viewContrl2连接到viewContrl2的另一个实例。在从***获得一些帮助 查看详情

iOS,Swift 4,导航控制器标题颜色在通过单击后退按钮返回时不会更改

】iOS,Swift4,导航控制器标题颜色在通过单击后退按钮返回时不会更改【英文标题】:iOS,Swift4,NavigationControllertitlecolourisnotbeingchangedwhencomingbackviaclickingonbackbutton【发布时间】:2018-07-3123:17:41【问题描述】:我的问题与这个问题Vie... 查看详情

Swift:通过 TabBar 和导航控制器以编程方式从一个视图转换到另一个视图

】Swift:通过TabBar和导航控制器以编程方式从一个视图转换到另一个视图【英文标题】:Swift:Programmaticallytransitioningfrom1viewtoanotherviaaTabBarandNavigationController【发布时间】:2016-06-1913:31:16【问题描述】:用户登录并登陆viewNumOne,填... 查看详情

Swift 语言的委托

...age【发布时间】:2014-06-0511:37:28【问题描述】:我有两个控制器,我需要调用第一个控制器到第二个控制器的函数:在第二个控制器中,我在类中创建了协议和初始化委托:protocoltestProtocolfunctestDelegate()//thisfunctionthefirstcontrollersc... 查看详情

iOS - 通过动画将搜索栏从中心移动到导航栏下方(Swift)

...】:我有一个搜索栏,它通过界面生成器添加到我的视图控制器的中心,我什至将它与IBOutlet连接起来。但是,我不得不将搜索栏放在视图控制器的中心,因为它上面有重要信息。我 查看详情

Swift 中的多视图控制器导航

】Swift中的多视图控制器导航【英文标题】:MultiViewControllerNavigationinSwift【发布时间】:2019-04-0303:37:41【问题描述】:Swift中的侧边菜单导航Swift4.2,Xcode10.0我的最终目标是能够轻松(通常)横向/导航通过我的视图控制器,如下... 查看详情

通过视图控制器将委托传递给视图控制器

】通过视图控制器将委托传递给视图控制器【英文标题】:Passingdelegatetoaviewcontrollerthroughaviewcontroller【发布时间】:2012-02-2410:08:57【问题描述】:我的storyboard中有三个viewController,每个都有三个viewController类。从我的主视图控制... 查看详情

如何通过单击按钮在 Swift UI 中从一个视图导航到另一个视图

...视图推送到另一个视图。同样,我们在情节提要中从一个控制器导航到另一个控制器。但在SwiftUI中如何实现这一点。【问题讨论】:【参考方案1】:您 查看详情

如何通过 Swift 扩展实现委托方法

】如何通过Swift扩展实现委托方法【英文标题】:HowdoIimplementdelegatemethodsthroughSwiftextension【发布时间】:2016-05-2507:46:33【问题描述】:我的项目是Obj-C和Swift的混合体,我正在尝试使用Swift扩展我的AppDelegate类。所以现在我有AppDeleg... 查看详情

如何从 App 委托导航内部视图控制器

】如何从App委托导航内部视图控制器【英文标题】:HowtonavigateInnerviewcontrollerfromAppdelegate【发布时间】:2016-06-2704:50:27【问题描述】:在我的应用委托中,这是我导航到SWRevealViewController的方式letrevealViewController=mainStoryboard.instantia... 查看详情