Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 10 months ago.
Improve this question
I want to show/hide progress view in swiftUI globally. I have api class for api calling but I want to show progressview when api calling.. how can I do that
class NetworkManager: NSObject {
static let shared = NetworkManager()
//MARK:- ======== FETCH API DATA =========
func fetchAPIData(url:String,
isShowHUD:Bool){
headerDic["timezone"] = TimeZone.current.identifier
if isShowHUD {
// I want to show progressview from here top of the screen.
}
**api calling code.**
}
}
}
Here if I pass isShowHUD then show progress view on top of the screen. if any error or got the response then it hide the progressview.
Please help me on that.how can I achieve in swift ui.I am in new in swift UI.
You'd need to add a ProgressView and you'd need a variable to notify when loading has finished when it's successful. Documentation on ProgressView can be found here. Without giving you the full answer he's a simple solution to add a ProgressView when doing some kind of network request.
class Network: ObservableObject {
#Published var loading = true
func fetchapidata() {
/*
Network request goes here, is successful change loading to false
*/
self.loading = false
}
}
struct ContentView: View {
#StateObject var network = Network()
var body: some View {
NavigationView {
List {
/*
Details go here
*/
}
.overlay {
if network.loading {
ProgressView("Loading")
}
}
.listStyle(.plain)
.navigationTitle("Title")
}
.navigationViewStyle(.stack)
.onAppear {
network.fetchapidata()
}
}
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 months ago.
Improve this question
I want to print the name of each swiftUI but on run time if it’s possible
Im trying to print out the name of a swiftUI view like on swift type(of:) but nothing. Any idea?
try something like this, to ...get the name of a SwiftUI view programmatically:
struct MyView: View {
#State var viewName = ""
var body: some View {
Text(viewName)
.onAppear {
viewName = "\(Self.self)"
}
}
}
Or simply:
struct MyView: View {
let viewName = "\(Self.self)"
var body: some View {
Text(viewName)
}
}
I have a view which displays a list of posts. I have implemented infinite scrolling, and it is functioning properly. however, there is one small problem I am running into, and attempts to solve it have me going round in circles.
Main view
struct PostsHomeView: View {
#EnvironmentObject var viewModel: ViewModel
#State var dataInitiallyFetched = false
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 0) {
if self.viewModel.posts.count > 0 {
PostsListView(posts: self.viewModel.posts,
isLoading: self.viewModel.canFetchMorePosts,
onScrolledAtBottom: self.viewModel.fetchMorePosts
)
} else {
VStack {
Text("You have no posts!")
}
}
}
.onAppear() {
if !self.dataInitiallyFetched {
self.viewModel.fetchMostRecentPosts()
self.dataInitiallyFetched = true
}
}
.navigationBarTitle("Posts", displayMode: .inline)
}
}
}
List view
struct PostsListView: View {
#EnvironmentObject var viewModel: ViewModel
let posts: [Post]
let isLoading: Bool
let onScrolledAtBottom: () -> Void
var body: some View {
List {
postsList
if isLoading {
loadingIndicator
}
}
}
private var postsList: some View {
ForEach(posts, id: \.self) { post in
PostsCellView(post: post)
.onAppear {
if self.posts.last == post {
self.onScrolledAtBottom()
}
}
}
.id(UUID())
}
}
Problem
Upon tapping one of the posts in the list, I am taken to a detail view. When I tap the nav bar's back button in order go back to the posts list, the whole view is reloaded and my post fetch methods are fired again.
In order to stop the fetch method that fetches most recent posts from firing, I have added a flag that I set to true after the initial load. This stops the fetch method that grabs the initial set of posts from firing when I go back and forth between the details view and posts home screen.
I have tried various things to stop the fetchMorePosts function from firing, but I keep going in circles. I added a guard statement to the top of the fetchMorePosts function in my view model. It checks to see if string is equal to "homeview", if not, then the fetch is not done. I set this string to "detailview" whenever the detail view is visited, then I reset it back to "homeview" in the guard statement.
guard self.lastView == "homeview" else {
self.lastView = "homeview"
return
}
This works to an extent, but I keep finding scenarios where it doesn't work as expected. There must be a straight-forward way to tell SwiftUI not to reload a view. The problem is the method sits in the onAppear closure which is vital for the infinite scrolling to work. I'm not using iOS 14 yet, so I can't use #StateObject.
Is there a way to tell SwiftUI not to fire onAppear everytime I return from a detail view?
Thanks in advance
The culprit was .id(UUID()). I removed it from my list and everything worked again.
Thanks Asperi. Your help is much appreciated.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Confused between TupleView and AnyView, Can anyone explain in detail TupleView and AnyView?
AnyView is a type-erased View. It is necessary for overcoming some of the type system limitations. For example, the following does not compile:
import SwiftUI
struct SomeView: View {
#State private var showText: Bool
var body: some View {
if showText {
return Text("This is text.")
} else {
return Rectangle()
}
}
}
This is because some View requires that the same concrete View type is returned in every possible case. We can't return Text in one case and Rectangle or whatever else in another.
We can't use View (without some) either, as protocols with associated types can't be used as a concrete type.
This is where AnyView comes to the rescue:
import SwiftUI
struct SomeView: View {
#State private var showText: Bool
var body: some View {
if showText {
return AnyView(Text("This is text."))
} else {
return AnyView(Rectangle())
}
}
}
In general, you can use AnyView whenever you want to hide a concrete type and just return View. This is not unique to SwiftUI. AnyCollection, AnySequence etc. play the same role.
TupleView is a concrete View type uses to store multiple View values. It's rarely used, mostly by library developers for implementing view builders, something like this:
struct MyView: View {
init<C0, C1>(
#ViewBuilder _ content: #escaping () -> TupleView<(C0, C1)>
) where C0: View, C1: View {
let content = content().value
// do something with content
}
// implement the rest of the view
}
MyView can now be used with the special syntax, like this:
MyView {
View1()
View2()
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am new to MVVM. How should I update the data model in parent view model from child view model?
As an example, suppose I have a CollectionViewModel for a Newsfeed page, it keeps an array of Post (my date model) and an array of CollectionCellViewModel that corresponds to individual posts. Each cell makes network request to listen for new likes. How can I pass this information back to CollectionViewModel and update Post?
You achieve that with multiple ways:
Delegation pattern:
protocol CollectionCellViewModelDelegate {
func onAction()
}
class CollectionCellViewModelDelegate: YourType {
var delegate: CollectionCellViewModelDelegate?
/// Your custom action
func yourCustomAction() {
delegate?.onAction
}
}
then assign .delegate in your parent class and implement onAction() method
Closures:
class CollectionCellViewModelDelegate: YourType {
var yourAction: (()->())?
func yourAction(_ completion: (()->())?) {
yourAction = completion
}
/// Your custom action
func yourCustomAction() {
yourAction?()
}
}
then call your closure with following code from parent class:
child.yourAction { // do custom stuff }
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
How can I use a class function I implement to perform a segue if the class it is held in is not connected to a viewController?
In order to perform a segue, you need the instance of view controller where the segue originates from - for example:
class MyViewController {
}
class MyClass {
showNextView(fromViewController: UIViewController) {
fromViewController.performSegueWithIdentifier("segue_id", sender: fromViewController)
}
}
However I discourage this kind of interaction. Don't tell the view controller how to show a view - let it do on its own, and just ask it.
So, I suggest creating an instance method in your view controller:
class MyViewController {
...
func goToNextView() {
performSegueWithIdentifier("segue_id", sender: self)
}
}
and use that to make the transition:
class MyClass {
showNextView(fromViewController: MyViewController) {
fromViewController.goToNextView()
}
}
You can instruct the currently visible view controller to segue using "performSegueWithIdentifier".
You obviously need a reference to the visible controller.
Inside your method use:
currentViewController.performSegueWithIdentifier("push", sender: currentViewController)