How to re-create a mainstoryboard if needed - ios

I am creating a notecards app and I need to be able to make a new notecard as many times as I want. I want to do this so the user is not limited to an amount of note cards. I need to know how I would create a new view controller (or note card) if they want. So they creating page can be the same but the new note card cant be the same view as the last note card otherwise it wont be the new one they created. To get to the point I am trying to create a new view for a new notecard that was created.

Think of a scene in a storyboard as a template. When you invoke a view controller from a storyboard, you get a new copy.
So say your app has a master view controller with a "create note card" button on it. You could connect that button to an IBAction that instantiates and displays a new copy of your note card view controller. The IBAction method might look like this:
#IBAction func createNoteCard(UIButton sender)
{
//Create a new instance of a Note card view controller
let newCard =
self.storyboard.instantiateViewControllerWithIdentifier("NoteCard")
//Put your code to configure the view controller here.
//Display the new note card view controller to the screen
self.presentViewController(newCard, animated: true)
}

It is very common to have one design used multiple times. I think it's more logical to create one viewController, and pass it data based on which notecard is selected, or a blank dataset when a new card is "created". This is a common design for use with a UITableView (listing your notecards), which when clicked on, opens the particular card selected. The detail (notecard) view is always the same view, but you pass it different data.

Related

SwiftUI - Updating a Page View Controller with a new page

I'm building a weather app that is hosted on a public repo here.
The most important files for this issue are the PageView and the RepresentedPageViewController.
I've created a UIPageViewController that interfaces with SwiftUI via UIViewControllerRepresentable. It allows a user to swipe through different cities and see each city's weather data, much like Apple's Weather app. When the makeUIViewController method of my page view controller is called I set its view controllers (there are 3 in this case to begin with, where each represents a city):
pageViewController.setViewControllers([controllers[0]],
direction: .forward,
animated: false)
This works fine and I'm able to navigate (swipe) between the different pages.
In the app's search menu, a user can then tap on a new city that they want to get the weather for. This adds the new city to the app's datasource of cities that the page view controller uses to create a page for each city.
Because the data object that holds the cities is stateful, the UI is recomputed when that object is set (when a user adds a new city). This triggers the updateUIViewController method in the page view controller. In this method, I reset the page view controller's viewcontrollers (there are now 4 because the user has added a new city):
func updateUIViewController(_ uiViewController: UIPageViewController, context: UIViewControllerRepresentableContext<RepresentedPageViewController>) {
// Check that the view controllers of the page view controller need to be reset.
// This is true when a user has added a new city because we'll create a new
// view controller to be added to the page view controller. We perform this check because
// we don't want to reset the viewcontrollers in all cases where the updateUIViewController method is called.
if shouldResetControllers {
uiViewController.setViewControllers([controllers[0]],
direction: .forward,
animated: false)
shouldResetControllers = false
}
}
My issue is that once this is done, the user is only able to see the first city of the viewcontrollers. The page view controller is still there because the user is still able to swipe, but there is only one city (the first one). I've created a screen recording of the result which you can view here.
think the problem stays in the Coordinator:
when you update controllers in pageviewcontroller, the parent property of Coordinator remains the same (and because it is a struct, all his properties). So you can simply add this line of code in your updateUIViewController method:
context.coordinator.parent = self
also, remember that animation of pageViewController.setViewControllers will occur, so you have to set animated to false, or handle it properly.
There are many other ways to solve this (I wrote the most intuitive solution),
the important thing is to know where the error comes from.
It seems like this is a SwiftUI bug. I had a similar problem where a UI update would reload the PageViewController with a single ViewController.
Adding an id to the PageViewController, described in "Updating an #Environment to pass data to PageViewController in SwiftUI results in loss of swiping between ViewControllers", seems to work.

Swift Make Animation to look like going to new ViewController without having One

I want to create a small side-feature to display the Files of a Server so a small FileExplorer.
I have one TableViewController (incl. NavigationController) where I diplay all Files of the current Directory.
If I tap on a Folder my intend it to go to the Subfolder and view its Content.
My Problem is that I cant create another TableViewController, because I don't know how much I would need, maybe hundred, because I can't know how many Subfolders are on the Server.
Does anyone know how I can make a kind of Animation so it looks like a new ViewController (incl. Back Button!) and simply reload the TableView with the new Data while animating?
If the user taps on a folder you can simply instantiate a new DownloadsViewController, set its properties so that it displays from the selected folder and then push that new instance onto your navigation controller.
Something like:
if let newVc = self.storyboard?.instantiateViewController(withIdentifier: "files") as? DownloadViewController { // The identifier must match the Storyboard ID for the scene in your storyboard
newVC.rootFolder = selectedFolder // You haven't shown your code, but this will be the folder from the array driving your tableview
self.navigationController?.pushViewController(newVC, animated: true)
}
In a comment you said "I am using an Navigationcontroller as mentioned above, but I'm trying to make a file Explorer so I would need to add unlimited Pages to the Storyboard".
You don't ned to have unlimited pages in your storyboard. Don't use segues. When you are ready to drill down into another level of your file hierarchy, use instantiateController(withIdentifier:) to create a new instance of your view controller, install your data into it, and push it onto your navigation controller.
It makes no sense to create an animation that looks like a view controller push, but isn't really. You DO want to push a new instance of your folder contents view controller.

how can I second time show my view controller without calling viewdidload?

here is my scenario case.
Initially for going to this VC without loading is hidden.when I click to first view controllers button it goes to second view controller.When I click button from secondVC it come back to first one and for going to this VC without loading button is now visible.Now when I click for going to this VC without loading I want to show my second view controller without reload because my previous loaded data for second view controller is needed.So how can I do that?
the actual scenario of my app look like this.My first VC
and the second one.
It's a picture of sound cloud but the case is same.
First possible solution,
Add SecondViewController as child view controller of FirstViewController using container view in Storyboard.
Every time you want to remove SecondViewController just hide/remove it with custom animation block.
Keep the reference of SecondViewController in FirstViewController
Second possible solution,
Create shared data object.
Then you can use that shared data object in any view controller, regardless of saving the state of any view controller.
I would create an object where i put the data und pass this from ViewController to ViewController by properties. Maybe this is to simple but it should work.

Why performSegueWithIdentifier creates always a new instance?

I have 3 view controller: containerViewController, questionViewController, answerViewController.
How can I swap question and answer, without to create a new instance from the view controllers? So if one is created, use that one.
Usually I swap between them like this:
containerViewController!.performSegueWithIdentifier("question", sender:self)
but this always creates a new instance.
Yes, it always will create a new instance. have no doubt for that. Because that command equal to create a new object and push it (or present it).
there's a lot of way to walkthrough it. In my case, i usually create questionViewController with an button, and by that button, it will present answerViewController. And answerViewController will have a button to dismiss. I think you can try it.

RESideMenu show selected item

I'm using this for the menu in my app: https://github.com/romaonthego/RESideMenu and I want to be able to show the selected item in order to make it more clear which view the user is currently on. Would I be able to do this in the cellForRowAtIndexPath method?
RESideMenu controller is a container controller like UITabBarController or UISplitViewController. That means that you specify content view controllers (in case of RESideMenu: content (front), right menu and left menu view controllers) and let container controller handle their display in a way that controller wants. That means that you can track which view controller you supplied to RESideMenu and highlight your cells depending on that information.
For example, you can associate a view controller instance with each menu cell and then:
if (cellBackingObject.viewController == reSideMenu.contentViewController)
{
// highlight cell
}
else
{
// don't highlight cell
}
Note, that you should reasonably manage view controller's life, because storing all of them in memory is not always good.

Resources