Unable to create list of string SwiftUI from json response - swift

I have a list of remarks which I receive from an API call. I have created a loop to create TEXT from the remarks but the texts do not appear in the application. Please check the code.
I have also checked the debugger and it shows a the string present there but it doesn't create the text.
VStack{
Text("Remarks")
.padding(.horizontal, 15)
.font(.title2)
if(currentFrResponse.remarks != nil){
Text("fine")
List(currentFrResponse.remarks!, id:\.self){ currentRemark in
Text("Test")
Text(currentRemark)
.bold()
.padding()
}
}
}
debugger result
Let me know if you need any more details

I have tried this code in my project and it's working fine, as per my knowledge this issue is something else related to other component or view that you are using in the same controller, But if you want you can try creating individual view for this list and then use it.
var body: some View {
VStack{
Text("Remarks")
.padding(.horizontal, 15)
.font(.title2)
List(landmarks, id:\.self){ currentRemark in
VStack{
Text(currentRemark.name)
.bold()
.padding()
}.padding()
}
}
}

Related

Fixed View above a List View within a Navigation View

How do I get a fixed (not scrolling) view above a List view within a NavigationView in SwiftUI?
The first picture shows what I try to achive / have so far. However the second picture shos what happens if I pull down, the title slides above the fixed content.
Using offset on the List and a ZStack I got close but the NavigationView Title keeps scrolling above the fixed viewwhen pulling down on the list.
Although I thought this is a more general question, to not risk this question gets closed, here is the code I have:
NavigationView {
ZStack{
List {
/* .. */
}
.listStyle(PlainListStyle())
.offset(x: 0, y: showFilter ? 100 : 0)
if showFilter {
VStack {
HStack {
Button(action: {
}, label: {
Text("Button")
})
.padding(5)
.background(Color(red: 238/255, green: 238/255, blue: 239/255))
.cornerRadius(5)
.padding()
Spacer()
}
Spacer()
}
}
}
.navigationBarItems(trailing:
Button(action: {
// initial
self.showFilter.toggle()
// completely different, odd behaviour (navigation title never fades away)
// withAnimation{ self.showFilter.toggle() }
}) {
Image(systemName: "line.horizontal.3.decrease.circle")
}
)
.navigationBarTitle("List")
}
Offset is weak approach here, because user will not see last rows in list when filter is shown and there are items more than screen area.
You can consider variant with section as placeholder (it is sticky and not overlapped by header) for filter (maybe with some custom style for buttons), so simple demo based on your code snapshot is like below.
Tested with Xcode 12 / iOS 14
NavigationView {
List {
Section(header: Group {
if showFilter {
VStack {
HStack {
Button(action: {
}, label: {
Text("Button")
})
.padding(5)
.background(Color(red: 238/255, green: 238/255, blue: 239/255))
.cornerRadius(5)
.padding()
Spacer()
}
Spacer()
}
}
}) {
ForEach(0..<20) { i in
Text("Item \(i)")
}
}}
.listStyle(PlainListStyle())
Not sure I understood your problem, can you please share a gif/video of the problem in action?
Either way you can try putting the list and the fixed view inside the same ZStack, put the list before the fixed view and give the fixed view a position attribute.
If the ZStack is inside the NavigationView it shouldn't affect the fixed view.
The Sudo-code would, roughly, be like this -
NavigationView {
ZStack {
List ...
FixedView()
.position(x: 100, y: 100)
}
}
If this was not enough you can check out Paul Hudson's tutorial on Absolute Positioning here.
And for more help please post your code and give us a video/gif demonstration so we can understand your problem and test it beforehand :)

Swift Navigation Link problems

