0
votes

My story board image is below

When the user clicked in a cell it will go to the detail view controller here I post a notification with the selected index(object of a class). In detail view controller I used a container view. In this container view, I used a page view controller having two view controllers let's say A and B correspondingly. Both these two view controllers I created add observer method. But only 'A' view controller is registering for the notification. How can I get the selected index(object of a class) in B view controller..?

Code of detail View controller

 override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.post(name: Notification.Name(rawValue: mynotificationkey), object: nil, userInfo: ["object": self.treatobj])



}




override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "pageView2" {
       if let destination = segue.destination as? PageViewController {
            destination.treatmentObject = treatobj



        }



    }

}

code of First View Controller that its executing fine

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(display(notification:)), name: Notification.Name(rawValue: mynotificationkey), object: nil)

      }

override func viewWillDisappear(_ animated: Bool) {
    NotificationCenter.default.removeObserver(self)
}


  func display(notification: Notification){
    if let object = notification.userInfo {
        if let obj = object["object"] {

            treatObject = obj as! TreatMents
            print(treatObject)
            self.detailTitleLabel.text = treatObject.trtName
            self.DesctextView.text = treatObject.desc1




        }
    }

}

code of second view controller that does not execute add observer

  override func viewDidLoad() {
    super.viewDidLoad()


    about.text = treatObj.aboutkerala
    //benifits = treatObj.benifits!



  NotificationCenter.default.addObserver(self, selector: #selector(notfrecieved(notification:)), name: NSNotification.Name(rawValue: mynotificationkey), object: nil)


    // Do any additional setup after loading the view.
}


func notfrecieved(notification: Notification) {

    if let object = notification.userInfo {
        if let obj = object["object"] {
            print(obj)
            treatObj = obj as! TreatMents
            about.text = treatObj.aboutkerala
            benifits = treatObj.benifits!
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }


        }
    }

}

code of Page view controller

    class PageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {


var treatmentObject = TreatMents()

lazy var VCArray : [UIViewController] = {

    return [self.VCInstance(name: "DescFisrtVC"),
            self.VCInstance(name: "DescSecondVC"),
            ]
}()


private func VCInstance(name: String) -> UIViewController {

  return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: name)


}


public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

    guard let viewControllerIndex = VCArray.index(of: viewController) else {
        return nil
    }


    let previousIndex = viewControllerIndex - 1

    guard previousIndex >= 0 else {
        return VCArray.last
    }

    guard VCArray.count > previousIndex else {
        return nil
    }



    return VCArray[previousIndex]
}


public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {

    guard let viewControllerIndex = VCArray.index(of: viewController) else {
        return nil
    }

    let nextIndex = viewControllerIndex + 1

    guard nextIndex < VCArray.count else {
        return VCArray.first
    }

    guard VCArray.count > nextIndex else {
        return nil
    }


    return VCArray[nextIndex]

}


// A page indicator will be visible if both methods are implemented, transition style is 'UIPageViewControllerTransitionStyleScroll', and navigation orientation is 'UIPageViewControllerNavigationOrientationHorizontal'.
// Both methods are called in response to a 'setViewControllers:...' call, but the presentation index is updated automatically in the case of gesture-driven navigation.

public func presentationCount(for pageViewController: UIPageViewController) -> Int {

    return VCArray.count
}


public func presentationIndex(for pageViewController: UIPageViewController) -> Int {


    guard let firstViewController = viewControllers?.first, let firstViewcontrollerIndex = VCArray.index(of: firstViewController) else {
        return 0
    }

    return firstViewcontrollerIndex
}
override func viewDidLoad() {

           super.viewDidLoad()
    self.dataSource = self
    self.delegate = self


    if let firstVc = VCArray.first {

        setViewControllers([firstVc], direction: .forward, animated: true, completion: nil)
    }





    // Do any additional setup after loading the view.
}
2
at where you are post this notification NSNotification.Name(rawValue: mynotificationkey). ? - KKRocks
you need to use different key for notification. - KKRocks
I declared a global variable as mynotificationkey and stored a value to that variable - Yasheed Mohammed

2 Answers

0
votes
  • If you want to NotificationCenter then you need to load that class in memory first .

  • If you are added NotificationCenter in class but that class not loaded so this will be not working .

0
votes

From the flow it looks to me that the two VCs in UIPageViewControllers didn't load yet when you are posting the notification.

Have a look at the explanation given in doc:

When defining a page view controller interface, you can provide the content view controllers one at a time (or two at a time, depending upon the spine position and double-sided state) or as-needed using a data source. When providing content view controllers one at a time, you use the setViewControllers(_:direction:animated:completion:) method to set the current content view controllers. To support gesture-based navigation, you must provide your view controllers using a data source object.

So my guess is that since one page is loaded at a time, so your second controller didn't register for this event.

I have an objection on this process design using NSNotification, since from your code it looks to me that you want to evaluate your TreatMents objects on both screen when they gets load, IMHO you can either use Singleton concept (using session) or use KVO to fix this problem.

EDIT:

In PageViewController you implement these two functions:

public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?   
public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? 

that returns a VC from VCArray like:

return VCArray[previousIndex]

You also have treatmentObject in PageViewController, can you pass this variable to your two viewcontrollers while fetching it in above delegate functions like:

public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

    guard let viewControllerIndex = VCArray.index(of: viewController) else {
        return nil
    }


    let previousIndex = viewControllerIndex - 1

    guard previousIndex >= 0 else {
        return VCArray.last
    }

    guard VCArray.count > previousIndex else {
        return nil
    }

    let VC = VCArray[previousIndex]      // <------ Check this out
    VC.treatObj = self.treatmentObject;  // <------ Check this out

    return VC
}

Or you can also save your selected treatment in session and retrieve it in two view controllers.