What you need to do is to use ContainerView in storyboard add containerView and in it's ViewController add your embedded one and access it like this from code
Storyboard:

We Don't have your models so I created one to showcase.
struct Folder {
var files: [String]
var folders: [Folder]?
var name: String
}
extension Folder {
static var mainDataSource: [Folder] {
return [
Folder(files: ["f1","f2","f3"], folders: nil, name: "Folder 1"),
Folder(files: ["f4","f5","f6"], folders: [Folder(files: ["foof2","foof3","foof4"], folders: nil, name: "Folder2-1")], name: "Folder2")
]
}
}
MasterVC should handle it like this:
class MasterViewController: UIViewController {
private var embedded: EmbededViewController!
@IBOutlet weak var container: UIView!
@IBOutlet weak var tableview: UITableView!
var path: String = "" // append later for titles
var selectedFolder: Folder?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "EmbeddedSeg" {
let vc = segue.destination as! EmbededViewController
embedded = vc
}
}
}
extension MasterViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 30)) //creating button just to showcase
let view = UIView()
button.setTitle( "back", for: .normal)
button.backgroundColor = .red
button.addTarget(self, action: #selector(didTapBack), for: .touchUpInside) // adding trigger on click
view.addSubview(button) // back button modify as needed
return view
}
// on back set the new selected Folder
@objc func didTapBack() {
selectedFolder = nil
tableview.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if selectedFolder != nil {
if indexPath.row > selectedFolder!.files.count - 1 { // if the indexPath pointing on folder
cell.textLabel?.text = selectedFolder!.folders?[(indexPath.row) - selectedFolder!.files.count].name // get folder name
} else {
cell.textLabel?.text = selectedFolder!.files[indexPath.row] // else get the file
}
} else {
cell.textLabel?.text = Folder.mainDataSource[indexPath.row].name // if there is no selected folder just get the name of folders/files from main
}
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if selectedFolder != nil { // if there is selected folder
return selectedFolder!.files.count + (selectedFolder?.folders?.count ?? 0) // return files and folders count
} else {
return Folder.mainDataSource.count // no selected then user main data source
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedFolder != nil { // if there is a folder
if indexPath.row > selectedFolder!.files.count - 1 { // if the clicked indexPath pointing on folder
selectedFolder = selectedFolder!.folders![(indexPath.row) - selectedFolder!.files.count] // set the selected folder with our tapped one
tableView.reloadData()
} else { // if was tapped on file just show the name
embedded.lblContents.text = selectedFolder!.files[indexPath.row]
}
} else {
var item = Folder.mainDataSource[indexPath.row] // if folder is nil then just show the item or selected folder in our case select folder only for the sake of example
selectedFolder = item
if item.files.count != 0 {
embedded.lblContents.text = item.files[0]
tableView.reloadData()
}
}
}
}
Result:

For pathing strings on top that's something else to handle based on
the object you got and adding a header to the tableView