I am having problems with NavigationLink in Swift and iOS 14. This is a known issue, however the problem solvers that I saw, are not sufficient. I found out that when a button with a NavigationLink is initialized early, it works and when you enter the page, you have the "go back" button. However, when the navigation link is in the middle, you are not able to go back when you enter the page and must close the app to go to the main screen again.
This is the code I am using:
HStack {
Button(action: {
if let url = URL(string: "I blacked this out to make no advert here") {
UIApplication.shared.open(url)
}
}){
Text("Rate App").foregroundColor(.gray)
}.modifier(navigationButtonViewStyle())
Spacer()
// this navigation link works fine
NavigationLink(destination: HelpView()) {
Text("FAQ").foregroundColor(.gray)
}.modifier(navigationButtonViewStyle())
}.padding(.horizontal, 20)
VStack {
Text("λSET")
.font(.largeTitle)
.fontWeight(.heavy)
.bold()
.padding(.top, 50)
.onAppear(perform: prepareHaptics)
.animation(.linear)
Text("λudio System Engineer Tools")
.fontWeight(.light)
.animation(.linear(duration: 0.5))
HStack {
Spacer()
// this navigation link is not showing the go back button when pressed and directed to the new screen
NavigationLink(destination: AboutView()) {
Text("About λSET")
.fontWeight(.heavy)
.bold()
}
Spacer()
}.modifier(calcTitleViewStyle())
.padding(.top, 20)
.padding(.bottom, 60)
}
I am not sure what the problem is, but am curious what this could be. I am working on a workaround, but I would love to solve the problem at its roots.
Thanks!
Fixed it myself by explicitly setting the .NavigationBar to true to force swift to load it. This was not needed in other pages, but I am now doing to make sure IOS14 accepts it, since a few things have been changed there.

SwiftUI: Two buttons with the same width/height

I have 2 buttons in an H/VStack. Both of them contain some text, in my example "Play" and "Pause". I would like to have that both buttons have the same width (and height) determined by the largest button. I have found some answers right here at SO but I can't get this code working unfortunately.
The following code illustrates the question:
import SwiftUI
struct ButtonsView: View {
var body: some View {
VStack {
Button(action: { print("PLAY tapped") }){
Text("Play")
}
Button(action: { print("PAUSE tapped") }) {
Text("Pause")
}
}
}
}
struct ButtonsView_Previews: PreviewProvider {
static var previews: some View {
ButtonsView()
}
}
The tvOS preview from Xcode shows the problem:
I would be thankful for an explanation for newbies 🙂
Here is run-time based approach without hard-coding. The idea is to detect max width of available buttons during drawing and apply it to other buttons on next update cycle (anyway it appears fluently and invisible for user).
Tested with Xcode 11.4 / tvOS 13.4
Required: Simulator or Device for testing, due to used run-time dispatched update
struct ButtonsView: View {
#State private var maxWidth: CGFloat = .zero
var body: some View {
VStack {
Button(action: { print("PLAY tapped") }){
Text("Play")
.background(rectReader($maxWidth))
.frame(minWidth: maxWidth)
}.id(maxWidth) // !! to rebuild button (tvOS specific)
Button(action: { print("PAUSE tapped") }) {
Text("Pause Long Demo")
.background(rectReader($maxWidth))
.frame(minWidth: maxWidth)
}.id(maxWidth) // !! to rebuild button (tvOS specific)
}
}
// helper reader of view intrinsic width
private func rectReader(_ binding: Binding<CGFloat>) -> some View {
return GeometryReader { gp -> Color in
DispatchQueue.main.async {
binding.wrappedValue = max(binding.wrappedValue, gp.frame(in: .local).width)
}
return Color.clear
}
}
}
You can implement the second custom layout example in the WWDC 2022 talk https://developer.apple.com/videos/play/wwdc2022/10056/ titled "Compose custom layouts with SwiftUI" which, if I understand the question, specifically solves it, for an arbitrary number of buttons/subviews. The example starts at the 7:50 mark.
after reading hit and trial implementing SO solns etc finally resolved this issue posting so that newbies as well as intermediate can benefit
paste it and obtain equal size(square) views
VStack(alignment: .center){
HStack(alignment:.center,spacing:0)
{
Button(action: {}, label: {
Text("Button one")
.padding(35)
.foregroundColor(.white)
.font(.system(size: 12))
.background(Color.green)
.frame(maxWidth:.infinity,maxHeight: .infinity)
.multilineTextAlignment(.center)
.cornerRadius(6)
}).background(Color.green)
.cornerRadius(6)
.padding()
Button(action: {}, label: {
Text("Button two")
.padding(35)
.foregroundColor(.white)
.font(.system(size: 12))
.frame(maxWidth:.infinity,maxHeight: .infinity)
.background(Color.green)
.multilineTextAlignment(.center)
}) .background(Color.green)
.buttonBorderShape(.roundedRectangle(radius: 8))
.cornerRadius(6)
.padding()
}.fixedSize(horizontal: false, vertical: true)
Add as many as buttons inside it. You can adjust it for VStack by adding only one button in hstack and add another button in another Hstack. I gave a general soln for both VStack and Hstack. You can also adjust padding of button as .padding(.leading,5) .padding(.top,5) .padding(.bottom,5) .padding(.trailing,5) to adjust the gaps between buttons
I think the best solution is to use GeometryReader, which resizes the width of the content of the Button. However, you need to check that you set a width of the Wrapper around the GeometryReader, because otherwise it would try to use the full screen width. (depends where you use that view, or if it is your primary view)
VStack
{
GeometryReader { geo in
VStack
{
Button(action: { print("PLAY tapped") }){
Text("Play")
.frame(width: geo.size.width)
}
.border(Color.blue)
Button(action: { print("Pause tapped") }){
Text("PAUSE")
.frame(width: geo.size.width)
}
.border(Color.blue)
}
}
}
.frame(width: 100)
.border(Color.yellow)
... which will look like that.
What happens if you put a Spacer() right after the Text("Play")? I think that might stretch out the 'Play' button.
Or maybe before and after Text("Play").

Navigation bar , remove strange space

in my project i'm try to remove the ugly space between my top bar Rectangle() and my List with NavigationView.
I don't know why between those 2 View SwiftUi create space.
as you can see from the picture below once I add the NavigationView it appear a strange space.
I would like my NavigationBarITEM touch my Rectangle()
if I use the offset() it works, but it sound strange.. should be by default they are inside a VStack
Thanks
VStack{
Rectangle()
.frame(height: g.size.height/12)
.foregroundColor(.blue)
.edgesIgnoringSafeArea(.top)
NavigationView{
List{
ForEach(self.dm.storage) { item in
Text(item.airportData.aptICAO)
}
} .navigationBarItems(trailing: EditButton())
}
}
It looks like you already have NavigationView above in view hierarchy, so you don't need second one
VStack{
Rectangle()
.frame(height: g.size.height/12)
.foregroundColor(.blue)
.edgesIgnoringSafeArea(.top)
// << no additional NavigationView needed
List{
ForEach(self.dm.storage) { item in
Text(item.airportData.aptICAO)
}
} .navigationBarItems(trailing: EditButton())
}

List inside ScrollView is not displayed on WatchOs

I have a list inside a scrollview and it is not displaying below the image and the buttons. I've also tried to put the list and other items inside of a VStack and that allows me to see one item of the list at the time opposed to scrolling past the Image and buttons to show the whole list.
ScrollView{
Image(uiImage: self.image)
.resizable()
.frame(width: 80, height: 80)
.scaledToFit()
Text("\(name)")
.lineLimit(2)
HStack{
Button(action: {
print("button1")
}){
Image(systemName: "pencil")
}
Button(action: {
print("button 2")
}){
Image(systemName: "trash")
}
}
List{
ForEach(self.items, id: \.self) { item in
VStack{
Text(item.name)
.font(.headline)
.lineLimit(1)
Text(item.subname)
.font(.subheadline)
.lineLimit(1)
}
}
}
}
.navigationBarTitle(Text("Tittle"))
.edgesIgnoringSafeArea(.bottom)
Ive also tried to add .frame( minHeight: 0, maxHeight: .infinity)
to the list to force it to have its whole height and that did not work either. Any suggestions or might this be a swiftUI bug ?
EDIT
I just realized Im getting this error when scrolling:
APPNAME Watch Extension[336:60406] [detents] could not play detent NO, 2, Error Domain=NSOSStatusErrorDomain Code=-536870187 "(null)", (
{
Gain = "0.01799999922513962";
OutputType = 0;
SlotIndex = 4;
},
{
Gain = "0.6000000238418579";
OutputType = 1;
SlotIndex = 5;
}
)
Indicate some height for your List like
List{
ForEach(self.items, id: \.self) { item in
VStack{
Text(item.name)
.font(.headline)
.lineLimit(1)
Text(item.subname)
.font(.subheadline)
.lineLimit(1)
}
}
}.frame(minHeight: 200, maxHeight: .infinity)
Have you tried putting the List inside of a GeometryReader and setting the frame there?
I got the same error with UIKit. The error message is related to haptic feedback, see here.
It says that a haptic feedback could not be played, probably type 2, i.e. directionDown, see here.
Since my code does not call play(_:), it must be called by watchOS itself.
The reason for the error might be very fast scrolling, which could result in too frequent calls to play(_:) that cannot be handled properly. The docs say:
Do not call this method multiple times in quick succession. If the
haptic engine is already engaged when you call this method, the system
stops the current feedback and imposes a minimum delay of 100
milliseconds before engaging the engine to generate the new feedback.
If this is really an effect of watchOS, I guess you cannot do anything to avoid the error.