не удалось просмотреть изображение с помощью json url SwiftUI

#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 , если вы счастливы нацелиться на ios15

2. некоторые наблюдения; ваши данные json не похожи на ваш логин-ответ. Как только вы выясните, что возвращает api, вы извлекаете значение URL-адреса поля «banner_image» и делаете другой запрос на извлечение с этим URL-адресом, чтобы получить данные изображения. И как сказал @Paulw11, не используйте код, который у вас есть в расширении изображения

3. я решил это, спасибо всем