Load image from sever inside image slider using swiftUI - xcode

I am trying to load image from server in a slide show with SwiftUi but image is not loading in the slide show. please see my code below
import SwiftUI
import Combine
struct ImageCarouselView<Content: View>: View {
private var numberOfImages: Int
private var content: Content
#State private var currentIndex: Int = 0
private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
init(numberOfImages: Int, #ViewBuilder content: () -> Content) {
self.numberOfImages = numberOfImages
self.content = content()
}
var body: some View {
GeometryReader { geometry in
// 1
ZStack(alignment: .bottom) {
HStack(spacing: 0) {
self.content
}
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .leading)
.offset(x: CGFloat(self.currentIndex) * -geometry.size.width, y: 0)
.animation(.spring())
.onReceive(self.timer) { _ in
self.currentIndex = (self.currentIndex + 1) % (self.numberOfImages == 0 ? 1 : self.numberOfImages)
}
// 2
HStack(spacing: 3) {
// 3
ForEach(0..<self.numberOfImages, id: \.self) { index in
// 4
Circle()
.frame(width: index == self.currentIndex ? 10 : 8,
height: index == self.currentIndex ? 10 : 8)
.foregroundColor(index == self.currentIndex ? Color.blue : .white)
.overlay(Circle().stroke(Color.gray, lineWidth: 1))
.padding(.bottom, 8)
.animation(.spring())
}
}
}
}
}
}
and in my view
struct MainView: View {
#Binding var showMenu: Bool
#State var index = 0
var body: some View {
ScrollView {
//MainView(with:"https://govcard.net/banners/banner1.jpg")
GeometryReader { geometry in
ImageCarouselView(numberOfImages: 3) {
Image("image_carousel_1")
.resizable()
.scaledToFill()
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
Image("image_carousel_2")
.resizable()
.scaledToFill()
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
Image("image_carousel_3")
.resizable()
.scaledToFill()
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
}
}.frame(height: 200, alignment: .center)
}
i want to use url instead of asset image.

As far as I've seen the easiest way would be to add the Kingfisher Swift package to your project.import KingfisherSwiftUI to your swift file and use the KFImage(myUrl).
import KingfisherSwiftUI
struct MainView: View {
//...
KFImage(URL(string: "https://example.com/image.png")!)
}
Here are the steps to add the Kingfisher to your project:
Select File > Swift Packages > Add Package Dependency.
Enter https://github.com/onevcat/Kingfisher.git in the "Choose Package Repository" dialog.
In the next page, specify the version resolving rule as "Up to Next Major" with "5.14.0" as its earliest version.

Related

I have 2 errors Expected expression and Expected ')' in expression list as I am a beginner in swiftUI I cannot find the error

Hello I am following a swiftUI training on the udemy site to learn the basics today I am making a magazine application and I encounter an error Expected expression and the following Expected ')' in expression list being a beginner I don't know exactly how to solve it if you can tell me exactly why there is this error
I thank you
import SwiftUI
struct ContentView: View {
// MARK: - PROPERTY
#State private var isAnimating: Bool = false
#State private var imageScale: CGFloat = 1
#State private var imageOffset: CGSize = .zero
// MARK: - FUNCTION
func resetImageState() {
return withAnimation(.spring()) {
imageScale = 1
imageOffset = .zero
}
}
// MARK: - CONTENT
var body: some View {
NavigationView {
ZStack{
// MARK - PAGE IMAGE
Image("magazine-front-cover")
.resizable()
.aspectRatio(contentMode: .fit)
.cornerRadius(10)
.padding()
.shadow(color: .black.opacity(0.2), radius:12, x: 2, y: 2)
.opacity(isAnimating ? 1 : 0)
.offset(x: imageOffset.width, y: imageOffset.height) .scaleEffect(imageScale)
// MARK - 1 TAP Gesture
.onTapGesture(count: 2, perform: {
if imageScale == 1 {
withAnimation(.spring()) {
imageScale = 5
}
} else {
resetImageState()
}
})
// MARK - 2. DRAG GESTURE
.gesture(
DragGesture ()
.onChanged { value in
withAnimation(.linear(duration: 1)) {
imageOffset = value.translation
}
}
.onEnded { _ in
if imageScale <= 1 {
resetImageState()
}
}
)
} // ZSTACK
.navigationTitle("Pinch & Zoom")
.navigationBarTitleDisplayMode(.inline)
.onAppear(perform: {
withAnimation(.linear(duration: 1)) {
isAnimating = true
}
})
// MARK: - INFO PANEL
.overlay(
InfoPanel(scale: imageScale, offset: imageOffset)
.padding(.horizontal)
.padding(.top, -60)
, alignment: .top
)
// MARK: - CONTROLS
.overlay(
Group {
HStack {
}
.padding(.bottom, 30)
, alignment: .bottom
)
} //: NAVIGATION
.navigationViewStyle(.stack)
}
}
// MARK - PREVIEW
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.previewDevice("iPhone 13")
}
}
I don't know exactly how to fix the problem
You have a leftover Group { without closing curly brackets.
This part of your code:
// MARK: - CONTROLS
.overlay(
Group {
HStack {
}
.padding(.bottom, 30)
, alignment: .bottom
)
Should be:
// MARK: - CONTROLS
.overlay(
HStack {
}
.padding(.bottom, 30)
, alignment: .bottom
)

Tracking scroll position in a List SwiftUI

So in the past I have been tracking the scroll position using a scroll view but I've fallen into a situation where I need to track the position using a List. I am using a List because I want some of the built in real estate to create my views such as the default List styles.
I can get the value using PreferenceKeys, but the issue is when I scroll to far upwards, the PreferenceKey value will default back to its position 0, breaking my show shy header view logic.
This is the TrackableListView code
struct TrackableListView<Content: View>: View {
let offsetChanged: (CGPoint) -> Void
let content: Content
init(offsetChanged: #escaping (CGPoint) -> Void = { _ in }, #ViewBuilder content: () -> Content) {
self.offsetChanged = offsetChanged
self.content = content()
}
var body: some View {
List {
GeometryReader { geometry in
Color.clear.preference(key: ScrollOffsetPreferenceKey.self, value: geometry.frame(in: .named("ListView")).origin)
}
.frame(width: 0, height: 0)
content
.offset(y: -10)
}
.coordinateSpace(name: "ListView")
.onPreferenceChange(ScrollOffsetPreferenceKey.self, perform: offsetChanged)
}
}
private struct ScrollOffsetPreferenceKey: PreferenceKey {
static var defaultValue: CGPoint = .zero
static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) { }
}
And this is my ContentView:
struct ContentView: View {
#State private var contentOffset = CGFloat(0)
#State private var offsetPositionValue: CGFloat = 0
#State private var isShyHeaderVisible = false
var body: some View {
NavigationView {
ZStack {
TrackableListView { offset in
withAnimation {
contentOffset = offset.y
}
} content: {
Text("\(contentOffset)")
}
.overlay(
ZStack {
HStack {
Text("Total points")
.foregroundColor(.white)
.lineLimit(1)
Spacer()
Text("20,000 pts")
.foregroundColor(.white)
.padding(.leading, 50)
}
.padding(.horizontal)
.padding(.vertical, 8)
.frame(width: UIScreen.main.bounds.width)
.background(Color.green)
.offset(y: contentOffset < 50 ? 0 : -5)
.opacity(contentOffset < 50 ? 1 : 0)
.transition(.move(edge: .top))
}
.frame(maxHeight: .infinity, alignment: .top)
)
}
.navigationTitle("Hello")
.navigationViewStyle(StackNavigationViewStyle())
.navigationBarTitleDisplayMode(.inline)
.frame(maxHeight: .infinity, alignment: .top)
.background(AccountBackground())
}
}
}
The issue was that Other Views in my hierarchy (probably introduced by SwiftUI) could be sending the default value, which is why you start getting zero sometimes.
What I needed was a way to determine when to use or forward the new value, versus when to ignore it.
To do this I had to make my value optional GCPoint, with a nil default value, then in your reduce method when using PreferenceKeys you have to do:
if let nextValue = nextValue() {
value = nextValue
}
Then make sure your CGPoint is an optional value.

Compiler Error: Cannot find variable in scope Xcode Bug

I keep getting a compiler error that's not allowing my app to build.
Below is where I declared the variable showLogOutChoice.
struct HomeView: View {
#EnvironmentObject var userInfo: UserInfo
var showLogOutChoice = false
I then tried to use the value as a trigger for the actionsheet, and it's the compiler is throwing the error that it's not in scope.
.toolbar {
ToolbarItem(placement:.navigationBarLeading){
Button {
} label: {
VStack{
Image("CombIcon")
.resizable()
.frame(width: 40, height: 40)
Text("Menu")
}
}
}
ToolbarItem(placement:.navigationBarTrailing){
Button {
showLogOutChoice = true
} label: {
Text("Log Out ")
}
.confirmationDialog(Text:"Are You Sure You Want To Log Out?", isPresented: $showLogOutChoice , titleVisibility: .visible) {
FBAuth.logout(completion: <#T##(Result<Bool, Error>) -> Void#>)
}
}
}
}
}
The variable should still be in scope, and it's not having the same issue when I change the variable to true. So I'm confused. I tried cleaning the build folder and deleting the derived data but still nothing has changed any suggestions.
I'll copy the full file and leave it below as well for reference. PLEASE HELP!
struct HomeView: View {
#EnvironmentObject var userInfo: UserInfo
var showLogOutChoice = false
//TO DO connect picture to display if picture is not found display person fill
//TO DO add scroll view
var body: some View {
let screenSize: CGRect = UIScreen.main.bounds
let screenHeight = screenSize.height
let screenWidth = screenSize.width
NavigationView{
VStack{
VStack{
if (userInfo.user.profilePictureUrl == "")
{
Image( systemName: "person.fill")
.font(.system(size: 120))
.padding()
.foregroundColor(.black)
}
else{
WebImage(url: URL(string: userInfo.user.profilePictureUrl))
.resizable()
.scaledToFill()
.frame(width: 120, height: 120)
.clipped()
.cornerRadius(120)
}
}
.overlay(RoundedRectangle(cornerRadius: 120)
.stroke(Color.black, lineWidth: 1))
VStack{
Text("Hello \(userInfo.user.firstName)")
.font(.custom("coolvetica", size: 55))
}
VStack(alignment: .leading){
VStack(alignment:.leading){
Text("Your Upcoming Appointment")
.font(.custom("coolvetica", size: 30))
}
ZStack{
RoundedRectangle(cornerRadius: 13, style: .continuous)
.frame(width: screenWidth * 0.9, height: screenHeight * 0.1)
.foregroundColor(.white)
.shadow(color: Color.black.opacity(0.3), radius: 3, x: 0, y: 6)
Text("Holy Grail Appointment - Nov. 19th, 2021 8:00 AM")
.font(.custom("coolvetica", size: 18))
}.padding(.bottom)
HStack{
Button {
//TO DO book an appointment action
} label: {
Text("Book An Appointment")
.font(.custom("coolvetica", size: 20))
.frame(maxWidth: screenWidth * 0.8, minHeight: 20 )
.padding()
.foregroundColor(.white)
.background(Color("steelteal"))
.cornerRadius(42)
}
// Button {
// //TO DO reschedule an appointment action
// // may just make it able to only book an appointment for now
// } label: {
// Text("Reschedule Appointment")
// .font(.custom("coolvetica", size: 15))
// .padding()
// .foregroundColor(.white)
// .background(Color("steelteal"))
// .cornerRadius(42)
//
// }
}
VStack{
Text("My Hair Journey W/ Shei")
.font(.custom("coolvetica", size: 30))
}
HStack{
// need to create logic to save pictures and a note to a specific user
// create checkin page where pictures can be added the date and a note
// create display screen that will pop out with full information once photo is click
// if no checkins/updates are found then display text, no updates found would you like to add one with button
// allow shei to also add updates to individual users
Image( systemName: "person.fill")
.font(.system(size: 80))
.padding()
.foregroundColor(.black)
.overlay(RoundedRectangle(cornerRadius: 2)
.stroke(Color.black, lineWidth: 1))
Image( systemName: "person.fill")
.font(.system(size: 80))
.padding()
.foregroundColor(.black)
.overlay(RoundedRectangle(cornerRadius: 2)
.stroke(Color.black, lineWidth: 1))
Image( systemName: "person.fill")
.font(.system(size: 80))
.padding()
.foregroundColor(.black)
.overlay(RoundedRectangle(cornerRadius: 2)
.stroke(Color.black, lineWidth: 1))
}
}
}
.toolbar {
ToolbarItem(placement:.navigationBarLeading){
Button {
} label: {
VStack{
Image("CombIcon")
.resizable()
.frame(width: 40, height: 40)
Text("Menu")
}
}
}
ToolbarItem(placement:.navigationBarTrailing){
Button {
showLogOutChoice = true
} label: {
Text("Log Out ")
}
.confirmationDialog(Text:"Are You Sure You Want To Log Out?", isPresented: $showLogOutChoice , titleVisibility: .visible) {
FBAuth.logout(completion: <#T##(Result<Bool, Error>) -> Void#>)
}
}
}
}
}
}

Can't Animate or Transition SwiftUI Images in Sequence

I have an app with a view where I show images taken with the device's camera (stored
with Core Data) and I want to create the effect of time lapse - say you take photos
of a flower over a period of time and want to show those images in a stream. I have
been able to do that - but I want to have some transition effects between the images
and have not been able to do so. I can apply rotation and a static scale but cannot
fade from 0 to 1 opacity, nor scale up from zero to full frame. I must be missing
something really simple. Here's the code using an array of photos instead of Core Data
for simplicity.
struct ContentView: View {
#State private var activeImageIndex = 0
#State private var startTimer = false
#State private var myAnimationBool = true
let timer = Timer.publish(every: 1.0, on: .main, in: .default).autoconnect()
let myShots = ["CoolEquipment", "FishAndChipsMedium", "FlatheadLake1", "GlacierBusMedium", "Hike", "HuckALaHuckMedium", "JohnAndRiverMedium", "MacDonaldLodgeLakesideMedium"
]
var body: some View {
GeometryReader { geo in
VStack {
Text("Sequence")
.foregroundColor(.blue)
.font(.system(size: 25))
Image(self.myShots[self.activeImageIndex])
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: geo.size.width - 20, height: geo.size.width - 20, alignment: .center)
.cornerRadius(20)
.shadow(radius: 10, x: 10, y: 10)
//None of these do anything
//.animation(.easeInOut(duration: 0.5))
//.animation(.easeInOut)
//.transition(.opacity)
//.transition(self.myAnimationBool ? .opacity : .slide)
//.transition(.scale)
//.transition(AnyTransition.opacity.combined(with: .slide))
//this works but is static
//.scaleEffect(self.myAnimationBool ? 0.5 : 1.0)
//this works but again is static
//.rotationEffect(.degrees(self.myAnimationBool ? 90 : 0))
.onReceive(self.timer) { t in
print("in fixed timer")
if self.startTimer {
self.activeImageIndex = (self.activeImageIndex + 1) % self.myShots.count
}
}
HStack {
Button(action: {
self.startTimer.toggle()
}) {
ZStack {
RoundedRectangle(cornerRadius: 20)
.fill(Color.yellow)
.frame(width: 200, height: 40)
Text(self.startTimer ? "Stop" : "Start").font(.headline)
}
}
}
.padding()
}//top VStack
}.onDisappear{ self.startTimer = false }
}
}
Any guidance would be appreciated. Xcode 11.3 (11C29)

SwiftUI round button deforms when clicked

I have created a round button with following code:
struct RoundButton : View {
var value = "..."
var body: some View {
GeometryReader { geometry in
Button(action: {}) {
VStack {
Text(self.value)
.font(.headline)
.color(Color("NightlyDark"))
Text("MIN")
.font(.footnote)
.color(.white)
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
.clipShape(Circle())
}
}
}
But when clicking the button, the shape gets deformed. Any idea why this happens ?
Same happens when i use .mask(Circle())
Is this a beta thing or normal behavior ? And does anyone maybe know a better way to create rounded buttons ?
what happens here is Button Considers all screen[width + height] as their frame by default.
so you have to set Button also.
I think it's the default behavior in watchOS
Here Your Code :
struct RoundButton: View {
var value = "..."
var body: some View {
GeometryReader { geometry in
Button(action: {}) {
VStack {
Text(self.value)
.font(.headline)
.foregroundColor(Color("NightlyDark"))
Text("MIN")
.font(.footnote)
.foregroundColor(.white)
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
.frame(width: geometry.size.width, height: geometry.size.height)
.clipShape(Circle())
}
}
}
Note: i'm using Xcode 11 Beta 4

Resources