简体   繁体   中英

Swift 3 - Delegate always returns nil value

UPDATED:

I have designed custom tabBar using buttons. I have 3 tabs, First tab has Messages icon, Second has Profile icon and Third has Photos icon. For third tab button, I have used uiCollectionView() where I need to set images.

For the Third tab's ViewController,there is one condition that I need to check, before changing the title of the first tab button. If messages JSON array is not empty then set "new message" title on the first tab button, else the Messages icon won't change.

There is one ParentTabViewController which has these 3 tabs, I have used uiView, where I change the content according to the tab buttons pressed. I tried to access the values of 3rd tab in ParentTabViewController by using delegate, but the delegate is always nil. I did like this:

class ParentTabViewController: UIViewController,MessageDelegateProtocol{
@IBOutlet weak var contentView: UIView!
@IBOutlet var tabBarButtons : [UIButton]!
@IBOutlet weak var firstTabButton: UIButton!
var MessageVC : UIViewController!
var ProfileVC : UIViewController!
var PhotosVC : UIViewController!
var viewControllers : [UIViewController]!
var message : String!
var selectedIndex:Int = 0
var photoVC = PhotosVC()

override func viewDidLoad() {
    super.viewDidLoad()
    photoVC.newMessageDelegate = self

    let storyBoard = UIStoryboard(name:"Main", bundle:nil)
    MessageVC = storyBoard.instantiateViewController(withIdentifier: "messagevc")
    ProfileVC = storyBoard.instantiateViewController(withIdentifier: "profile")
    PhotosVC = storyBoard.instantiateViewController(withIdentifier: "photos")

    viewControllers = [MessageVC, ProfileVC, PhotosVC]
    tabBarButtons[selectedIndex].isSelected = true
    didPressTabs(tabBarButtons[selectedIndex])
}
@IBAction func didPressTabs(_ sender: UIButton)
{
    let previousIndex = selectedIndex
    selectedIndex = sender.tag
    tabBarButtons[previousIndex].isSelected = false

    let previousVC = viewControllers[previousIndex]

    previousVC.willMove(toParentViewController: nil)
    previousVC.removeFromParentViewController()
    previousVC.view.removeFromSuperview()

    sender.isSelected = true
    let presentVC = viewControllers[selectedIndex]
    addChildViewController(presentVC)

    presentVC.view.frame = contentView.bounds
    contentView.addSubview(presentVC.view)
    presentVC.didMove(toParentViewController: self)

    if selectedIndex == 2{   // this is what I thought of doing.Correct me if wrong.
     //  check the condition 
     //   if messagesArray != nil
     //   set the first tab title "new message"
    }
    else{
     //    do not change the button image 
    }
}
func sendMessage(message : String)
{
    self.message = message
    print("message........", self.message, "\n\n")
}
}

Here is the View Controller for 3rd tab:

import UIKit
protocol MessageDelegateProtocol:class  {
 func sendMessage(message : String) 
}

class PhotosVC: UIViewController,UICollectionViewDataSource, UICollectionViewDelegate{
@IBOutlet weak var collectionView: UICollectionView!
var userMessageArray = [UserMessageClass]()    // array of model class
var newMessage : String!
weak var newMessageDelegate : MessageDelegateProtocol?

override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.delegate = self
    collectionView.dataSource = self
    loadData()                        // function to get json reponse
}
// implement collectionView delegate and dataSource methods

func getData(newMsg : UserMessageClass)    //func to get values from model class
{
    newMessage = newMsg.messageString           // here I get the "new message" String
    newMessageDelegate?.sendMessage(message: newMessage)
}    enter code here

func loadData()
{
    // get json response. And pass the payload to UserMessageClass using that class's array
    userMessageArray.append(UserMessageClass(dict : jsonData))
    var msgData = UserMessageClass(dict: jsonData)
    getData(alarm: msgData)
}
}

I tried searching a lot about accessing tab buttons in another VC, but didn't find any nearby approach as such. Also I am not able to figure out why delegate is always nil. Suggestions or Help would be grateful. Many Thanks :)

The problem is the following line.

let firstTab = storyBoard.instantiateViewController(withIdentifier: "parentVC") as! ParentViewController

You are probably expecting it to give you the instance of ParentViewController which you have setup initially. However, it will give you the instance of a newly initiated ParentViewController which is not what you want.

To counter this problem you can either make use of a delegate or completion block defined which will be defined inside your ParentViewController class.

Update: Try adding PhotosVC.newMessageDelegate = self under the line

PhotosVC = storyBoard.instantiateViewController(withIdentifier: "photos")

Also change var PhotosVC : UIViewController! to var photosVC: PhotosVC!

This should work now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM