How to send an event from two different view branches in SwiftUI? - swiftui

I'm building a SwiftUI app for macOS, then I came with the following challenge.
Given a view hierarchy like:
Which basically shows a collection of elements in ElementListView. Then the FiltersView is used to search new elements to possibly add to the element list, the results of that search are shown in rows like FilterRow.
When a user clicks on FilterRow, that means I want to add a new element to the ElementListView, but I am not sure of How to propagate events between the two branches of the view hierarchy in SwiftUI?
If I were to implement this in pure AppKit, I would probably use the responder chain, but I guess it's not the SwiftUI way of doing it.

You can have a shared ObservableObject for filters and list views. As soon as ObservableObject changes SwiftUI updates views connected to it.

Related

How to Order a 3 Way Tie?

I'm working on an app that involves inputting the amount of cards players ended up with, and ordering them in a list. But if theres a 2 or 3 way tie, I want the user to be able to have a menu that lets them select the order of who had the highest card to lowest card, that way I can organize the list. How do I get the user to order them, like what kind of Alert/Popup lets me do that?
Edit: Basically I was asking how to make a picker that lets you arrange multiple items into a specific order but it seems the best thing to do is just to have a stack appear with buttons for each item, where you can click them and go from there to create your order. Hope this helps for anyone in a similar situation!
For that kind of user interaction where they are doing more than just tapping an option (in your case, you want them to order the various cards), I would create your own custom view rather than use an alert or action sheet or similar.
The way you implement will depend on how you want it to look. If you want the view to appear on top of your current view (a bit like an alert does) where it only takes up the space needed for the content) then you can embed in a zStack. If you want it to slide up from the bottom as almost the same size as the full screen then you can use a sheet (sometimes also referred to as a modal).
A little difficult to explain how they look visually - if you google image search “SwiftUI sheet” then you’ll see what I mean (if you aren’t already familiar with them)
ZStack
you put your current view in a ZStack then create a new view which goes in the ZStack after it but you wrap it in an if statement so it’s conditionally shown based on a Boolean being true.
E.g.
if gameTied { ChooseSortOrderView() }
then when your game finishes - if it’s a tie, you set your Boolean to true and up pops the new view.
You can pass in the tied cards, get the user to sort them via drag and drop, form, picker (whatever you want), submit it. Then set the bool back to false to make the view go away.
sheet
The other alternative instead of using a zstack would be sheet so you get a modal view appear. Similar approach but instead of the ZStack, you use a .sheet modifier.

In Swiftui, how to minimize passing functions to sub-views

