Swift - How to Call and Show XIB/StoryBoard inside from XIB?

Hi!

I got confused while I am trying to achieve showing a xib or storyboard view inside of a xib view.

I have a table filled with ViewCell xibs and every one of them has buttons for playing podcasts.

When the user clicks the "play button", I want to show a full-screen player view top of the screen, like an alert notification with a close button, play button, volume slider, etc.

If I create and show the player view inside of the cell xib, it only shows up to the size of a cell. I want to show the player view full-screen.

Thus, I created another xib file and put the play button, volume slider, etc. in that file.

But I can't call or show the player view xib from the table cell xib.

How can I achieve this? How do I reach another xib file inside of a xib file?

I tried this :
Code Block swift
let podcastViewCell = (UINib(nibName: "PodcastViewCell", bundle: nil), forCellWithReuseIdentifier: "PodcastViewCell")

But couldn't get any value from this for now.

Also, do you suggest using a storyboard view for showing it in xib? If so, I could use storyboard view too but I still need help calling it.
Answered by oguzhanvarsak in 675788022
I have found the answer by using delegates. Now I can hide/unhide (edit, overall) the view's properties. This was the problem answered by Sh_Khan:

Problem is here

Code Block
DetailViewController().setupPodcastPlayer(link: url)

This DetailViewController() is a new instance not the presented one , hook the real shown one and change it's attribute as needed through delegate or a notification if you need to
I have declared a delegate in PodcastViewCell:
Code Block swift
var delegate: PodcastViewCellDelegate?


and its protocol for passing data :
Code Block swift
protocol PodcastViewCellDelegate {
    func podcastButtonClicked(podcastUrl: String)
}


In the View Controller, I want to edit element from, added this :
Code Block swift
extension DetailViewController: PodcastViewCellDelegate {
    func podcastButtonClicked(podcastUrl: String) {
        setupPodcastPlayer(link: podcastUrl)
        podcastPlayerView.isHidden = false
    }
}


Now my player works as expected and I can hide/unhide my UIView!

Thank you for all of your efforts again! Hope to see you in another thread 😅
I would not addSubview in the cell, but instantiate the player view (from its nib) and present it modally from the cell.

When you close the player, dismiss its view.
I am having issues with presenting the nib cell. I want to show the player view when the play button pressed. But couldn’t get how to reach that nib.
Could you explain.

I am having issues with presenting the nib cell

Cell is defined in a nib, PodcastViewCell, exact ?

What issue exactly ? You just display the cell in the tableView.
So, you should have registered the cell, in viewDidLoad (where the table view is):

