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
Post
Replies
Boosts
Views
Activity
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
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?
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?
All posts i came across instructs the user to import the objective c files into the swift project so that a bridging header file can be created to expose it.
Does this mean i have to instead download the objective c library, extract and copy all the files to the swift project? where the prompt to create the bridging header will be triggered?
Or is there a way to install the objective c library via cocoapods and manually trigger to create the bridging header to make it usable?
I prefer the latter, if it is possible?
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)
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. 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.
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. Please see screenshot. Currently the icon placeholder is small. What I am trying to replicate is to have an area (the one in red) where the place holder icon is in the middle horizontally and vertically.
That same red area is where the downloaded image will be drawn. I think the term for this is aspect ratio if i am not mistaken? That the height should be proportionate based on the width.
I am using Kingfisher to load the image. This is what I have.
KFImage.url(URL(string: ""))
.placeholder {
HStack {
Image(systemName: "photo")
.resizable()
.frame(width: 50, alignment: .center)
.background(.red)
}
.background(.yellow)
.scaledToFit()
}
.fade(duration: 0.25)
.onFailure { error in print("Load image error : \(error) = \(earthquakeDetail.imgUrl)")
}
.resizable()
.aspectRatio(contentMode: .fill)
Based on the screenshot image, the area for HStack is so thin with its height being small. My goal is to create an area like the one in red border.
Thoughts?
The title might be confusing but here is an example data to give a clear understanding
struct City {
var name: String?
var businesses: [Business]?
}
So if i have a city array, i wish to merge the businesses array based on the city name since the city may have duplicates e.g.
[
{
name: "CIty 1"
businesses: [
{ name: "Business 1" },
{ name: "Business 2" },
]
},
{
name: "CIty 2"
businesses: [
{ name: "Business 1" },
{ name: "Business 2" },
]
}
{
name: "CIty 1"
businesses: [
{ name: "Business 3" },
{ name: "Business 4" },
]
}
]
In the data example above, there are 2 entries of City1. i am looking for a way to not have to use a dictionary, if it is possible to use the existing array and output it such that there is only 1 entry of City but will contain 4 entries of business.
Thoughts?
This is my current view. Instead of a List, I use a LazyVStack wrapped under a ScrollView.
.onAppear does not seem to work here. I assumed it runs when the view is visible on the screen.
My goal is when the footer is visible, it always runs a Task.
What could be wrong?
@State private var cities: [City]?
@State private var index = 0
@State private var showFooter = true
func content(_ cities: [City]) -> some View {
return GeometryReader { geometryProxy in
ScrollView {
LazyVStack(alignment: .leading, spacing: 0) {
if cities.count > 0 {
ForEach(cities) { city in
HStack {
Text(city.header)
.bold()
.foregroundColor(.white)
.textCase(.uppercase)
.padding(.all, 8)
Spacer()
}
.background(Color(UIColor(named: PrefTool.instance.getBoolean(Keyword.DARK_MODE) ? "DarkerGray" : "DarkGray")!))
ForEach(city.businesses) { busines in
Text(business.name)
Divider()
}
}
}
else {
Text("Empty List")
}
}
.safeAreaInset(edge: .bottom, spacing: 0) {
if showFooter {
VStack {
Text("Footer")
}
.padding()
.frame(maxWidth: .infinity)
// The background will extend automatically to the edge
.background(Color.green)
.onAppear {
Task {
do {
let moreList = try await getMoreCities(index)
showFooter = false
if !moreList.isEmpty {
cities?.append(contentOf: moreList)
showFooter = true
}
} catch {
showFooter = false
}
}
}
}
}
}
}
}
This is used inside body
var body: some View {
content(cities)
}
Thoughts? What is a good way to show a footer and then run a task when it is visible in the screen.
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 all. Came here as a last resort. All the samples provided that I came across are not in SwiftUI.
Google's documentation is also outdated since they do not provide any samples or tutorial to do so in SwiftUI.
While showing the map in SwiftUI requires you to extend a UIViewRepresentable, i have no clue how to apply the custom info window with it.
Anyone got suggestions?
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?