AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79576321
Accepted
user30115770
user30115770
Asked: 2025-04-16 10:55:58 +0800 CST2025-04-16 10:55:58 +0800 CST 2025-04-16 10:55:58 +0800 CST

Como salvar imagens de um Photo Picker no SwiftData

  • 772

Estou tendo problemas para salvar imagens no SwiftData e não tenho certeza da melhor maneira de fazer isso.

Tenho um modelo de dados EntryModel para uma entrada individual como tal:

@Model
class EntryModel {
   var type: EntryType
   var who: UserModel
   var what: String
   var value: Double? = nil
   var note: String
   @Attribute(.externalStorage) var images: [Data]?
   var when: Date = Date.now

  init(type: EntryType, who: UserModel, what: String, note: String, images: [Data] = [], when: Date) {
    self.type = type
    self.who = who
    self.what = what
    self.note = note
    self.images = images
    self.when = when
}

Em seguida, tenho uma NewEntryView que permite aos usuários criar uma nova entrada e anexar algumas imagens opcionais para obter informações adicionais. O código fica assim:

struct New EntryView {
   @State private var entryItems = [PhotosPickerItem]()
   @State private var entryImages = [Image]()

// Other code pertaining to different parts of my form

HStack {
    PhotosPicker(selection: $entryItems, maxSelectionCount: 5, matching: .images) {
        Image(systemName: "plus")
          .font(.title)
          .foregroundStyle(.adaptiveBlack)
          .frame(width: 80, height: 70)
          .background(
              RoundedRectangle(cornerRadius: 10)
                 .stroke(lineWidth: 2)
                 .fill(selectedEntryType.color)
                 .frame(width: 70, height: 60)
           )
       }
                        
       ScrollView(.horizontal) {
          HStack(spacing: 10) {
             ForEach(0..<entryImages.count, id: \.self) { i in
                entryImages[i]
                    .resizable()
                    .scaledToFill()
                    .clipShape(RoundedRectangle(cornerRadius: 10))
                    .frame(height: 60)
             }
          }
          .onChange(of: entryItems) {
             Task {
                entryImages.removeAll()
                                    
                for item in entryItems {
                   if let image = try? await item.loadTransferable(type: Image.self) {
                   entryImages.append(image)
                }
            }
        }
   }

// More code

Button {
   let entry = EntryModel(type: selectedEntryType, who: selectedUser!, what: titleTextField, note: noteTextField, when: selectedDate)
   modelContext.insert(entry)
} label: {
// Custom label
}

Agora, com esta implementação atual, posso de fato selecionar imagens do meu álbum de fotos e preenchê-las no HStack.

Quando o botão é clicado na parte inferior, as outras informações preenchidas pelo usuário também são salvas no SwiftData e podem ser usadas em todo o aplicativo.

O problema que tenho é salvar essas imagens no SwiftData para serem usadas em todo o aplicativo.

Devo inseri-los no contexto do modelo como faço com os outros valores? Se sim, como?

Caso contrário, como eu alteraria meu código atual?

Qualquer ajuda será apreciada.

Aliás, não tenho certeza da sua relevância, mas desde que implementei o PhotosPicker, recebo o seguinte aviso no Xcode:

PHPickerViewControllerDelegate_Private não responde a _pickerDidPerformConfirmationAction:

swiftui
  • 1 1 respostas
  • 44 Views

1 respostas

  • Voted
  1. Best Answer
    workingdog support Ukraine
    2025-04-16T13:48:19+08:002025-04-16T13:48:19+08:00

    Como já mostrei na minha resposta anterior à sua pergunta, use outro modelo para os dados das imagens, com um relacionamento com o EntryModel.

    Aqui está um código de exemplo totalmente funcional:

    
    @main
    struct TestApp: App {
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
            .modelContainer(for: EntryModel.self)
        }
    }
    
    @Model class UserModel {
        var name: String
        var age: Int
        
        init(name: String, age: Int) {
            self.name = name
            self.age = age
        }
    }
    
    @Model class ImageData {
        @Attribute(.externalStorage)
        var data: Data
        var entry: EntryModel?
    
        init(data: Data) {
            self.data = data
        }
    }
    
    @Model class EntryModel {
        var type: String
        var who: UserModel
        var what: String
        var value: Double? = nil
        var note: String
        var when: Date = Date.now
    
        @Relationship(deleteRule: .cascade, inverse: \ImageData.entry) var images: [ImageData]?
    
        init(type: String, who: UserModel, what: String, value: Double? = nil, note: String, images: [ImageData]? = nil, when: Date) {
            self.type = type
            self.who = who
            self.what = what
            self.value = value
            self.note = note
            self.images = images
            self.when = when
        }
    }
    
    struct ContentView: View {
        @Environment(\.modelContext) private var modelContext  // <--- here
        
        @State private var entryItems = [PhotosPickerItem]()
        @State private var entryImages = [Image]()
        
        @State private var imagesData = [ImageData]()  // <--- here
        
        var body: some View {
            VStack {
                Text("Select images first").font(.title)
                PhotosPicker(selection: $entryItems, maxSelectionCount: 5, matching: .images) {
                    Image(systemName: "plus")
                        .font(.title)
                        .foregroundStyle(.secondary)
                        .frame(width: 80, height: 70)
                    
                    ScrollView(.horizontal) {
                        HStack(spacing: 10) {
                            ForEach(0..<entryImages.count, id: \.self) { i in
                                entryImages[i]
                                    .resizable()
                                    .scaledToFit()
                                    .clipShape(RoundedRectangle(cornerRadius: 10))
                                    .frame(height: 60)
                            }
                        }
                        .onChange(of: entryItems) {
                            // --- here
                            Task { @MainActor in
                                entryImages.removeAll()
                                for item in entryItems {
                                    if let imageData = try? await item.loadTransferable(type: Data.self) {
                                        imagesData.append(ImageData(data: imageData))
                                        if let uiImage = UIImage(data: imageData) { entryImages.append(Image(uiImage: uiImage))
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                
                // example code
                Button("Save Images to SwiftData") {
                    let entryModel = EntryModel(type: "type",
                                                who: UserModel(name: "test-user", age: 32),
                                                what: "what",
                                                note: "note",
                                                images: imagesData, // <--- here
                                                when: Date())
                    modelContext.insert(entryModel)  // <--- here
                }.buttonStyle(.bordered)
                
                Text("Images from SwiftData")
                ImagesView()
            }
        }
    }
    
    // example code to display the saved images
    struct ImagesView: View {
        @Environment(\.modelContext) private var modelContext
        @Query private var entries: [EntryModel]
        
        var body: some View {
            ForEach(entries) { entry in
                ScrollView (.horizontal) {
                    HStack {
                        if let imagesData = entry.images {
                            ForEach(imagesData) { imgData in
                                if let uimg = UIImage(data: imgData.data) {
                                    Image(uiImage: uimg).resizable()
                                        .frame(width: 123, height: 123)
                                }
                            }
                        }
                    }
                }
            }.padding()
        }
    }
    
    
    • 0

relate perguntas

  • SwiftUI: Como criar um gradiente com um tom mais claro?

  • SwiftUI - visão comum com variável "binding"

  • Criando uma visualização do dia do calendário

  • Como deixar a animação mais lenta SwiftUI

  • Não entendo o layout de texto do SwiftUI

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve