Perform Segue from a custom Button





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







2















I created a custom button to include in the button the information I need:



class CustomButton: UIButton {   
var urlString: String?
var documentType: String?
var requestEntity: String?
var requestSortBy: [NSSortDescriptor]?
var requestPredicate: NSPredicate?
}


When I create the cells in the collectionView (embedded in a tableView) I include the information in my custom button, called documentTypeButton. And also the target for executing the function HomeTableViewController.documentTypeButtonTapped(_:) to perform the segue.



func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

let languageSelected = UserDefaults().value(forKey: "language") as! String

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell

cell.documentTypeButton.documentType = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].name
cell.documentTypeButton.requestEntity = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].entityName
cell.documentTypeButton.requestSortBy = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].sortBy
cell.documentTypeButton.requestPredicate = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].predicate
cell.documentTypeButton.addTarget(nil, action: #selector(HomeTableViewController.documentTypeButtonTapped(_:)), for: .touchUpInside)


return cell

}


And the, in the HomeTableViewController I have the function to execute when touching inside the button:



@objc func documentTypeButtonTapped(_ sender: CustomButton) {

performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())
print(sender.documentType)
print(sender.requestEntity)

}

func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

let languageSelected = UserDefaults().value(forKey: "language") as! String

if let destination = segue.destination as? DocumentListTableViewController {

destination.titlePassed = sender.documentType!.localized(lang: languageSelected)
destination.requestedEntity = sender.requestEntity
destination.requestedSortBy = sender.requestSortBy
destination.requestedPredicate = sender.requestPredicate

}

}


The print statements above work well and print the information. And the segue goes to the DocumentListTableViewController.



In the viewDidLoad of the DocumentListTableViewController I added the following:



override func viewDidLoad() {
super.viewDidLoad()

print(titlePassed)
print(requestedEntity)

}


And the two print statements print nil.



I guess the problem should be in the prepareForSegue, maybe with the sender... I don't know.



Any help would be appreciated.










share|improve this question































    2















    I created a custom button to include in the button the information I need:



    class CustomButton: UIButton {   
    var urlString: String?
    var documentType: String?
    var requestEntity: String?
    var requestSortBy: [NSSortDescriptor]?
    var requestPredicate: NSPredicate?
    }


    When I create the cells in the collectionView (embedded in a tableView) I include the information in my custom button, called documentTypeButton. And also the target for executing the function HomeTableViewController.documentTypeButtonTapped(_:) to perform the segue.



    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let languageSelected = UserDefaults().value(forKey: "language") as! String

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell

    cell.documentTypeButton.documentType = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].name
    cell.documentTypeButton.requestEntity = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].entityName
    cell.documentTypeButton.requestSortBy = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].sortBy
    cell.documentTypeButton.requestPredicate = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].predicate
    cell.documentTypeButton.addTarget(nil, action: #selector(HomeTableViewController.documentTypeButtonTapped(_:)), for: .touchUpInside)


    return cell

    }


    And the, in the HomeTableViewController I have the function to execute when touching inside the button:



    @objc func documentTypeButtonTapped(_ sender: CustomButton) {

    performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())
    print(sender.documentType)
    print(sender.requestEntity)

    }

    func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

    let languageSelected = UserDefaults().value(forKey: "language") as! String

    if let destination = segue.destination as? DocumentListTableViewController {

    destination.titlePassed = sender.documentType!.localized(lang: languageSelected)
    destination.requestedEntity = sender.requestEntity
    destination.requestedSortBy = sender.requestSortBy
    destination.requestedPredicate = sender.requestPredicate

    }

    }


    The print statements above work well and print the information. And the segue goes to the DocumentListTableViewController.



    In the viewDidLoad of the DocumentListTableViewController I added the following:



    override func viewDidLoad() {
    super.viewDidLoad()

    print(titlePassed)
    print(requestedEntity)

    }


    And the two print statements print nil.



    I guess the problem should be in the prepareForSegue, maybe with the sender... I don't know.



    Any help would be appreciated.










    share|improve this question



























      2












      2








      2








      I created a custom button to include in the button the information I need:



      class CustomButton: UIButton {   
      var urlString: String?
      var documentType: String?
      var requestEntity: String?
      var requestSortBy: [NSSortDescriptor]?
      var requestPredicate: NSPredicate?
      }


      When I create the cells in the collectionView (embedded in a tableView) I include the information in my custom button, called documentTypeButton. And also the target for executing the function HomeTableViewController.documentTypeButtonTapped(_:) to perform the segue.



      func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

      let languageSelected = UserDefaults().value(forKey: "language") as! String

      let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell

      cell.documentTypeButton.documentType = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].name
      cell.documentTypeButton.requestEntity = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].entityName
      cell.documentTypeButton.requestSortBy = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].sortBy
      cell.documentTypeButton.requestPredicate = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].predicate
      cell.documentTypeButton.addTarget(nil, action: #selector(HomeTableViewController.documentTypeButtonTapped(_:)), for: .touchUpInside)


      return cell

      }


      And the, in the HomeTableViewController I have the function to execute when touching inside the button:



      @objc func documentTypeButtonTapped(_ sender: CustomButton) {

      performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())
      print(sender.documentType)
      print(sender.requestEntity)

      }

      func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

      let languageSelected = UserDefaults().value(forKey: "language") as! String

      if let destination = segue.destination as? DocumentListTableViewController {

      destination.titlePassed = sender.documentType!.localized(lang: languageSelected)
      destination.requestedEntity = sender.requestEntity
      destination.requestedSortBy = sender.requestSortBy
      destination.requestedPredicate = sender.requestPredicate

      }

      }


      The print statements above work well and print the information. And the segue goes to the DocumentListTableViewController.



      In the viewDidLoad of the DocumentListTableViewController I added the following:



      override func viewDidLoad() {
      super.viewDidLoad()

      print(titlePassed)
      print(requestedEntity)

      }


      And the two print statements print nil.



      I guess the problem should be in the prepareForSegue, maybe with the sender... I don't know.



      Any help would be appreciated.










      share|improve this question
















      I created a custom button to include in the button the information I need:



      class CustomButton: UIButton {   
      var urlString: String?
      var documentType: String?
      var requestEntity: String?
      var requestSortBy: [NSSortDescriptor]?
      var requestPredicate: NSPredicate?
      }


      When I create the cells in the collectionView (embedded in a tableView) I include the information in my custom button, called documentTypeButton. And also the target for executing the function HomeTableViewController.documentTypeButtonTapped(_:) to perform the segue.



      func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

      let languageSelected = UserDefaults().value(forKey: "language") as! String

      let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell

      cell.documentTypeButton.documentType = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].name
      cell.documentTypeButton.requestEntity = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].entityName
      cell.documentTypeButton.requestSortBy = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].sortBy
      cell.documentTypeButton.requestPredicate = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row].predicate
      cell.documentTypeButton.addTarget(nil, action: #selector(HomeTableViewController.documentTypeButtonTapped(_:)), for: .touchUpInside)


      return cell

      }


      And the, in the HomeTableViewController I have the function to execute when touching inside the button:



      @objc func documentTypeButtonTapped(_ sender: CustomButton) {

      performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())
      print(sender.documentType)
      print(sender.requestEntity)

      }

      func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

      let languageSelected = UserDefaults().value(forKey: "language") as! String

      if let destination = segue.destination as? DocumentListTableViewController {

      destination.titlePassed = sender.documentType!.localized(lang: languageSelected)
      destination.requestedEntity = sender.requestEntity
      destination.requestedSortBy = sender.requestSortBy
      destination.requestedPredicate = sender.requestPredicate

      }

      }


      The print statements above work well and print the information. And the segue goes to the DocumentListTableViewController.



      In the viewDidLoad of the DocumentListTableViewController I added the following:



      override func viewDidLoad() {
      super.viewDidLoad()

      print(titlePassed)
      print(requestedEntity)

      }


      And the two print statements print nil.



      I guess the problem should be in the prepareForSegue, maybe with the sender... I don't know.



      Any help would be appreciated.







      ios swift xcode






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 25 '18 at 7:58









      Arie Pinto

      9041816




      9041816










      asked Nov 24 '18 at 21:13









      jRuMoLjRuMoL

      335




      335
























          3 Answers
          3






          active

          oldest

          votes


















          3














          Try to pass sender parameter in performSegue() method like this:



          @objc func documentTypeButtonTapped(_ sender: CustomButton) {

          performSegue(withIdentifier: "goToDocumentList", sender: sender)
          print(sender.documentType)
          print(sender.requestEntity)

          }


          Problem is that you are instantiating new object of type CustomButton() instead passing sender.






          share|improve this answer
























          • Still returns nil for the two print statements in the DocumentListTableViewController

            – jRuMoL
            Nov 24 '18 at 21:20











          • Try to use breakpoint if assign statements in prepare method are invoked and have proper data.

            – bezoadam
            Nov 24 '18 at 21:24





















          2














          The issue is that you pass a new (empty) instance of CustomButton in the performSegue call rather than the sender of the action.



          But your design to create a custom button as data container is still worse. Don't do that. It's horrible.



          There is a much easier and more efficient solution:



          In AllDocumentsCollectionViewCell create a callback closure



          var callback : (()->Void)?


          and an IBAction and connect it to the button, the callback is called when the button is tapped.



          @IBAction func documentTypeButtonTapped(_ sender: UIButton) {
          callback?()
          }


          In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array.



          But the way calling UserDefaults().value( in each call of collectionView and getting the same item for index path 4 times is very very inefficient. And never use value(forKey. There is string(forKey in UserDefaults.



          func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

          let languageSelected = UserDefaults().string(forKey: "language")!

          let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell
          cell.callback { [weak self] in
          let item = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row]
          self?.performSegue(withIdentifier: "goToDocumentList", sender: item)
          }
          return cell

          }


          In prepare(for get the data source item (I have no idea what type it is) and retrieve the information from there. You can even pass the entire item to the destination view controller.



          func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

          let languageSelected = UserDefaults().string(forKey: "language")!

          if let destination = segue.destination as? DocumentListTableViewController {
          let item = sender as! WhatEverTheTypeIs // change this to the real type
          destination.titlePassed = item.name.localized(lang: languageSelected)
          destination.requestedEntity = item.entityName
          destination.requestedSortBy = item.sortBy
          destination.requestedPredicate = item.predicate

          }
          }





          share|improve this answer


























          • Thank you very much for your answer. When you say "In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array." I have no idea about how to do that. I have been searching but it is difficult for me to understand it.

            – jRuMoL
            Nov 25 '18 at 14:55













          • Actually my answer contains all the code you need.

            – vadian
            Nov 25 '18 at 17:46



















          2














          In your performSegue call your are sending a new instance of CustomButton



          performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())


          So its parameters are going to be nil in the next view controller, you need to send the sender instead.



          performSegue(withIdentifier: "goToDocumentList", sender: sender)


          You need to override prepareForSegue for it to be called, no need to change to its signature, you could write it like this instead:



          override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
          let languageSelected = UserDefaults().value(forKey: "language") as! String

          if let destination = segue.destination as? DocumentListTableViewController {

          let myCustomButton = sender as! CustomButton

          destination.titlePassed = myCustomButton.documentType!.localized(lang: languageSelected)
          destination.requestedEntity = myCustomButton.requestEntity
          destination.requestedSortBy = myCustomButton.requestSortBy
          destination.requestedPredicate = myCustomButton.requestPredicate

          }
          }





          share|improve this answer


























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462424%2fperform-segue-from-a-custom-button%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            3














            Try to pass sender parameter in performSegue() method like this:



            @objc func documentTypeButtonTapped(_ sender: CustomButton) {

            performSegue(withIdentifier: "goToDocumentList", sender: sender)
            print(sender.documentType)
            print(sender.requestEntity)

            }


            Problem is that you are instantiating new object of type CustomButton() instead passing sender.






            share|improve this answer
























            • Still returns nil for the two print statements in the DocumentListTableViewController

              – jRuMoL
              Nov 24 '18 at 21:20











            • Try to use breakpoint if assign statements in prepare method are invoked and have proper data.

              – bezoadam
              Nov 24 '18 at 21:24


















            3














            Try to pass sender parameter in performSegue() method like this:



            @objc func documentTypeButtonTapped(_ sender: CustomButton) {

            performSegue(withIdentifier: "goToDocumentList", sender: sender)
            print(sender.documentType)
            print(sender.requestEntity)

            }


            Problem is that you are instantiating new object of type CustomButton() instead passing sender.






            share|improve this answer
























            • Still returns nil for the two print statements in the DocumentListTableViewController

              – jRuMoL
              Nov 24 '18 at 21:20











            • Try to use breakpoint if assign statements in prepare method are invoked and have proper data.

              – bezoadam
              Nov 24 '18 at 21:24
















            3












            3








            3







            Try to pass sender parameter in performSegue() method like this:



            @objc func documentTypeButtonTapped(_ sender: CustomButton) {

            performSegue(withIdentifier: "goToDocumentList", sender: sender)
            print(sender.documentType)
            print(sender.requestEntity)

            }


            Problem is that you are instantiating new object of type CustomButton() instead passing sender.






            share|improve this answer













            Try to pass sender parameter in performSegue() method like this:



            @objc func documentTypeButtonTapped(_ sender: CustomButton) {

            performSegue(withIdentifier: "goToDocumentList", sender: sender)
            print(sender.documentType)
            print(sender.requestEntity)

            }


            Problem is that you are instantiating new object of type CustomButton() instead passing sender.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 24 '18 at 21:17









            bezoadambezoadam

            1041210




            1041210













            • Still returns nil for the two print statements in the DocumentListTableViewController

              – jRuMoL
              Nov 24 '18 at 21:20











            • Try to use breakpoint if assign statements in prepare method are invoked and have proper data.

              – bezoadam
              Nov 24 '18 at 21:24





















            • Still returns nil for the two print statements in the DocumentListTableViewController

              – jRuMoL
              Nov 24 '18 at 21:20











            • Try to use breakpoint if assign statements in prepare method are invoked and have proper data.

              – bezoadam
              Nov 24 '18 at 21:24



















            Still returns nil for the two print statements in the DocumentListTableViewController

            – jRuMoL
            Nov 24 '18 at 21:20





            Still returns nil for the two print statements in the DocumentListTableViewController

            – jRuMoL
            Nov 24 '18 at 21:20













            Try to use breakpoint if assign statements in prepare method are invoked and have proper data.

            – bezoadam
            Nov 24 '18 at 21:24







            Try to use breakpoint if assign statements in prepare method are invoked and have proper data.

            – bezoadam
            Nov 24 '18 at 21:24















            2














            The issue is that you pass a new (empty) instance of CustomButton in the performSegue call rather than the sender of the action.



            But your design to create a custom button as data container is still worse. Don't do that. It's horrible.



            There is a much easier and more efficient solution:



            In AllDocumentsCollectionViewCell create a callback closure



            var callback : (()->Void)?


            and an IBAction and connect it to the button, the callback is called when the button is tapped.



            @IBAction func documentTypeButtonTapped(_ sender: UIButton) {
            callback?()
            }


            In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array.



            But the way calling UserDefaults().value( in each call of collectionView and getting the same item for index path 4 times is very very inefficient. And never use value(forKey. There is string(forKey in UserDefaults.



            func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

            let languageSelected = UserDefaults().string(forKey: "language")!

            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell
            cell.callback { [weak self] in
            let item = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row]
            self?.performSegue(withIdentifier: "goToDocumentList", sender: item)
            }
            return cell

            }


            In prepare(for get the data source item (I have no idea what type it is) and retrieve the information from there. You can even pass the entire item to the destination view controller.



            func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

            let languageSelected = UserDefaults().string(forKey: "language")!

            if let destination = segue.destination as? DocumentListTableViewController {
            let item = sender as! WhatEverTheTypeIs // change this to the real type
            destination.titlePassed = item.name.localized(lang: languageSelected)
            destination.requestedEntity = item.entityName
            destination.requestedSortBy = item.sortBy
            destination.requestedPredicate = item.predicate

            }
            }





            share|improve this answer


























            • Thank you very much for your answer. When you say "In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array." I have no idea about how to do that. I have been searching but it is difficult for me to understand it.

              – jRuMoL
              Nov 25 '18 at 14:55













            • Actually my answer contains all the code you need.

              – vadian
              Nov 25 '18 at 17:46
















            2














            The issue is that you pass a new (empty) instance of CustomButton in the performSegue call rather than the sender of the action.



            But your design to create a custom button as data container is still worse. Don't do that. It's horrible.



            There is a much easier and more efficient solution:



            In AllDocumentsCollectionViewCell create a callback closure



            var callback : (()->Void)?


            and an IBAction and connect it to the button, the callback is called when the button is tapped.



            @IBAction func documentTypeButtonTapped(_ sender: UIButton) {
            callback?()
            }


            In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array.



            But the way calling UserDefaults().value( in each call of collectionView and getting the same item for index path 4 times is very very inefficient. And never use value(forKey. There is string(forKey in UserDefaults.



            func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

            let languageSelected = UserDefaults().string(forKey: "language")!

            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell
            cell.callback { [weak self] in
            let item = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row]
            self?.performSegue(withIdentifier: "goToDocumentList", sender: item)
            }
            return cell

            }


            In prepare(for get the data source item (I have no idea what type it is) and retrieve the information from there. You can even pass the entire item to the destination view controller.



            func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

            let languageSelected = UserDefaults().string(forKey: "language")!

            if let destination = segue.destination as? DocumentListTableViewController {
            let item = sender as! WhatEverTheTypeIs // change this to the real type
            destination.titlePassed = item.name.localized(lang: languageSelected)
            destination.requestedEntity = item.entityName
            destination.requestedSortBy = item.sortBy
            destination.requestedPredicate = item.predicate

            }
            }





            share|improve this answer


























            • Thank you very much for your answer. When you say "In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array." I have no idea about how to do that. I have been searching but it is difficult for me to understand it.

              – jRuMoL
              Nov 25 '18 at 14:55













            • Actually my answer contains all the code you need.

              – vadian
              Nov 25 '18 at 17:46














            2












            2








            2







            The issue is that you pass a new (empty) instance of CustomButton in the performSegue call rather than the sender of the action.



            But your design to create a custom button as data container is still worse. Don't do that. It's horrible.



            There is a much easier and more efficient solution:



            In AllDocumentsCollectionViewCell create a callback closure



            var callback : (()->Void)?


            and an IBAction and connect it to the button, the callback is called when the button is tapped.



            @IBAction func documentTypeButtonTapped(_ sender: UIButton) {
            callback?()
            }


            In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array.



            But the way calling UserDefaults().value( in each call of collectionView and getting the same item for index path 4 times is very very inefficient. And never use value(forKey. There is string(forKey in UserDefaults.



            func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

            let languageSelected = UserDefaults().string(forKey: "language")!

            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell
            cell.callback { [weak self] in
            let item = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row]
            self?.performSegue(withIdentifier: "goToDocumentList", sender: item)
            }
            return cell

            }


            In prepare(for get the data source item (I have no idea what type it is) and retrieve the information from there. You can even pass the entire item to the destination view controller.



            func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

            let languageSelected = UserDefaults().string(forKey: "language")!

            if let destination = segue.destination as? DocumentListTableViewController {
            let item = sender as! WhatEverTheTypeIs // change this to the real type
            destination.titlePassed = item.name.localized(lang: languageSelected)
            destination.requestedEntity = item.entityName
            destination.requestedSortBy = item.sortBy
            destination.requestedPredicate = item.predicate

            }
            }





            share|improve this answer















            The issue is that you pass a new (empty) instance of CustomButton in the performSegue call rather than the sender of the action.



            But your design to create a custom button as data container is still worse. Don't do that. It's horrible.



            There is a much easier and more efficient solution:



            In AllDocumentsCollectionViewCell create a callback closure



            var callback : (()->Void)?


            and an IBAction and connect it to the button, the callback is called when the button is tapped.



            @IBAction func documentTypeButtonTapped(_ sender: UIButton) {
            callback?()
            }


            In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array.



            But the way calling UserDefaults().value( in each call of collectionView and getting the same item for index path 4 times is very very inefficient. And never use value(forKey. There is string(forKey in UserDefaults.



            func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

            let languageSelected = UserDefaults().string(forKey: "language")!

            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "allDocumentsItemCell", for: indexPath) as! AllDocumentsCollectionViewCell
            cell.callback { [weak self] in
            let item = Catalog.sharedInstance.allSections[allDocumentsSection!].singleItems[indexPath.row]
            self?.performSegue(withIdentifier: "goToDocumentList", sender: item)
            }
            return cell

            }


            In prepare(for get the data source item (I have no idea what type it is) and retrieve the information from there. You can even pass the entire item to the destination view controller.



            func prepare(for segue: UIStoryboardSegue, sender: CustomButton) {

            let languageSelected = UserDefaults().string(forKey: "language")!

            if let destination = segue.destination as? DocumentListTableViewController {
            let item = sender as! WhatEverTheTypeIs // change this to the real type
            destination.titlePassed = item.name.localized(lang: languageSelected)
            destination.requestedEntity = item.entityName
            destination.requestedSortBy = item.sortBy
            destination.requestedPredicate = item.predicate

            }
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 24 '18 at 21:46

























            answered Nov 24 '18 at 21:33









            vadianvadian

            157k17168193




            157k17168193













            • Thank you very much for your answer. When you say "In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array." I have no idea about how to do that. I have been searching but it is difficult for me to understand it.

              – jRuMoL
              Nov 25 '18 at 14:55













            • Actually my answer contains all the code you need.

              – vadian
              Nov 25 '18 at 17:46



















            • Thank you very much for your answer. When you say "In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array." I have no idea about how to do that. I have been searching but it is difficult for me to understand it.

              – jRuMoL
              Nov 25 '18 at 14:55













            • Actually my answer contains all the code you need.

              – vadian
              Nov 25 '18 at 17:46

















            Thank you very much for your answer. When you say "In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array." I have no idea about how to do that. I have been searching but it is difficult for me to understand it.

            – jRuMoL
            Nov 25 '18 at 14:55







            Thank you very much for your answer. When you say "In HomeTableViewController assign a closure to the callback, perform the segue in there and pass the item of the data source array." I have no idea about how to do that. I have been searching but it is difficult for me to understand it.

            – jRuMoL
            Nov 25 '18 at 14:55















            Actually my answer contains all the code you need.

            – vadian
            Nov 25 '18 at 17:46





            Actually my answer contains all the code you need.

            – vadian
            Nov 25 '18 at 17:46











            2














            In your performSegue call your are sending a new instance of CustomButton



            performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())


            So its parameters are going to be nil in the next view controller, you need to send the sender instead.



            performSegue(withIdentifier: "goToDocumentList", sender: sender)


            You need to override prepareForSegue for it to be called, no need to change to its signature, you could write it like this instead:



            override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            let languageSelected = UserDefaults().value(forKey: "language") as! String

            if let destination = segue.destination as? DocumentListTableViewController {

            let myCustomButton = sender as! CustomButton

            destination.titlePassed = myCustomButton.documentType!.localized(lang: languageSelected)
            destination.requestedEntity = myCustomButton.requestEntity
            destination.requestedSortBy = myCustomButton.requestSortBy
            destination.requestedPredicate = myCustomButton.requestPredicate

            }
            }





            share|improve this answer






























              2














              In your performSegue call your are sending a new instance of CustomButton



              performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())


              So its parameters are going to be nil in the next view controller, you need to send the sender instead.



              performSegue(withIdentifier: "goToDocumentList", sender: sender)


              You need to override prepareForSegue for it to be called, no need to change to its signature, you could write it like this instead:



              override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
              let languageSelected = UserDefaults().value(forKey: "language") as! String

              if let destination = segue.destination as? DocumentListTableViewController {

              let myCustomButton = sender as! CustomButton

              destination.titlePassed = myCustomButton.documentType!.localized(lang: languageSelected)
              destination.requestedEntity = myCustomButton.requestEntity
              destination.requestedSortBy = myCustomButton.requestSortBy
              destination.requestedPredicate = myCustomButton.requestPredicate

              }
              }





              share|improve this answer




























                2












                2








                2







                In your performSegue call your are sending a new instance of CustomButton



                performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())


                So its parameters are going to be nil in the next view controller, you need to send the sender instead.



                performSegue(withIdentifier: "goToDocumentList", sender: sender)


                You need to override prepareForSegue for it to be called, no need to change to its signature, you could write it like this instead:



                override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
                let languageSelected = UserDefaults().value(forKey: "language") as! String

                if let destination = segue.destination as? DocumentListTableViewController {

                let myCustomButton = sender as! CustomButton

                destination.titlePassed = myCustomButton.documentType!.localized(lang: languageSelected)
                destination.requestedEntity = myCustomButton.requestEntity
                destination.requestedSortBy = myCustomButton.requestSortBy
                destination.requestedPredicate = myCustomButton.requestPredicate

                }
                }





                share|improve this answer















                In your performSegue call your are sending a new instance of CustomButton



                performSegue(withIdentifier: "goToDocumentList", sender: CustomButton())


                So its parameters are going to be nil in the next view controller, you need to send the sender instead.



                performSegue(withIdentifier: "goToDocumentList", sender: sender)


                You need to override prepareForSegue for it to be called, no need to change to its signature, you could write it like this instead:



                override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
                let languageSelected = UserDefaults().value(forKey: "language") as! String

                if let destination = segue.destination as? DocumentListTableViewController {

                let myCustomButton = sender as! CustomButton

                destination.titlePassed = myCustomButton.documentType!.localized(lang: languageSelected)
                destination.requestedEntity = myCustomButton.requestEntity
                destination.requestedSortBy = myCustomButton.requestSortBy
                destination.requestedPredicate = myCustomButton.requestPredicate

                }
                }






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 24 '18 at 21:48

























                answered Nov 24 '18 at 21:36









                Arie PintoArie Pinto

                9041816




                9041816






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462424%2fperform-segue-from-a-custom-button%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    Tangent Lines Diagram Along Smooth Curve

                    Yusuf al-Mu'taman ibn Hud

                    Zucchini