Code Block
override func viewDidLoad() {
super.viewDidLoad()
let nib = UINib(nibName: "PodcastViewCell", bundle: nil) 
tableView.register(nib, forCellReuseIdentifier: "PodcastViewCell")

Assuming you have defined an IBOutlet (tableView) for the UITableView or that your class is a UITableViewController

Does this part work OK ?

If so, could you show how you call now the player ?
Yeah, this is actually my question.

I still have "PodcastViewCell" as Table View Cell, like in my previous question. Now, I want to show "PlayerViewCell" (a full-screen player view I recently added) when the "Play" button in the "PodcastViewCell" nib is pressed.

Or should I just add a View to the storyboard then just change its visibility? Or should I do something else?
I've achieved to play my player outside of the xib, in my view controller as you suggested earlier. Thanks for the idea again!

Then I created a container view for the playerViewCell nib on my storyboard for the player and marked it as hidden. When I try to unhide it with
Code Block swift
podcastView.isHidden = false


I always get

Code Block debugger
"Unexpectedly found nil while implicitly unwrapping an Optional value"


I don't know why it isn't loaded even tho the controller's other elements (like play button, etc.) on the screen.

(Even tried to use dummy UIView and just unhide it but still got the same error.)
Good to see you solved a first problem.

Are you sure you have properly connected the podcastView to its IBOutlet ?

To be sure:
  • if not connected, connect it

  • if connected, unconnect

  • then reconnect

  • and do an option clean build folder.

I am able to hide/unhide the view in general when I try to do it on most functions. But I get the error when I try to do it on one specific function: the function I call from nib file. I don’t know what is the issue but I think this usually happens if I try to change an element’s properties before loading it. But all of the other elements are loaded when I call the function, like play button or podcast title label.
Please show the code where you try to unhide. Show the complete code, not only one line.
You should show the full code of the class.
My view controller for podcasts table, now it plays the podcast too.
Code Block swift
class DetailViewController: BaseViewController {
    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet weak var podcastPlayerView: UIView!
    var podcastLink: String = ""
    static var itemId = "0"
    var player: AVPlayer?
    var playerItem: AVPlayerItem?
    var timeObserverToken: Any?
    var played = false
    override func viewDidLoad() {
        super.viewDidLoad()
        "self.podcastPlayerView.isHidden = false" "<-------- Unhiding process successful in this step"
    }
    override func viewWillDisappear(_ animated: Bool) {
        showPodcastButton = false
        player?.pause()
        player?.replaceCurrentItem(with: nil)
        player = nil
    }
    func setupPodcastPlayer(link: String) {
        player?.pause()
        player?.replaceCurrentItem(with: nil)
        player = nil
        if !played {
            if link != "" {
                playerItem = AVPlayerItem( url:NSURL( string:link )! as URL )
                player = AVPlayer(playerItem:playerItem)
                player!.rate = 1.0;
                player!.play()
                played = true
                didPlayedOnce = true
                podcastPlay()
            } else {
                "link empty"
            }
        } else {
            player?.replaceCurrentItem(with: nil)
            played = false
        }
    }
    func podcastPlay() {
self.podcastPlayerView.isHidden = false "<---- If I try to unhide here, app crashes."
"Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value"
    }
}


The "Play Button" action from PodcastViewCell, where I call ViewController's player function. This only passes the cell's podcast link.
Code Block swift
@IBAction func playPodcast(_ sender: Any) {
        NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
        if let itemOffset = DetailViewController.allItems?.itemListv2.firstIndex(where: {$0.itemId == itemAuthor?.itemId}) {
        podcastLink = DetailViewController.allItems?.itemListv2[itemOffset].podcastsound
        }
let url = podcastLink ?? " "
        requestAuthorDetailViewController.setupPodcastPlayer(link: url)
}


I do not see
       podcastView.isHidden
in this code.
Where is it ? Did you replace by something different ?
The comments on lines 50 and 16 are for that purpose.

Named podcastView as podcastPlayerView
I can easily hide/unhide the podcastPlayerView in viewWillAppear, or a function calling in the viewWillAppear. But after the load, if any function tries to hide/unhide the view, the application crashes. It's like the view gets destroyed after load. Searched for a force loading method but couldn't find anything working for me. One of them was adding this to viewDidLoad() but I still can't reach the podcastPlayerView

Code Block swift
view.addSubview(podcastPlayerView)

Are you sure podcastPlayerView is connected to its IBOutlet correctly ?
I think so. If it didn't connect correctly, I wouldn't hide or unhide the view in viewDidLoad right? I see the view controller's name is correct under Referencing Outlets when I right click the view but still tried removing and then adding the connection again but no use.
Accepted Answer
I have found the answer by using delegates. Now I can hide/unhide (edit, overall) the view's properties. This was the problem answered by Sh_Khan:

Problem is here

Code Block
DetailViewController().setupPodcastPlayer(link: url)

This DetailViewController() is a new instance not the presented one , hook the real shown one and change it's attribute as needed through delegate or a notification if you need to
I have declared a delegate in PodcastViewCell:
Code Block swift
var delegate: PodcastViewCellDelegate?


and its protocol for passing data :
Code Block swift
protocol PodcastViewCellDelegate {
    func podcastButtonClicked(podcastUrl: String)
}


In the View Controller, I want to edit element from, added this :
Code Block swift
extension DetailViewController: PodcastViewCellDelegate {
    func podcastButtonClicked(podcastUrl: String) {
        setupPodcastPlayer(link: podcastUrl)
        podcastPlayerView.isHidden = false
    }
}


Now my player works as expected and I can hide/unhide my UIView!

Thank you for all of your efforts again! Hope to see you in another thread 😅
Swift - How to Call and Show XIB/StoryBoard inside from XIB?
 
 
Q