I am working on a todo app that interacts with an API to store data. My view structure looks like this (simplified):
ContentView: List of { ProjectView }
ProjectView: List of { TaskView }
The ContentView has a webServer variable that provides functions like storeTask(task: Task) and deleteTask(task: Task).
So now I want my TaskView to be able to modify tasks. The most straightforward pattern seems to provide storeTask and deleteTask to TaskView to keep the view ignorant of the implementation details. That means that I have to pass these two functions through the whole tree of sub-views: ContentView -> ProjectView -> TaskView. But then, a minor change in function signature requires a changes for every view that's part of the view hierarchy.
This feels like an inefficient pattern as it's already complex for the simple app I am building. What are other approaches? For context, I remember this same issue from working on React, and using approaches like Redux to deal with this. I'm wondering whether there's a standard approach for simplifying this in SwiftUI?
The most common architecture pattern in SwiftUI is MVVM (Model-View-ViewModel). There are many articles online explaining it, but essentially the layers break into:
Model - manage a piece of data
View - manage the UI
ViewModel - manage the data (models) to be displayed in the UI (view)
To answer your question, you would need to create ViewModel layer that manages your data and pass that ViewModel throughout your Views (as #Asperi mentioned in the comments).
Here is a great article explaining MVVM: https://matteomanferdini.com/mvvm-pattern-ios-swift/
Here is one of my Github repo's that uses MVVM Architecture in SwiftUI to make a todo-list app, similar to your project. If you take a look at the ViewModel layers you will find examples of what you're trying to do. https://github.com/ndsarno/TodoList-MVVM-Advanced

When or in which controller should i load external data?

Say i have two controllers and probably a stupid question.
UITableView -> loads cell items from external HTTP resource
UIViewController -> loads information from external HTTP resource based on the cell that was tabbed
Should i/ Does one load the data needed in 2. within the table view class 1. and send it to the view controller, or load it in the view controller class 2. that gets shown when cell has been tabbed?
NB: When a cell item is tabbed, i will be using ActivityIndicator to show a loading screen.
Your question isn't super clear.
A view controller contains a view (and subviews, like your UITableView), so many developers typically use their subclassed UIViewController as a UITableViewDataSource for a table view that it's displaying.
If you have a more complicated architecture, perhaps you can designate another object to be your table view's data source.
If you select (or tab) on a different cell in the table, you can use UITableViewDelegate methods to detect another cell was selected and then adjust the data source and reload the data.

How Can i put more of 5 tabs in a Tab Bar Controller?

:D
i'm have a storyboard with a TabBarController but when i do the relationship with my others seven view controllers in mi tab bar appears a "more" Tab, How can i put this seven tabs in one tabbar?
I´ll have to do manually? with a tabbarcontroller class? or implementing Tabbar Delegate in a uiviewcontroller, But i dont have any idea how to do this.
Thank You Soo much!
Please Help Me.
Thanks Again.
I believe Apple actively discourages people from doing this in their apps, and so do I. It is never done in the iOS itself, and I have never seen it in any third-party apps either, so users will probably be confused.
If you add more than five items to the viewControllers property, the
tab bar controller automatically inserts a special view controller
(called the More view controller) to handle the display of the
additional items. The More view controller provides a custom interface
that lists the additional view controllers in a table, which can
expand to accommodate any number of view controllers. The More view
controller cannot be customized or selected and does not appear in any
of the view controller lists managed by the tab bar controller. For
the most part, it appears automatically when it is needed and is
separate from your custom content. You can get a reference to it
though by accessing the moreNavigationController property of
UITabBarController.
Also refer this link for a possible workaround!
You can use any open source custom UITabbarControler or can create your own.
As created in this open source code. JFTabBarController a custom tabbar controller on Cocoa Controls

UITabBarController containing UISplitViewController doesn't handle rotation on iPad correctly

I’m experiencing unusual behavior on an iPad in iOS 6.1.2 when using a UITabBarController with a UISplitViewController (which has a UITableViewController for the master view controller). If I have multiple tabs, of which at least one tab contains a split view controller, and I am in landscape mode while viewing the tab that contains the split view controller, then I switch to another tab, then move to portrait mode, then press the tab that contains the split view controller, what happens next is that the master view controller (a table view controller) will display the table view over top of the detail view, when it is clearly not supposed to be there. This behavior happens only the first time the app is loaded, but is consistent behavior.
This scenario is easy to recreate by simply creating a project that is a split view application that uses an iPad device and Core Data (didn’t try it without using Core Data). After the project is created, use the storyboard and add a tab bar controller and make it the initial view controller, then add a view controller seque from the tab bar controller to the split view controller. After that, only one change is necessary in code which is to change the one line in application:didfinishLaunchingWithOptions in the AppDelegate.m:
Change the following template code:
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
To:
UITabBarController *tbc = (UITabBarController *)self.window.rootViewController;
UISplitViewController *splitViewController = [tbc.viewControllers lastObject];
Perhaps I’m breaking some iOS rules, and trying to do something I’m not supposed to? All I want to do is to be able to tab between a few different split view controllers. Suggestions?
Take a look at this Git.
https://github.com/nalyd88/DCToolkit/tree/master/DCToolkit/DCToolkit
From what I understand the problem stems from the split view controller not updating it's orientation when it's not visible.
Here a subclassed tab view controller and split view controller are used which pass the message along.
Thanks to Dylan at http://objectiveseesharp.wordpress.com/ for this solution! I just found it.