I need advice in situation: I have several JSON where may be several types of transport are (for example, only train (first variant) or train and bus (second variant). I know that there are only 3 types of transport maximum.
So, I'd like to show info from JSON about train in first view controller, info from JSON about bus in second end etc.
How better to do: create several view controllers (for maximum variants - 3), several tabBar.items (3) and when I get data from JSON in AppDelegate I will know: "OK, I know that in that JSON info only about train and I should show only tabBar.item = "train" and work only with TrainViewController and others tabBar.items I must hide from user? Is it good experience?
Your question will have multiple solutions to achieve your goal and totally depends on what kind of UI will attract your users. But along with the UI I will also advice you to consider the app size and code complexity.
If I would have to do this, I would have done like this:
1) Use single `ViewControlller` with `SegementedControl` on top having titles of your variants.
2) Whenever user selects the `segment`,load necessary data for that variant.
3) If you are going to show that data in list format, then It would be very easy to manage your `datasource` as you can simply replace the datasource depending on the selected variant.
This is not the exact or the only solution, but IMO this will reduce app size as you will be using single ViewController instead of three and you can easily manage all your complexity in a single ViewController class.
I would go about your tab bar programmatically. I would create a new Cocoa Touch Class, calling it something like CustomTabBarController and subclassing it as a UITabBarController. Go ahead to your App Delegate file and inside of your didFinishLaunchingWithOptions function, add the following:
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = CustomTabBarController()
Now, when your app launches, your rootViewController will be this tab bar view. Now inside of your viewDidLoad in your CustomTabBarController class, you'd simple implement your viewControllers in an array, which your tab bar will show and go to when touched like so:
let trainController = UIViewController()
let trainNavigationController = UINavigationController(rootViewController: trainController)
trainNavigationController.tabBarItem.image = UIImage(named: "your_tab_icon")?.withRenderingMode(.alwaysOriginal)
trainNavigationController.tabBarItem.selectedImage = UIImage(named: "your_tab_selected_icon")?.withRenderingMode(.alwaysOriginal)
let busController = UIViewController()
let busNavigationController = UINavigationController(rootViewController: trainController)
busNavigationController.tabBarItem.image = UIImage(named: "your_tab_icon")?.withRenderingMode(.alwaysOriginal)
busNavigationController.tabBarItem.selectedImage = UIImage(named: "your_tab_selected_icon")?.withRenderingMode(.alwaysOriginal)
viewControllers = [trainNavigationController, busNavigationController]
As for the JSON part, that's a totally different ball game. There are many tutorials online and on SO. Hope this helps and points you in the right direction. Good luck!
Related
I need to do multiple language switching within the app
Need to stay in the current view after switching the language
And my entire application UI needs to be updated to see the replaced language
I found that many people's approach is to reset the root view, which means that you want to re-create the view, the data need to re-request, etc.
I think this is very unreasonable
Do not you use Notification, is there any other way?
If there is a valid link and demo reference is even better
Thank you very much
I'm not sure on how your app works, but why don't you just try something like this:
func updateLanguage() {}
You can use dictionaries to help you to easily update your content. I've made a simple example so you can understand what I'm talking about:
enum Languages {
case english
case portuguese
}
var myLabel = UILabel()
let myLabelText : [Languages : String] = [
Languages.english : "My Label",
Languages.portuguese : "Minha Etiqueta"
]
func updateLanguage(to language : Languages) {
// Updates myLabel's text in real time:
myLabel.text = myLabelText[language]
// Update other UI elements below...
}
Whenever you call the method "updateLanguage", your UI elements will change it's text value in real time, no need to reload anything or to use another "hacks", it's pretty simple and straightforward, I have this approach on my apps, and it just works.
Hopefully that helps!
Try loadView() to refresh same view controller. And add same method in other vc's viewwillappear from which u have pushed that vc .
I am trying to navigate to a UIViewController using Swift 2.3. To be more precise, I am trying to reload the UIViewController that is currently active. I do not know which view the user currently has active, so this must be defined dynamically.
I have tried several approaches, but they all result in either compile or runtime errors.
Is something like this possible?
let activeViewIdentifier = ??? // Get currently active view identifier as a string
self.performSegueWithIdentifier(activeViewIdentifier, sender:self)
You can get like this :
Objective-C :
self.navigationController.topViewController.restorationIdentifier
Swift :
self.navigationController?.topViewController?.restorationIdentifier
I think you have some issues with your architecture; it's not the best approach to reload just everything on some View Controller you can chose;
Much better way of thinking is to determine, what exactly you want to reload and add methods to reload only thus things
Anyway, if my answer hasn't assure you, consider replacing existing view controller with new and presenting it with some animation, or without it; so your general algorithm may look like this:
Get new VC from storyboard, or creating new instance, if you don't prefer to use it
Push it over your existing controller
Reload stack of navigation controller, in which you are now
you can try this
let activeViewIdentifier = self.navigationController?.childViewControllers[(self.navigationController?.childViewControllers.count)!-1]
You can use the restorationIdentifier, it's right above the Storyboard identifier and it's a UIViewController property.
let activityIdentifierStr = activeViewIdentifier?.restorationIdentifier
self.performSegueWithIdentifier(activityIdentifierStr!, sender:self)
I built a simple app to view movie listing from rotten tomatoes(as a part of learning ios development)https://raw.githubusercontent.com/koldkoder/movie_listing/master/rotten_tomatoes.gif
I am trying to add tab control. One tab would list current box office movies, and second tab to list movies out on DVD recently. Both Views are exactly same, just they get data from different api endpoint. I want to use UITabBarController to implement this functionality. But i dont want to create two duplicate Viewcontrollers, instead use one for both the purpose. What is the right way of doing this, using storyboard, and code.
This is pretty straight forward. Create one UIViewController that takes a view type param in initializer like this:
typedef NS_ENUM (NSInteger, MediaViewType) {
MediaViewTypeBoxOffice = 0,
MediaViewTypeDVD
};
- (id)initWithViewType:(MediaViewType)iViewType;
In the implementation file, handle your view & functionality based on passed view type. Then add your view controller's instances to UITabBarController:
MyMediaViewController *vc1 = [MyMediaViewController alloc] initWithViewType: MediaViewTypeBoxOffice];
MyMediaViewController *vc2 = [MyMediaViewController alloc] initWithViewType: MediaViewTypeDVD];
self.tabBarController.viewControllers = #[vc1, vc2];
I want to use a view controller from a storyboard twice (DRY!). However, in one case I'd like it to be full screen, and in other I'd like it to be roughly 3/4 of the screen (within another VC). How can I reuse it like that?
There is a great library for that. I didn't create it but I have used it: https://github.com/m1entus/MZFormSheetController
here is a partial snippet
MZFormSheetSegue *formSheetSegue = (MZFormSheetSegue *)segue;
MZFormSheetController *formSheet = formSheetSegue.formSheetController;
formSheet.transitionStyle = MZFormSheetTransitionStyleBounce;
formSheet.shouldCenterVertically = YES;
formSheet.cornerRadius = 0;
formSheet.presentedFormSheetSize = CGSizeMake(290, 290);
So the idea is that, when you segue, if you want full size then segue normally. If you want smaller size, use as I show in the snippet above. Read the readme and the example.
Instead of going on and one, I am leaving it to you to ask more question if you need further help as you try out the git project.
I'm trying to tell my modal views parent view to update its data before the user returns to the screen, but I'm having some difficulties getting the message through.
I've tried all variants of this statement:
let parent:Oversikt = self.presentingViewController as Oversikt
parent.getShifts()
//OR
let parent:Oversikt = self.navigationController.parentViewController as Oversikt
parent.getShifts()
but I keep getting EXC_BAD_ACCESS in the libswiftCore.dylib swift_dynamicCastClassUnconditional:
Can anyone help me? I apologise if this is a stupid question, I'm like most of you very new to swift. Here's an image of my storyboard. The rightmost one wants to communicate with the second leftmost one.
If this was objective-c I would recommend using delegation, but in this case it may be much easier to use NSNotificationCenter. If all you want to do is send a simple message to another view controller, that is one quite simple method.