#swiftui #kingfisher
Вопрос:
В настоящее время я разрабатываю приложение, использующее SwiftUI
и пытающееся создать представление жестов панорамирования.
Я использую Kingfisher
для отображения нескольких изображений в жесте панорамирования.
Когда я открываю Hstack
вид, отображается первое изображение в нескольких видах карт, но последующие изображения не отображаются при пролистывании. Первое изображение, которое было отображено, также исчезает.
Как я мог бы решить эту проблему?
Вот коды:
Мучения.быстро
import SwiftUI
import Kingfisher
import FirebaseStorage
struct PanListView: View {
@ObservedObject var viewModel:ViewModel
var body: some View {
NavigationView{
VStack{
List(self.viewModel.posts.indices, id: .self){index in
ZStack{
Button(action: {
viewModel.selectedDetailIndex = Double(index)
let postCountDevided2:Double = Double(viewModel.posts.count) / 2
viewModel.initialIndex = (postCountDevided2 - 0.5) - viewModel.selectedDetailIndex
self.viewModel.initialX = CGFloat((Double(UIScreen.main.bounds.width) - 15) * self.viewModel.initialIndex)
self.viewModel.x = self.viewModel.initialX
if ((viewModel.posts.count % 2) == 0){
self.viewModel.swipePostsCount = CGFloat(viewModel.initialIndex 0.5)
}else{
self.viewModel.swipePostsCount = CGFloat(viewModel.initialIndex)
}
self.viewModel.detailShowArray[Int(viewModel.selectedDetailIndex)] = true
}, label: {
Text(self.viewModel.posts[index].word)
})
NavigationLink(
destination: PanSwipeView(
viewModel: viewModel, posts: self.viewModel.posts
)
){
EmptyView()
}.frame(width:0).opacity(0)
}
}
}
.navigationBarTitle("ListView",displayMode: .inline)
}
.navigationViewStyle(StackNavigationViewStyle())
.onAppear(){
self.viewModel.getAllPosts(){(status) in
for _ in 0..<self.viewModel.posts.count{
self.viewModel.detailShowArray.append(false)
}
}
}
}
}
struct PanSwipeView: View {
@ObservedObject var viewModel:ViewModel
@State var posts:[Post]
@State var screen = UIScreen.main.bounds.width - 30
var body: some View {
HStack(spacing:15){
Spacer()
ForEach(self.posts.indices, id: .self){ index in
PanDetailCard(
viewModel: viewModel,
index: index,
imageURL: posts[index].image_url ?? "",
word:posts[index].word
)
.offset(x:self.viewModel.x)
.highPriorityGesture(DragGesture(minimumDistance: 20)
.onChanged({(value) in
if value.translation.width > 0{
self.viewModel.x = value.location.x
}else {
self.viewModel.x = value.location.x - self.screen
}
})
.onEnded({(value) in
if value.translation.width > 0{
if value.translation.width > ((self.viewModel.swipePostsCount - 80) / 2) amp;amp; Int(viewModel.swipePostsCount) != self.getMid(){
self.viewModel.swipePostsCount = 1
self.updateHeight(value: Int(viewModel.swipePostsCount))
if ((posts.count % 2) == 0){
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount - 0.5)
}else{
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount)
}
}else{
if ((posts.count % 2) == 0){
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount - 0.5)
}else{
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount)
} }
}else{
if ((posts.count % 2) == 0){
if -value.translation.width > ((self.viewModel.swipePostsCount - 80) / 2) amp;amp; -Int(viewModel.swipePostsCount) != self.getMid() - 1{
self.viewModel.swipePostsCount -= 1
self.updateHeight(value: Int(viewModel.swipePostsCount))
if ((posts.count % 2) == 0){
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount - 0.5)
}else{
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount)
}
}else{
if ((posts.count % 2) == 0){
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount - 0.5)
}else{
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount)
}
}
}else{
if -value.translation.width > ((self.viewModel.swipePostsCount - 80) / 2) amp;amp; -Int(viewModel.swipePostsCount) != self.getMid(){
self.viewModel.swipePostsCount -= 1
self.updateHeight(value: Int(viewModel.swipePostsCount))
if ((posts.count % 2) == 0){
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount - 0.5)
}else{
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount)
}
}else{
if ((posts.count % 2) == 0){
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount - 0.5)
}else{
self.viewModel.x = (self.screen 15 ) * (self.viewModel.swipePostsCount)
}
}
}
}
})
)
}
Spacer()
}
.frame(width: UIScreen.main.bounds.width,height: UIScreen.main.bounds.height)
.background(Color.black.opacity(0.2))
.animation(.spring())
.navigationBarTitle("Detail",displayMode: .inline)
}
func getMid() -> Int{
return viewModel.posts.count / 2
}
func updateHeight(value:Int){
var id : Int
if value < 0 {
id = -value getMid()
}else{
id = getMid() - value
}
for i in 0..<viewModel.posts.count{
self.viewModel.detailShowArray[i] = false
}
self.viewModel.detailShowArray[id] = true
}
}
struct PanDetailCard: View {
@ObservedObject var viewModel:ViewModel
@State var screen = UIScreen.main.bounds.width - 30
@State var url:String = ""
var index:Int
var imageURL:String
var word:String
var body: some View {
ScrollView{
Group{
HStack{
Text("Test")
Spacer()
}
HStack{
Spacer()
Text(Date(),style: .date)
.font(.footnote)
.foregroundColor(.secondary)
}
HStack{
Button(action: {
}, label: {
HStack{
Image(systemName: "person.circle")
.foregroundColor(Color.black)
Text("user_name")
.foregroundColor(Color.black)
}
})
Spacer()
}
}
Group{
KFImage(URL(string: URL))
.cancelOnDisappear(true)
.resizable()
.scaledToFit()
.frame(width: ScreenSize.screenWidth * 0.8, height: ScreenSize.screenWidth * 0.8)
Text("test")
.font(.title2)
.fontWeight(.bold)
VStack(alignment: .leading){
Text("test")
.fontWeight(.bold)
.foregroundColor(Color.black)
Text(word)
.font(.title)
.fontWeight(.bold)
.foregroundColor(.blue)
Text("test")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(Color.black)
}
Divider()
VStack(alignment: .leading){
Text("sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample,sample")
.foregroundColor(Color.black)
}
}
}
.frame(width: UIScreen.main.bounds.width - 30, height: viewModel.detailShowArray[index] ? (UIScreen.main.bounds.height * 0.7) 60 : (UIScreen.main.bounds.height * 0.7) )
.background(Color.white)
.cornerRadius(10)
.onAppear(){
if imageURL != "" {
let storage = Storage.storage().reference()
storage.child(imageURL).downloadURL(completion: {(url,err) in
if err != nil{
print((err?.localizedDescription)!)
return
}
self.url = "(url!)"
})
}
}
}
}
ViewModel.swift
import Foundation
import SwiftUI
import Firebase
class ViewModel: ObservableObject {
func getAllPosts(completion:@escaping(Bool) -> ()){
ref.collection("Posts").getDocuments{
(snap, err) in
guard let docs = snap else{
completion(false)
return
}
self.posts = []
docs.documentChanges.forEach{ (doc) in
let post = try! doc.document.data(as:Post.self)
self.posts.append(post!)
}
completion(true)
}
}
}
Model.swift
import Foundation
import Firebase
import FirebaseFirestore
import FirebaseFirestoreSwift
struct Post : Identifiable,Codable {
@DocumentID var id : String?
var image_url : String?
var word : String
enum CodingKeys : String,CodingKey {
case id
case image_url
case word
}
}
Xcode: Версия 12.3
iOS: 14.0
Зимородок: 6.2.1