#ios #swiftui #carousel
Вопрос:
Я хочу просмотреть свое изображение URL-адреса Json в цикле foreach для карусели. но мой код работает с массивом изображений, который находится в моей системе. я не могу просмотреть изображение с URL-адреса json в SwiftUI, пожалуйста, укажите мне, где я ошибаюсь
вот моя модель просмотра……..
import Foundation
import SwiftUI
class BannerViewModel: ObservableObject{
@Published var banner = [Banner]()
let prefixUrl = "https://acubeappsdevelopment.com/Development/MysteryBox/MysteryBoxApis/"
init() {
fetchBanners()
}
func fetchBanners(){
guard let url = URL(string: "(prefixUrl)/signup") else {
print("not found url")
return
}
let body = "email=xyz@gmail.comamp;password=admin"
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.httpMethod = "POST"
request.httpBody = body.data(using: String.Encoding.utf8)!
URLSession.shared.dataTask(with: request){ (data, response, error) in
if error != nil{
print("error", error?.localizedDescription ?? "")
return
}
do{
if let data = data {
let result = try JSONDecoder().decode(LoginResponse.self, from: data)
DispatchQueue.main.async {
self.banner = result.banner
print("result of banner =>",result.banner)
}
}else{
print("no data")
}
}catch let JsonError{
print("fetch json error",JsonError.localizedDescription)
}
}.resume()
}
}
Вот мой баннер……
Здесь массив изображений работает с системными образами, но код не работает с изображением ответа json. я хочу просмотреть весь мой ответ json «banner_image»
import SwiftUI
struct PagingView<Content>: View where Content: View {
@Binding var index: Int
let maxIndex: Int
let content: () -> Content
@State private var offset = CGFloat.zero
@State private var dragging = false
init(index: Binding<Int>, maxIndex: Int, @ViewBuilder content: @escaping () -> Content) {
self._index = index
self.maxIndex = maxIndex
self.content = content
}
var body: some View {
ZStack(alignment: .bottomTrailing) {
GeometryReader { geometry in
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 0) {
self.content()
.frame(width: geometry.size.width, height: geometry.size.height)
.clipped()
}
}
.content.offset(x: self.offset(in: geometry), y: 0)
.frame(width: geometry.size.width, alignment: .leading)
.gesture(
DragGesture().onChanged { value in
self.dragging = true
self.offset = -CGFloat(self.index) * geometry.size.width value.translation.width
}
.onEnded { value in
let predictedEndOffset = -CGFloat(self.index) * geometry.size.width value.predictedEndTranslation.width
let predictedIndex = Int(round(predictedEndOffset / -geometry.size.width))
self.index = self.clampedIndex(from: predictedIndex)
withAnimation(.easeOut) {
self.dragging = false
}
}
)
}
.clipped()
PageControl(index: $index, maxIndex: maxIndex)
}
}
func offset(in geometry: GeometryProxy) -> CGFloat {
if self.dragging {
return max(min(self.offset, 0), -CGFloat(self.maxIndex) * geometry.size.width)
} else {
return -CGFloat(self.index) * geometry.size.width
}
}
func clampedIndex(from predictedIndex: Int) -> Int {
let newIndex = min(max(predictedIndex, self.index - 1), self.index 1)
guard newIndex >= 0 else { return 0 }
guard newIndex <= maxIndex else { return maxIndex }
return newIndex
}
}
struct PageControl: View {
@Binding var index: Int
let maxIndex: Int
var body: some View {
HStack(spacing: 8) {
ForEach(0...maxIndex, id: .self) { index in
Circle()
.fill(index == self.index ? Color.white : Color.gray)
.frame(width: 8, height: 8)
}
}
.padding()
}
}
struct BannerView: View {
@State var index = 0
@State var banners = [Banner]()
@ObservedObject var bannerViewModel = BannerViewModel()
var images = ["box_banner", "box_banner", "box_banner", "box_banner"]
// i want to preview image with url which is coming from json
// var images =
var body: some View {
VStack {
//this code is working with images array......
// PagingView(index: $index.animation(), maxIndex: images.count - 1) {
// ForEach(self.images, id: .self) { imageName in
// Image(imageName)
// .resizable()
// .scaledToFill()
// }
// }
//i want to preview all images which is coming from json.....
PagingView(index: $index.animation(), maxIndex: 5 - 1) {
ForEach(banners, id: .bannerID) { imageName in
Image(imageName.bannerImage)
.resizable()
.scaledToFill()
}
}
.aspectRatio(5/3, contentMode: .fit)
.clipShape(RoundedRectangle(cornerRadius: 15))
// .onAppear() {
// bannerViewModel.fetchBanners { (LoginResponse) in
// self.LoginResponse = LoginResponse
// }
// }
Image("app_icon")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300, height: 300, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
}
.padding()
}
}
struct BannerView_Previews: PreviewProvider {
static var previews: some View {
BannerView()
.environmentObject(BannerViewModel())
}
}
extension Image {
func data(url:URL) -> Self {
if let data = try? Data(contentsOf: url) {
return Image(uiImage: UIImage(data: data)!)
.resizable()
}
return self
.resizable()
}
}
````````
Here is my Json file
"Banner": [
{
"banner_id": "1",
"type": "0",
"banner_image": "https://acubeappsdevelopment.com/projects/MysteryBox/uploads/banner/box_banner.jpg",
"created_at": ""
},
{
"banner_id": "2",
"type": "0",
"banner_image": "https://acubeappsdevelopment.com/projects/MysteryBox/uploads/banner/box_banner.jpg",
"created_at": ""
}
]
Here is my ModelView
```````
import Foundation
import SwiftUI
import Combine
// MARK: - Welcome
struct LoginResponse: Codable {
let result: Result
let support: Support
let banner: [Banner]
let totalReward: TotalReward
let category: [Category]
let interest: [Interest]
let header: [Header]
let coupon: Coupon
enum CodingKeys: String, CodingKey {
case result
case support = "Support"
case banner = "Banner"
case totalReward = "Total_Reward"
case category = "Category"
case interest = "Interest"
case header = "Header"
case coupon = "Coupon"
}
}
// MARK: - Banner
struct Banner: Codable {
let bannerID, type: String
let bannerImage: String
let createdAt: String
enum CodingKeys: String, CodingKey {
case bannerID = "banner_id"
case type
case bannerImage = "banner_image"
case createdAt = "created_at"
}
}
// MARK: - Category
struct Category: Codable {
let categoryID, categoryName, createdAt: String
enum CodingKeys: String, CodingKey {
case categoryID = "category_id"
case categoryName = "category_name"
case createdAt = "created_at"
}
}
// MARK: - Coupon
struct Coupon: Codable {
let couponName, couponPoint: String
enum CodingKeys: String, CodingKey {
case couponName = "coupon_name"
case couponPoint = "coupon_point"
}
}
// MARK: - Header
struct Header: Codable {
let headerID, headerTitle, userID, createdAt: String
let name: String
let image: String
enum CodingKeys: String, CodingKey {
case headerID = "header_id"
case headerTitle = "header_title"
case userID = "user_id"
case createdAt = "created_at"
case name, image
}
}
// MARK: - Interest
struct Interest: Codable {
let interestID, interestName: String
enum CodingKeys: String, CodingKey {
case interestID = "interest_id"
case interestName = "interest_name"
}
}
// MARK: - Result
struct Result: Codable {
let message, status, userID, email: String
let phone, countryCode, name, coupon: String
let age, gender: String
let token: JSONNull?
enum CodingKeys: String, CodingKey {
case message = "MESSAGE"
case status = "STATUS"
case userID = "user_id"
case email, phone, countryCode, name, coupon, age, gender, token
}
}
// MARK: - Support
struct Support: Codable {
let privacyPolicy, termsAndCondition, supportMail, contactNumber: String
enum CodingKeys: String, CodingKey {
case privacyPolicy = "Privacy_policy"
case termsAndCondition = "Terms_and_condition"
case supportMail = "Support_mail"
case contactNumber = "contact_number"
}
}
// MARK: - TotalReward
struct TotalReward: Codable {
let rewardPoint: String?
enum CodingKeys: String, CodingKey {
case rewardPoint = "Reward_Point"
}
}
// MARK: - Encode/decode helpers
class JSONNull: Codable, Hashable {
public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool {
return true
}
public var hashValue: Int {
return 0
}
public init() {}
public required init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if !container.decodeNil() {
throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encodeNil()
}
}
````````
Комментарии:
1. На самом деле вы нигде не извлекаете данные изображения. Кроме того, вы не должны использовать
Data(contentsOf:)
для извлечения данных из сети — это явно указано в документации. Вы можете использоватьasyncImage
, если вы счастливы нацелиться на ios152. некоторые наблюдения; ваши данные json не похожи на ваш логин-ответ. Как только вы выясните, что возвращает api, вы извлекаете значение URL-адреса поля «banner_image» и делаете другой запрос на извлечение с этим URL-адресом, чтобы получить данные изображения. И как сказал @Paulw11, не используйте код, который у вас есть в расширении изображения
3. я решил это, спасибо всем