struct ImageTest: View {
@State private var selectedPhotos: [PhotosPickerItem] = []
@State private var photosData: [Data] = []
@State private var text: String = ""
var body: some View {
NavigationStack{
Form {
Section {
HStack {
PhotosPicker(selection: $selectedPhotos,
maxSelectionCount: 10,
matching: .images,
photoLibrary: .shared()) {
AddPhotoIcon(numOfImages: photosData.count)
}
.task(id: selectedPhotos) {
for selectedPhoto in selectedPhotos {
if let data = try? await selectedPhoto.loadTransferable(type: Data.self) {
self.photosData.append(data)
}
}
self.selectedPhotos = []
}
if !photosData.isEmpty {
ScrollView(.horizontal) {
HStack {
ForEach(photosData, id: \.self) { data in
if let image = UIImage(data: data) {
Image(uiImage: image)
.resizable()
.scaledToFill()
.frame(width: 50, height: 50)
}
}
}
}
}
Spacer()
}
}
Section {
TextField("Any", text: $text)
}
}
}
}
}
Here with SwiftData I'm making the model that contains images and title. There is a delay when entering just ten-character text after selecting photos for like 2~3 seconds. In the debug the memory usage it soars to 700MB. How can I improve it?
The delay and memory usage spike you're experiencing are likely due to the process of loading and displaying high-resolution images directly in the SwiftUI view. Each time you pick an image, it's being loaded in its original size which consumes a large amount of memory, especially if you are selecting multiple images. Moreover, the ForEach loop rebuilds each time photosData changes, which also could be causing a delay.
Before appending the image data to photosData, reduce the image resolution to a reasonable size that fits your UI. And load the images in a background thread to prevent UI freezing. In addition, use Lazy Loading: In SwiftUI, you can use LazyHStack instead of HStack to load the images lazily.
For example :
struct ImageTest: View {
@State private var selectedPhotos: [PhotosPickerItem] = []
@State private var photosData: [UIImage] = []
@State private var text: String = ""
var body: some View {
NavigationStack{
Form {
Section {
HStack {
PhotosPicker(selection: $selectedPhotos,
maxSelectionCount: 10,
matching: .images,
photoLibrary: .shared()) {
AddPhotoIcon(numOfImages: photosData.count)
}
.task(id: selectedPhotos) {
for selectedPhoto in selectedPhotos {
if let data = try? await selectedPhoto.loadTransferable(type: Data.self) {
if let image = UIImage(data: data) {
self.photosData.append(image.resized(to: CGSize(width: 50, height: 50))!)
}
}
}
self.selectedPhotos = []
}
if !photosData.isEmpty {
ScrollView(.horizontal) {
LazyHStack {
ForEach(photosData, id: \.self) { image in
Image(uiImage: image)
.resizable()
.scaledToFill()
.frame(width: 50, height: 50)
}
}
}
}
Spacer()
}
}
Section {
TextField("Any", text: $text)
}
}
}
}
}
extension UIImage {
func resized(to size: CGSize) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
self.draw(in: CGRect(origin: .zero, size: size))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
}