I wish to ask for suggestions how to go about how to fetch data once it is successful in a swift ui view.
Where is it best to put it? What annotation is best suited for this?
I have a map view and it fetches data first before showing marker annotations. I put it in onAppear. This may work if it is just 1 view. But if this view is used inside a TabView, then once the tab is selected, the onAppear block will be executed and will be fetched again.
What is the best way to go about this by fetching the data only once? Thoughts?
var body: some View {
TabView {
MapView(cameraUpdate: ...)
.onAppear() {
// fetch data here.
}
.onDisappear() {
}
.tabItem {
Label("tab2, systemImage: "list.dash")
}
MapView(cameraUpdate: ...)
.onAppear() {
}
.onDisappear() {
}
.tabItem {
Label("tab2, systemImage: "list.dash")
}
}
.onAppear() {
}
}
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
So you can unwrap an optional like this
if let var1 {
}
else {
}
What is the opposite for this one such that I only want to put code in the else.
Should I go with
if var1 == nil {
}
or is there something close like
if !(let var1) {
}
Thoughts?
Hi. This short code for Kingfisher goes like this
KingfisherManager.shared.retrieveImage(with: ImageResource(downloadURL: URL(string: "URL HERE")!)) { result in
switch result {
case .success(let value):
break
default:
break
}
}
I am actually interested in .success only but if i remove default it will show an error message like Switch must be exhaustive.
How to make this an if statement that goes something like this
if result == .success {
how to get value in scope here so i can use it. thoughts?
}
I am trying to avoid doing different code in swift. I already found a good library in java
https://github.com/ChristianLutz/gpcj
I was wondering if anybody has used a related library like that in Swift?
I only wish to draw the convex hull of the typhoon path in maps
Thoughts?
See sample code
@State private var citiesList: [City]?
var body: some View {
if let cities {
content(cities)
}
else {
AsyncView(
operation: { try await getData(()) },
content: { cities in
contentView(cities)
}
)
}
}
So this works ok. my issue is when adding a code above contentView(cities) since it seems this kind of closure only accepts 1 line, returning a view and does not accept any other code?
like if i add the line
citiesList = cities
contentView(cities)
it will say Type '()' cannot conform to 'View'
What is the solution for this?
Or is it possible that the "cities in" part, i can assign it to the citiesList, so that citiesList will be passed to the content(citiesList) method instead of content(cities) ?
Hi. What could be the issue with this piece of code? I only want the image to rotate 360 degrees non stop
var body: some View {
HStack {
Image(systemName: "arrow.clockwise")
.rotationEffect(Angle.degrees(360), anchor: .center)
.animation(
.linear(duration: 1.5)
.repeatForever(autoreverses: false),
value: UUID()
)
Text("Downloading ...")
}
}
Even without the value attribute in the .animation, no animation happens. Am i missing something else?
Hi. Beginner here. I am looking at bottom sheet and it is frustrating that the result is always full screen. Sure, in iPad it gets displayed as a modal dialog. I wonder why they just let it behave like that in the iPhone.
The sheet should resize. based on the contents. What is your workaround for this? Should I still use sheet? or do it some other way using something else?
I looked at .presentationDetents() but i can only set a fixed height to it. My content can be either 3,4,5,6,7... lines of Text() so my goal is to make the sheet height based on the contents inside it.
Thoughts, ideas welcome.
My navigation link looks like this
struct ContentView: View {
var body: some View {
NavigationView {
GeometryReader { geometryProxy in
NavigationLink {
EmptyView() // Any view
}
label: {
TestView(geometryProxy: geometryProxy)
.buttonStyle(.plain)
.padding(.leading, 8)
}
.buttonStyle(.plain)
.padding(.leading, 0)
}
}
}
}
And my test view looks like this
struct TestView: View {
var geometryProxy: GeometryProxy
var body: some View {
HStack {
Text("Some text here extra space on right")
.frame(maxWidth: geometryProxy.size.width * 0.85, alignment: .leading)
HStack {
Text("9.4")
.lineLimit(2)
.padding(8)
}
.frame(maxWidth: geometryProxy.size.width * 0.15)
.padding([.top, .bottom], 4)
}
}
}
Because there is some gap between the text "Some text here extra space on right" and "9.4", when that area gets tapped nothing happens. NavigationLink will only work when any text is tapped. Why is that?
What is lacking here that will make any view in the TestView cllickable, including empty space.
Hi. Beginner here.
https://github.com/lhuanyu/SwiftClipper
I am trying out Swift Clipper and when clipping arrays of CGPoint, I get the error message ClipperError(message: "Error: PolyTree struct is needed for open path clipping.")
Problem is, I cannot instantiate PolyTree class because there is no init() inside of it.
https://github.com/lhuanyu/SwiftClipper/blob/master/Sources/SwiftClipper/PolyNode.swift
Does this mean it is best I copy the whole library source code to my project so I can at least add an init() so I can instantiate it?
This is a simple method I am using to loop through each CGPoint array and union them.
func cb(_ e: [[CGPoint]]) -> [CGPoint] {
var t: [CGPoint] = []
if !e.isEmpty && e.count > 1 {
t = e[0]
var paths = Paths()
let c = Clipper()
for o in (1..<e.count) {
do {
paths.removeAll()
c.clear()
c.addPath(t, .subject, false)
c.addPath(e[o], .subject, false)
try c.execute(clipType: .union, solution: &paths)
t = paths.first ?? []
} catch {
print(error)
}
}
}
return t
}
Thoughts? Is this the only way to instantiate? By copying the source files to my project and add the init constructor there?
Or, is there a hack to forcefully add an init constructor of a lib? (Though I do not think this is possible)
Wish to ask for suggestions. My goal is to have a view where user inputs an array of strings. Depending on the number of strings, should have equal distribution of spacing between them.
E.g. 5 items. 1st item should be top, last item should be bottom while the 2nd-4th should be in between and all of them should have equal spacing.
This is what I have
import SwiftUI
struct MyView: View {
@State private var labels: [String]?
var labels = ["Great", "Major", "Strong", "Moderate", "Small"]
var colors = [.blue, .red]
HStack {
Spacer()
LazyHGrid(rows: [GridItem(.adaptive(minimum: 120))]) {
if let labels {
Group {
ForEach(labels, id:\.self) { label in
Text(label)
}
}
}
}
.frame(maxHeight: .infinity)
Rectangle()
.foregroundColor(.clear)
.background(LinearGradient(gradient: Gradient(colors: colors ?? []), startPoint: .top, endPoint: .bottom))
Spacer()
}
}
The result is not what I expected it to be. Notice the orange arrows.
If i add more strings, ["Great", "Major", "Strong", "Moderate", "Small", "Great", "Major", "Strong", "Moderate", "Small"], it becomes 2 columns. Why is that?
Maybe because the minimum value si 120? Is there a way to automatically have some formula where the minimum value is set based on the number of strings in the array?
Please see image.
I want the text "one case per million to extend". but in this scenario, it seems that the image overlay is occupying space inside the the view where the text are located
Same as "One Death Per People". I think the first line should be "One Death Per" and maybe because the image is big that it somehow is occupying its area? (But i placed the image in overlay so it should be rendered no top)
I think the word "Per" should still in in the first line.
Any idea what could be the problem?
This is my code
struct Stat: View {
var body: some View {
VStack {
Text("One Case Per People")
.frame(maxWidth: .infinity, alignment: .leading)
.font(.system(size: 19))
Text("2")
.frame(maxWidth: .infinity, alignment: .leading)
.font(.system(size: 15))
Spacer()
}
.padding(8)
.frame(minHeight: 100)
.cornerRadius(8)
.background(Color.gray)
.overlay(
Image(systemName: "person.3.fill")
.resizable()
.frame(width: 60, height: 60, alignment: .trailing)
.padding(8),
alignment: .bottomTrailing
)
}
}
I used a grid to display them
ScrollView {
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())]) {
Stat()
Stat()
Stat()
Stat()
}
}
}
Thoughts?
Hi. this is my sample code
import Foundation
var features = [[String: Any]]()
var geo = [String: Any]()
geo["type"] = "FeatureCollection"
geo["features"] = features
let geoJson = try? JSONSerialization.data(withJSONObject: String(data: geo, encoding: .utf8)!, options: [])
Why does the error message say Cannot convert value of type '[String : Any]' to expected argument type 'Data'
I am going to use the data in the GMUGeoJSONParser(data: ...) in maps ios utils
I went back to square one since the NavigationLink isActive is deprecated, this is when I found out about NavigationSplitView which removes the hassle of creating a 2 column app.
However, I can never figure out why the toggle button does not show. I copied this sample code (already tried 2 tutorials, copy pasted them but still no toggle button)
Anyone know why?
import SwiftUI
enum DemoScreen: String, Codable {
case first, second, third
var title: String {
rawValue.capitalized
}
}
struct ContentView: View {
@State
private var selection: DemoScreen? = .first
var body: some View {
NavigationSplitView {
sidebarContent
} detail: {
detailContent
}
}
}
extension ContentView {
var sidebarContent: some View {
List {
link(to: .first)
link(to: .second)
link(to: .third)
}
}
func link(to page: DemoScreen) -> some View {
NavigationLink(value: page) {
Text(page.title)
}
}
}
extension ContentView {
@ViewBuilder
var detailContent: some View {
if let selection = selection {
detailContent(for: selection)
.buttonStyle(.bordered)
} else {
Text("No selection")
}
}
@ViewBuilder
func detailContent(for screen: DemoScreen) -> some View {
switch screen {
case .first: Button("First button") {}
case .second: Button("Second button") {}
case .third: Button("Second button") {}
}
}
}
Why is there no toggle button above? And why is the menu always showing? I cant see the detiail view anymore
I am testing this in playground. I have no clue why this url does not work? nil is returned.
print(URL(string: "http://202.90.159.177/geoserver/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=true&LAYERS=Boundary:Boundary_Province&TILED=true&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&STYLES&BBOX=%f,%f,%f,%f"))
The cause is &BBOX=%f,%f,%f,%f
but i do not understand why that full url doesnt work if that is included. Going to use this in GMSURLTileLayer in ios maps utils.
I have seen posts about this error message but i am making a new one because my case is different. the json is valid. so i have no clue why it gives out this error.
Sample json here
i removed the forward slash so it will be clean since when i do a print() it always shows as "key": "value"
this is the code i use to convert it to data then it gives out that error. i checked the json in online json validator sites and it's good.
let string = the json string from the url above
let jsonObject = try? JSONSerialization.data(withJSONObject: string, options: [])
It is supposed to be a json array. any idea why the error?